diff options
author | Alex <lx@deuxfleurs.fr> | 2025-01-30 16:18:38 +0000 |
---|---|---|
committer | Alex <lx@deuxfleurs.fr> | 2025-01-30 16:18:38 +0000 |
commit | 3192088aac0e1795401304a8dec715cd343538cf (patch) | |
tree | bfea9c13130481a3463f8bba2c2fe85fe3be6cd4 /src/api | |
parent | 6ed78abb5cd09f4e5ca5effe5d6137faf33133f8 (diff) | |
parent | 5a89350b382f9a24d4e81b056f88dc16a5daa080 (diff) | |
download | garage-3192088aac0e1795401304a8dec715cd343538cf.tar.gz garage-3192088aac0e1795401304a8dec715cd343538cf.zip |
Merge pull request 'admin refactoring: refactor CLI to use Admin API requests (step 2)' (#943) from refactor-admin into next-v2
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/943
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/admin/api.rs | 136 | ||||
-rw-r--r-- | src/api/admin/bucket.rs | 14 | ||||
-rw-r--r-- | src/api/admin/error.rs | 2 | ||||
-rw-r--r-- | src/api/admin/macros.rs | 26 | ||||
-rw-r--r-- | src/api/admin/router_v2.rs | 3 |
5 files changed, 104 insertions, 77 deletions
diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs index 39e05d51..21133f10 100644 --- a/src/api/admin/api.rs +++ b/src/api/admin/api.rs @@ -1,3 +1,4 @@ +use std::convert::TryFrom; use std::net::SocketAddr; use std::sync::Arc; @@ -77,18 +78,18 @@ admin_endpoints![ // because they directly produce an http::Response // ********************************************** -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct OptionsRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CheckDomainRequest { pub domain: String, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct HealthRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct MetricsRequest; // ********************************************** @@ -97,10 +98,10 @@ pub struct MetricsRequest; // ---- GetClusterStatus ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetClusterStatusRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetClusterStatusResponse { pub node: String, @@ -112,7 +113,7 @@ pub struct GetClusterStatusResponse { pub nodes: Vec<NodeResp>, } -#[derive(Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct NodeResp { pub id: String, @@ -128,7 +129,7 @@ pub struct NodeResp { pub metadata_partition: Option<FreeSpaceResp>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NodeRoleResp { pub id: String, @@ -137,7 +138,7 @@ pub struct NodeRoleResp { pub tags: Vec<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FreeSpaceResp { pub available: u64, @@ -146,7 +147,7 @@ pub struct FreeSpaceResp { // ---- GetClusterHealth ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetClusterHealthRequest; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -167,10 +168,10 @@ pub struct GetClusterHealthResponse { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConnectClusterNodesRequest(pub Vec<String>); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConnectClusterNodesResponse(pub Vec<ConnectNodeResponse>); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ConnectNodeResponse { pub success: bool, @@ -179,10 +180,10 @@ pub struct ConnectNodeResponse { // ---- GetClusterLayout ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetClusterLayoutRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetClusterLayoutResponse { pub version: u64, @@ -190,7 +191,7 @@ pub struct GetClusterLayoutResponse { pub staged_role_changes: Vec<NodeRoleChange>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NodeRoleChange { pub id: String, @@ -198,7 +199,7 @@ pub struct NodeRoleChange { pub action: NodeRoleChangeEnum, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum NodeRoleChangeEnum { #[serde(rename_all = "camelCase")] @@ -213,21 +214,21 @@ pub enum NodeRoleChangeEnum { // ---- UpdateClusterLayout ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateClusterLayoutRequest(pub Vec<NodeRoleChange>); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateClusterLayoutResponse(pub GetClusterLayoutResponse); // ---- ApplyClusterLayout ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApplyClusterLayoutRequest { pub version: u64, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApplyClusterLayoutResponse { pub message: Vec<String>, @@ -236,10 +237,10 @@ pub struct ApplyClusterLayoutResponse { // ---- RevertClusterLayout ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct RevertClusterLayoutRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse); // ********************************************** @@ -248,13 +249,13 @@ pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse); // ---- ListKeys ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ListKeysRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ListKeysResponse(pub Vec<ListKeysResponseItem>); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ListKeysResponseItem { pub id: String, @@ -263,14 +264,14 @@ pub struct ListKeysResponseItem { // ---- GetKeyInfo ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetKeyInfoRequest { pub id: Option<String>, pub search: Option<String>, pub show_secret_key: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetKeyInfoResponse { pub name: String, @@ -281,14 +282,14 @@ pub struct GetKeyInfoResponse { pub buckets: Vec<KeyInfoBucketResponse>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct KeyPerm { #[serde(default)] pub create_bucket: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct KeyInfoBucketResponse { pub id: String, @@ -297,7 +298,7 @@ pub struct KeyInfoBucketResponse { pub permissions: ApiBucketKeyPerm, } -#[derive(Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct ApiBucketKeyPerm { #[serde(default)] @@ -310,18 +311,18 @@ pub struct ApiBucketKeyPerm { // ---- CreateKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateKeyRequest { pub name: Option<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateKeyResponse(pub GetKeyInfoResponse); // ---- ImportKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ImportKeyRequest { pub access_key_id: String, @@ -329,21 +330,21 @@ pub struct ImportKeyRequest { pub name: Option<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ImportKeyResponse(pub GetKeyInfoResponse); // ---- UpdateKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateKeyRequest { pub id: String, pub body: UpdateKeyRequestBody, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateKeyResponse(pub GetKeyInfoResponse); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateKeyRequestBody { pub name: Option<String>, @@ -353,12 +354,12 @@ pub struct UpdateKeyRequestBody { // ---- DeleteKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeleteKeyRequest { pub id: String, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeleteKeyResponse; // ********************************************** @@ -367,13 +368,13 @@ pub struct DeleteKeyResponse; // ---- ListBuckets ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ListBucketsRequest; -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ListBucketsResponseItem { pub id: String, @@ -381,7 +382,7 @@ pub struct ListBucketsResponseItem { pub local_aliases: Vec<BucketLocalAlias>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BucketLocalAlias { pub access_key_id: String, @@ -390,13 +391,14 @@ pub struct BucketLocalAlias { // ---- GetBucketInfo ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetBucketInfoRequest { pub id: Option<String>, pub global_alias: Option<String>, + pub search: Option<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBucketInfoResponse { pub id: String, @@ -414,14 +416,14 @@ pub struct GetBucketInfoResponse { pub quotas: ApiBucketQuotas, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBucketInfoWebsiteResponse { pub index_document: String, pub error_document: Option<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBucketInfoKey { pub access_key_id: String, @@ -430,7 +432,7 @@ pub struct GetBucketInfoKey { pub bucket_local_aliases: Vec<String>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApiBucketQuotas { pub max_size: Option<u64>, @@ -439,17 +441,17 @@ pub struct ApiBucketQuotas { // ---- CreateBucket ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateBucketRequest { pub global_alias: Option<String>, pub local_alias: Option<CreateBucketLocalAlias>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateBucketResponse(pub GetBucketInfoResponse); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateBucketLocalAlias { pub access_key_id: String, @@ -460,23 +462,23 @@ pub struct CreateBucketLocalAlias { // ---- UpdateBucket ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateBucketRequest { pub id: String, pub body: UpdateBucketRequestBody, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateBucketResponse(pub GetBucketInfoResponse); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateBucketRequestBody { pub website_access: Option<UpdateBucketWebsiteAccess>, pub quotas: Option<ApiBucketQuotas>, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateBucketWebsiteAccess { pub enabled: bool, @@ -486,12 +488,12 @@ pub struct UpdateBucketWebsiteAccess { // ---- DeleteBucket ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeleteBucketRequest { pub id: String, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeleteBucketResponse; // ********************************************** @@ -500,13 +502,13 @@ pub struct DeleteBucketResponse; // ---- AllowBucketKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct AllowBucketKeyRequest(pub BucketKeyPermChangeRequest); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct AllowBucketKeyResponse(pub GetBucketInfoResponse); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BucketKeyPermChangeRequest { pub bucket_id: String, @@ -516,10 +518,10 @@ pub struct BucketKeyPermChangeRequest { // ---- DenyBucketKey ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DenyBucketKeyRequest(pub BucketKeyPermChangeRequest); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse); // ********************************************** @@ -528,7 +530,7 @@ pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse); // ---- AddBucketAlias ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AddBucketAliasRequest { pub bucket_id: String, @@ -536,10 +538,10 @@ pub struct AddBucketAliasRequest { pub alias: BucketAliasEnum, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct AddBucketAliasResponse(pub GetBucketInfoResponse); -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum BucketAliasEnum { #[serde(rename_all = "camelCase")] @@ -553,7 +555,7 @@ pub enum BucketAliasEnum { // ---- RemoveBucketAlias ---- -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RemoveBucketAliasRequest { pub bucket_id: String, @@ -561,5 +563,5 @@ pub struct RemoveBucketAliasRequest { pub alias: BucketAliasEnum, } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse); diff --git a/src/api/admin/bucket.rs b/src/api/admin/bucket.rs index 0cc420ec..d2d75fc0 100644 --- a/src/api/admin/bucket.rs +++ b/src/api/admin/bucket.rs @@ -73,16 +73,22 @@ impl EndpointHandler for GetBucketInfoRequest { type Response = GetBucketInfoResponse; async fn handle(self, garage: &Arc<Garage>) -> Result<GetBucketInfoResponse, Error> { - let bucket_id = match (self.id, self.global_alias) { - (Some(id), None) => parse_bucket_id(&id)?, - (None, Some(ga)) => garage + let bucket_id = match (self.id, self.global_alias, self.search) { + (Some(id), None, None) => parse_bucket_id(&id)?, + (None, Some(ga), None) => garage .bucket_helper() .resolve_global_bucket_name(&ga) .await? .ok_or_else(|| HelperError::NoSuchBucket(ga.to_string()))?, + (None, None, Some(search)) => { + garage + .bucket_helper() + .admin_get_existing_matching_bucket(&search) + .await? + } _ => { return Err(Error::bad_request( - "Either id or globalAlias must be provided (but not both)", + "Either id, globalAlias or search must be provided (but not several of them)", )); } }; diff --git a/src/api/admin/error.rs b/src/api/admin/error.rs index 40d686e3..205fc314 100644 --- a/src/api/admin/error.rs +++ b/src/api/admin/error.rs @@ -56,7 +56,7 @@ impl From<HelperError> for Error { impl CommonErrorDerivative for Error {} impl Error { - fn code(&self) -> &'static str { + pub fn code(&self) -> &'static str { match self { Error::Common(c) => c.aws_code(), Error::NoSuchAccessKey(_) => "NoSuchAccessKey", diff --git a/src/api/admin/macros.rs b/src/api/admin/macros.rs index 7082577f..9521616e 100644 --- a/src/api/admin/macros.rs +++ b/src/api/admin/macros.rs @@ -4,7 +4,7 @@ macro_rules! admin_endpoints { $($endpoint:ident,)* ] => { paste! { - #[derive(Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum AdminApiRequest { $( $special_endpoint( [<$special_endpoint Request>] ), @@ -14,7 +14,7 @@ macro_rules! admin_endpoints { )* } - #[derive(Serialize)] + #[derive(Debug, Clone, Serialize)] #[serde(untagged)] pub enum AdminApiResponse { $( @@ -22,7 +22,7 @@ macro_rules! admin_endpoints { )* } - #[derive(Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum TaggedAdminApiResponse { $( $endpoint( [<$endpoint Response>] ), @@ -43,7 +43,7 @@ macro_rules! admin_endpoints { } impl AdminApiResponse { - fn tagged(self) -> TaggedAdminApiResponse { + pub fn tagged(self) -> TaggedAdminApiResponse { match self { $( Self::$endpoint(res) => TaggedAdminApiResponse::$endpoint(res), @@ -52,6 +52,24 @@ macro_rules! admin_endpoints { } } + $( + impl From< [< $endpoint Request >] > for AdminApiRequest { + fn from(req: [< $endpoint Request >]) -> AdminApiRequest { + AdminApiRequest::$endpoint(req) + } + } + + impl TryFrom<TaggedAdminApiResponse> for [< $endpoint Response >] { + type Error = TaggedAdminApiResponse; + fn try_from(resp: TaggedAdminApiResponse) -> Result< [< $endpoint Response >], TaggedAdminApiResponse> { + match resp { + TaggedAdminApiResponse::$endpoint(v) => Ok(v), + x => Err(x), + } + } + } + )* + #[async_trait] impl EndpointHandler for AdminApiRequest { type Response = AdminApiResponse; diff --git a/src/api/admin/router_v2.rs b/src/api/admin/router_v2.rs index 29250f39..9d60b312 100644 --- a/src/api/admin/router_v2.rs +++ b/src/api/admin/router_v2.rs @@ -46,7 +46,7 @@ impl AdminApiRequest { POST DeleteKey (query::id), GET ListKeys (), // Bucket endpoints - GET GetBucketInfo (query_opt::id, query_opt::global_alias), + GET GetBucketInfo (query_opt::id, query_opt::global_alias, query_opt::search), GET ListBuckets (), POST CreateBucket (body), POST DeleteBucket (query::id), @@ -141,6 +141,7 @@ impl AdminApiRequest { Ok(AdminApiRequest::GetBucketInfo(GetBucketInfoRequest { id, global_alias, + search: None, })) } Endpoint::CreateBucket => { |