admin API refactoring (step 1) #939

Merged
lx merged 19 commits from refactor-admin into next-v2 2025-01-29 20:42:57 +00:00
5 changed files with 86 additions and 222 deletions
Showing only changes of commit 12ea4cda5f - Show all commits

View file

@ -946,14 +946,16 @@ paths:
schema: schema:
$ref: '#/components/schemas/BucketInfo' $ref: '#/components/schemas/BucketInfo'
/AddGlobalBucketAlias: /AddBucketAlias:
post: post:
tags: tags:
- Bucket aliases - Bucket aliases
operationId: "AddGlobalBucketAlias" operationId: "AddlBucketAlias"
summary: "Add a global alias" summary: "Add an alias to a bucket"
description: | description: |
Add a global alias to the target bucket Add an alias for the target bucket.
This can be a local alias if `accessKeyId` is specified,
or a global alias otherwise.
requestBody: requestBody:
required: true required: true
content: content:
@ -961,78 +963,6 @@ paths:
schema: schema:
type: object type: object
required: [bucketId, alias] required: [bucketId, alias]
properties:
bucketId:
type: string
example: e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b
alias:
type: string
example: my_documents
responses:
'500':
description: "The server can not handle your request. Check your connectivity with the rest of the cluster."
'400':
description: "Bad request, check your request body"
'404':
description: "Bucket not found"
'200':
description: Returns exhaustive information about the bucket
content:
application/json:
schema:
$ref: '#/components/schemas/BucketInfo'
/RemoveGlobalBucketAlias:
post:
tags:
- Bucket aliases
operationId: "RemoveGlobalBucketAlias"
summary: "Delete a global alias"
description: |
Delete a global alias from the target bucket
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucketId, alias]
properties:
bucketId:
type: string
example: e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b
alias:
type: string
example: my_documents
responses:
'500':
description: "The server can not handle your request. Check your connectivity with the rest of the cluster."
'400':
description: "Bad request, check your request body"
'404':
description: "Bucket not found"
'200':
description: Returns exhaustive information about the bucket
content:
application/json:
schema:
$ref: '#/components/schemas/BucketInfo'
/AddLocalBucketAlias:
post:
tags:
- Bucket aliases
operationId: "AddLocalBucketAlias"
summary: "Add a local alias"
description: |
Add a local alias, bound to specified account, to the target bucket
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucketId, accessKeyId, alias]
properties: properties:
bucketId: bucketId:
type: string type: string
@ -1057,21 +987,23 @@ paths:
schema: schema:
$ref: '#/components/schemas/BucketInfo' $ref: '#/components/schemas/BucketInfo'
/RemoveGlobalBucketAlias: /RemoveBucketAlias:
post: post:
tags: tags:
- Bucket aliases - Bucket aliases
operationId: "RemoveGlobalBucketAlias" operationId: "RemoveBucketAlias"
summary: "Delete a local alias" summary: "Remove an alias from a bucket"
description: | description: |
Delete a local alias, bound to specified account, from the target bucket Remove an alias for the target bucket.
This can be a local alias if `accessKeyId` is specified,
or a global alias otherwise.
requestBody: requestBody:
required: true required: true
content: content:
application/json: application/json:
schema: schema:
type: object type: object
required: [bucketId, accessKeyId, alias] required: [bucketId, alias]
properties: properties:
bucketId: bucketId:
type: string type: string

View file

@ -750,35 +750,11 @@ Other flags will remain unchanged.
### Operations on bucket aliases ### Operations on bucket aliases
#### AddGlobalBucketAlias `POST /v2/AddGlobalBucketAlias` #### AddBucketAlias `POST /v2/AddBucketAlias`
Creates a global alias for a bucket. Creates an alias for a bucket in the namespace of a specific access key.
If `accessKeyId` is specified, an alias is created in the local namespace
Request body format: of the key. Otherwise, a global alias is created.
```json
{
"bucketId": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b",
"alias": "the-bucket"
}
```
#### RemoveGlobalBucketAlias `POST /v2/RemoveGlobalBucketAlias`
Removes a global alias for a bucket.
Request body format:
```json
{
"bucketId": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b",
"alias": "the-bucket"
}
```
#### AddLocalBucketAlias `POST /v2/AddLocalBucketAlias`
Creates a local alias for a bucket in the namespace of a specific access key.
Request body format: Request body format:
@ -790,9 +766,11 @@ Request body format:
} }
``` ```
#### RemoveLocalBucketAlias `POST /v2/RemoveLocalBucketAlias` #### RemoveBucketAlias `POST /v2/RemoveBucketAlias`
Removes a local alias for a bucket in the namespace of a specific access key. Removes an alias for a bucket in the namespace of a specific access key.
If `accessKeyId` is specified, the alias is removed from the local namespace
of the key. Otherwise, the alias is removed from the global namespace.
Request body format: Request body format:

View file

@ -54,10 +54,8 @@ admin_endpoints![
DenyBucketKey, DenyBucketKey,
// Operations on bucket aliases // Operations on bucket aliases
AddGlobalBucketAlias, AddBucketAlias,
RemoveGlobalBucketAlias, RemoveBucketAlias,
AddLocalBucketAlias,
RemoveLocalBucketAlias,
]; ];
// ********************************************** // **********************************************
@ -514,48 +512,26 @@ pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse);
// Operations on bucket aliases // Operations on bucket aliases
// ********************************************** // **********************************************
// ---- AddGlobalBucketAlias ---- // ---- AddBucketAlias ----
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct AddGlobalBucketAliasRequest { pub struct AddBucketAliasRequest {
pub bucket_id: String, pub bucket_id: String,
pub access_key_id: Option<String>,
pub alias: String, pub alias: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct AddGlobalBucketAliasResponse(pub GetBucketInfoResponse); pub struct AddBucketAliasResponse(pub GetBucketInfoResponse);
// ---- RemoveGlobalBucketAlias ---- // ---- RemoveBucketAlias ----
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct RemoveGlobalBucketAliasRequest { pub struct RemoveBucketAliasRequest {
pub bucket_id: String, pub bucket_id: String,
pub access_key_id: Option<String>,
pub alias: String, pub alias: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct RemoveGlobalBucketAliasResponse(pub GetBucketInfoResponse); pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);
// ---- AddLocalBucketAlias ----
#[derive(Serialize, Deserialize)]
pub struct AddLocalBucketAliasRequest {
pub bucket_id: String,
pub access_key_id: String,
pub alias: String,
}
#[derive(Serialize, Deserialize)]
pub struct AddLocalBucketAliasResponse(pub GetBucketInfoResponse);
// ---- RemoveLocalBucketAlias ----
#[derive(Serialize, Deserialize)]
pub struct RemoveLocalBucketAliasRequest {
pub bucket_id: String,
pub access_key_id: String,
pub alias: String,
}
#[derive(Serialize, Deserialize)]
pub struct RemoveLocalBucketAliasResponse(pub GetBucketInfoResponse);

View file

@ -18,14 +18,12 @@ use garage_model::s3::object_table::*;
use crate::admin::api::ApiBucketKeyPerm; use crate::admin::api::ApiBucketKeyPerm;
use crate::admin::api::{ use crate::admin::api::{
ApiBucketQuotas, AllowBucketKeyRequest, AllowBucketKeyResponse, DenyBucketKeyRequest, AddBucketAliasRequest, AddBucketAliasResponse, AllowBucketKeyRequest, AllowBucketKeyResponse,
DenyBucketKeyResponse, BucketKeyPermChangeRequest, BucketLocalAlias, CreateBucketRequest, ApiBucketQuotas, BucketKeyPermChangeRequest, BucketLocalAlias, CreateBucketRequest,
CreateBucketResponse, DeleteBucketRequest, DeleteBucketResponse, GetBucketInfoKey, CreateBucketResponse, DeleteBucketRequest, DeleteBucketResponse, DenyBucketKeyRequest,
GetBucketInfoRequest, GetBucketInfoResponse, GetBucketInfoWebsiteResponse, DenyBucketKeyResponse, GetBucketInfoKey, GetBucketInfoRequest, GetBucketInfoResponse,
AddGlobalBucketAliasRequest, AddGlobalBucketAliasResponse, RemoveGlobalBucketAliasRequest, GetBucketInfoWebsiteResponse, ListBucketsRequest, ListBucketsResponse, ListBucketsResponseItem,
RemoveGlobalBucketAliasResponse, ListBucketsRequest, ListBucketsResponse, ListBucketsResponseItem, RemoveBucketAliasRequest, RemoveBucketAliasResponse, UpdateBucketRequest, UpdateBucketResponse,
AddLocalBucketAliasRequest, AddLocalBucketAliasResponse, RemoveLocalBucketAliasRequest,
RemoveLocalBucketAliasResponse, UpdateBucketRequest, UpdateBucketResponse,
}; };
use crate::admin::error::*; use crate::admin::error::*;
use crate::admin::EndpointHandler; use crate::admin::EndpointHandler;
@ -453,76 +451,56 @@ pub async fn handle_bucket_change_key_perm(
// ---- BUCKET ALIASES ---- // ---- BUCKET ALIASES ----
#[async_trait] #[async_trait]
impl EndpointHandler for AddGlobalBucketAliasRequest { impl EndpointHandler for AddBucketAliasRequest {
type Response = AddGlobalBucketAliasResponse; type Response = AddBucketAliasResponse;
async fn handle(self, garage: &Arc<Garage>) -> Result<AddGlobalBucketAliasResponse, Error> { async fn handle(self, garage: &Arc<Garage>) -> Result<AddBucketAliasResponse, Error> {
let bucket_id = parse_bucket_id(&self.bucket_id)?; let bucket_id = parse_bucket_id(&self.bucket_id)?;
let helper = garage.locked_helper().await; let helper = garage.locked_helper().await;
helper match self.access_key_id {
.set_global_bucket_alias(bucket_id, &self.alias) None => {
.await?; helper
.set_global_bucket_alias(bucket_id, &self.alias)
.await?;
}
Some(ak) => {
helper
.set_local_bucket_alias(bucket_id, &ak, &self.alias)
.await?;
}
}
Ok(AddGlobalBucketAliasResponse( Ok(AddBucketAliasResponse(
bucket_info_results(garage, bucket_id).await?, bucket_info_results(garage, bucket_id).await?,
)) ))
} }
} }
#[async_trait] #[async_trait]
impl EndpointHandler for RemoveGlobalBucketAliasRequest { impl EndpointHandler for RemoveBucketAliasRequest {
type Response = RemoveGlobalBucketAliasResponse; type Response = RemoveBucketAliasResponse;
async fn handle(self, garage: &Arc<Garage>) -> Result<RemoveGlobalBucketAliasResponse, Error> { async fn handle(self, garage: &Arc<Garage>) -> Result<RemoveBucketAliasResponse, Error> {
let bucket_id = parse_bucket_id(&self.bucket_id)?; let bucket_id = parse_bucket_id(&self.bucket_id)?;
let helper = garage.locked_helper().await; let helper = garage.locked_helper().await;
helper match self.access_key_id {
.unset_global_bucket_alias(bucket_id, &self.alias) None => {
.await?; helper
.unset_global_bucket_alias(bucket_id, &self.alias)
.await?;
}
Some(ak) => {
helper
.unset_local_bucket_alias(bucket_id, &ak, &self.alias)
.await?;
}
}
Ok(RemoveGlobalBucketAliasResponse( Ok(RemoveBucketAliasResponse(
bucket_info_results(garage, bucket_id).await?,
))
}
}
#[async_trait]
impl EndpointHandler for AddLocalBucketAliasRequest {
type Response = AddLocalBucketAliasResponse;
async fn handle(self, garage: &Arc<Garage>) -> Result<AddLocalBucketAliasResponse, Error> {
let bucket_id = parse_bucket_id(&self.bucket_id)?;
let helper = garage.locked_helper().await;
helper
.set_local_bucket_alias(bucket_id, &self.access_key_id, &self.alias)
.await?;
Ok(AddLocalBucketAliasResponse(
bucket_info_results(garage, bucket_id).await?,
))
}
}
#[async_trait]
impl EndpointHandler for RemoveLocalBucketAliasRequest {
type Response = RemoveLocalBucketAliasResponse;
async fn handle(self, garage: &Arc<Garage>) -> Result<RemoveLocalBucketAliasResponse, Error> {
let bucket_id = parse_bucket_id(&self.bucket_id)?;
let helper = garage.locked_helper().await;
helper
.unset_local_bucket_alias(bucket_id, &self.access_key_id, &self.alias)
.await?;
Ok(RemoveLocalBucketAliasResponse(
bucket_info_results(garage, bucket_id).await?, bucket_info_results(garage, bucket_id).await?,
)) ))
} }

View file

@ -55,10 +55,8 @@ impl AdminApiRequest {
POST AllowBucketKey (body), POST AllowBucketKey (body),
POST DenyBucketKey (body), POST DenyBucketKey (body),
// Bucket aliases // Bucket aliases
POST AddGlobalBucketAlias (body), POST AddBucketAlias (body),
POST RemoveGlobalBucketAlias (body), POST RemoveBucketAlias (body),
POST AddLocalBucketAlias (body),
POST RemoveLocalBucketAlias (body),
]); ]);
if let Some(message) = query.nonempty_message() { if let Some(message) = query.nonempty_message() {
@ -174,24 +172,26 @@ impl AdminApiRequest {
Ok(AdminApiRequest::DenyBucketKey(DenyBucketKeyRequest(req))) Ok(AdminApiRequest::DenyBucketKey(DenyBucketKeyRequest(req)))
} }
// Bucket aliasing // Bucket aliasing
Endpoint::GlobalAliasBucket { id, alias } => Ok(AdminApiRequest::AddGlobalBucketAlias( Endpoint::GlobalAliasBucket { id, alias } => {
AddGlobalBucketAliasRequest { Ok(AdminApiRequest::AddBucketAlias(AddBucketAliasRequest {
access_key_id: None,
bucket_id: id,
alias,
}))
}
Endpoint::GlobalUnaliasBucket { id, alias } => Ok(AdminApiRequest::RemoveBucketAlias(
RemoveBucketAliasRequest {
access_key_id: None,
bucket_id: id, bucket_id: id,
alias, alias,
}, },
)), )),
Endpoint::GlobalUnaliasBucket { id, alias } => Ok(
AdminApiRequest::RemoveGlobalBucketAlias(RemoveGlobalBucketAliasRequest {
bucket_id: id,
alias,
}),
),
Endpoint::LocalAliasBucket { Endpoint::LocalAliasBucket {
id, id,
access_key_id, access_key_id,
alias, alias,
} => Ok(AdminApiRequest::AddLocalBucketAlias(AddLocalBucketAliasRequest { } => Ok(AdminApiRequest::AddBucketAlias(AddBucketAliasRequest {
access_key_id, access_key_id: Some(access_key_id),
bucket_id: id, bucket_id: id,
alias, alias,
})), })),
@ -199,9 +199,9 @@ impl AdminApiRequest {
id, id,
access_key_id, access_key_id,
alias, alias,
} => Ok(AdminApiRequest::RemoveLocalBucketAlias( } => Ok(AdminApiRequest::RemoveBucketAlias(
RemoveLocalBucketAliasRequest { RemoveBucketAliasRequest {
access_key_id, access_key_id: Some(access_key_id),
bucket_id: id, bucket_id: id,
alias, alias,
}, },