WIP: Automatically create node layout, keys and buckets #883

Draft
apapsch wants to merge 6 commits from apapsch/garage:feature/auto-config into main
3 changed files with 60 additions and 5 deletions
Showing only changes of commit 7af19649bb - Show all commits

View file

@ -1,8 +1,5 @@
use crate::admin::AdminRpc; use crate::admin::AdminRpc;
use crate::cli::{ use crate::cli::{cmd_apply_layout, cmd_assign_role, fetch_layout, fetch_status, ApplyLayoutOpt, AssignRoleOpt, BucketOperation, BucketOpt, KeyImportOpt, KeyInfoOpt, KeyOperation, PermBucketOpt, WebsiteOpt};
cmd_apply_layout, cmd_assign_role, fetch_layout, fetch_status, ApplyLayoutOpt, AssignRoleOpt,
BucketOperation, BucketOpt, KeyImportOpt, KeyInfoOpt, KeyOperation, PermBucketOpt,
};
use bytesize::ByteSize; use bytesize::ByteSize;
use garage_model::helper::error::Error as HelperError; use garage_model::helper::error::Error as HelperError;
use garage_net::endpoint::Endpoint; use garage_net::endpoint::Endpoint;
@ -10,7 +7,7 @@ use garage_net::message::PRIO_NORMAL;
use garage_net::NodeID; use garage_net::NodeID;
use garage_rpc::layout::NodeRoleV; use garage_rpc::layout::NodeRoleV;
use garage_rpc::system::SystemRpc; use garage_rpc::system::SystemRpc;
use garage_util::config::{AutoBucket, AutoKey, AutoNode, AutoPermission}; use garage_util::config::{AutoBucket, AutoBucketWebsite, AutoKey, AutoNode, AutoPermission, WebsiteAllowance};
use garage_util::data::Uuid; use garage_util::data::Uuid;
use garage_util::error::Error; use garage_util::error::Error;
@ -100,6 +97,32 @@ pub async fn bucket_create(
} }
} }
pub async fn bucket_configure_website(
rpc_cli: &Endpoint<AdminRpc, ()>,
rpc_host: NodeID,
bucket_name: String,
website: &AutoBucketWebsite,
) -> Result<(), Error> {
match rpc_cli
.call(
&rpc_host,
AdminRpc::BucketOperation(BucketOperation::Website(WebsiteOpt{
allow: matches!(website.mode, WebsiteAllowance::Allow),
deny: matches!(website.mode, WebsiteAllowance::Deny),
bucket: bucket_name.clone(),
index_document: website.index_document.clone(),
error_document: website.error_document.clone(),
})),
PRIO_NORMAL,
)
.await?
{
Ok(_) => Ok(()),
Err(HelperError::BadRequest(msg)) => Err(Error::Message(msg)),
resp => Err(Error::unexpected_rpc_message(resp)),
}
}
pub async fn grant_permission( pub async fn grant_permission(
rpc_cli: &Endpoint<AdminRpc, ()>, rpc_cli: &Endpoint<AdminRpc, ()>,
rpc_host: NodeID, rpc_host: NodeID,

View file

@ -309,6 +309,11 @@ pub async fn cmd_auto(
for perm in bucket.allow.iter() { for perm in bucket.allow.iter() {
grant_permission(rpc_admin, rpc_host, bucket.name.clone(), perm).await?; grant_permission(rpc_admin, rpc_host, bucket.name.clone(), perm).await?;
} }
// Configure website access.
if let Some(website) = bucket.website.as_ref() {
bucket_configure_website(rpc_admin, rpc_host, bucket.name.clone(), website).await?
}
} }
} }
_ => { _ => {

View file

@ -232,6 +232,33 @@ pub struct AutoBucket {
pub name: String, pub name: String,
/// Permissions to grant on bucket to given keys /// Permissions to grant on bucket to given keys
pub allow: Vec<AutoPermission>, pub allow: Vec<AutoPermission>,
/// Website configuration
pub website: Option<AutoBucketWebsite>
}
fn default_index_document() -> String {
"index.html".to_string()
}
/// Bucket website configuration to create automatically
#[derive(Deserialize, Debug, Clone, Default)]
pub struct AutoBucketWebsite {
/// Allow or deny (default) website access
#[serde(default)]
pub mode: WebsiteAllowance,
/// Error document: the optional document returned when an error occurs
pub error_document: Option<String>,
/// Index document: the suffix appended to request paths ending by /
#[serde(default = "default_index_document")]
pub index_document: String,
}
#[derive(Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "lowercase")]
pub enum WebsiteAllowance {
Allow,
#[default]
Deny,
} }
/// Permission to create automatically /// Permission to create automatically