aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <lx@deuxfleurs.fr>2025-01-28 15:59:32 +0100
committerAlex Auvolat <lx@deuxfleurs.fr>2025-01-29 19:26:16 +0100
commit5037b97dd41cb668289708384c13006f5db2afd7 (patch)
treefebe4fd01af337c11fb92f406a3c60b1b94038b2
parentaf1a53083452e7953736261db57aea4a68aa4278 (diff)
downloadgarage-5037b97dd41cb668289708384c13006f5db2afd7.tar.gz
garage-5037b97dd41cb668289708384c13006f5db2afd7.zip
admin api: add compatibility from v1/ to v2/
-rw-r--r--src/api/admin/api_server.rs6
-rw-r--r--src/api/admin/router_v1.rs10
-rw-r--r--src/api/admin/router_v2.rs163
-rw-r--r--src/api/router_macros.rs4
4 files changed, 115 insertions, 68 deletions
diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs
index e00f17c4..2f2e3284 100644
--- a/src/api/admin/api_server.rs
+++ b/src/api/admin/api_server.rs
@@ -127,12 +127,10 @@ impl ApiHandler for AdminApiServer {
req: Request<IncomingBody>,
endpoint: Endpoint,
) -> Result<Response<ResBody>, Error> {
- let auth_header = req.headers().get(AUTHORIZATION).clone();
+ let auth_header = req.headers().get(AUTHORIZATION).cloned();
let request = match endpoint {
- Endpoint::Old(endpoint_v1) => {
- todo!() // TODO: convert from old semantics, if possible
- }
+ Endpoint::Old(endpoint_v1) => AdminApiRequest::from_v1(endpoint_v1, req).await?,
Endpoint::New(_) => AdminApiRequest::from_request(req).await?,
};
diff --git a/src/api/admin/router_v1.rs b/src/api/admin/router_v1.rs
index d69675cc..7e738145 100644
--- a/src/api/admin/router_v1.rs
+++ b/src/api/admin/router_v1.rs
@@ -4,7 +4,6 @@ use hyper::{Method, Request};
use crate::admin::error::*;
use crate::admin::router_v0;
-use crate::admin::Authorization;
use crate::router_macros::*;
router_match! {@func
@@ -205,15 +204,6 @@ impl Endpoint {
))),
}
}
- /// Get the kind of authorization which is required to perform the operation.
- pub fn authorization_type(&self) -> Authorization {
- match self {
- Self::Health => Authorization::None,
- Self::CheckDomain => Authorization::None,
- Self::Metrics => Authorization::MetricsToken,
- _ => Authorization::AdminToken,
- }
- }
}
generateQueryParameters! {
diff --git a/src/api/admin/router_v2.rs b/src/api/admin/router_v2.rs
index f9a976c4..e0c54f0e 100644
--- a/src/api/admin/router_v2.rs
+++ b/src/api/admin/router_v2.rs
@@ -6,7 +6,7 @@ use paste::paste;
use crate::admin::api::*;
use crate::admin::error::*;
-//use crate::admin::router_v1;
+use crate::admin::router_v1;
use crate::admin::Authorization;
use crate::helpers::*;
use crate::router_macros::*;
@@ -67,82 +67,141 @@ impl AdminApiRequest {
Ok(res)
}
- /*
- /// Some endpoints work exactly the same in their v1/ version as they did in their v0/ version.
- /// For these endpoints, we can convert a v0/ call to its equivalent as if it was made using
- /// its v1/ URL.
- pub fn from_v0(v0_endpoint: router_v0::Endpoint) -> Result<Self, Error> {
- match v0_endpoint {
- // Cluster endpoints
- router_v0::Endpoint::ConnectClusterNodes => Ok(Self::ConnectClusterNodes),
- // - GetClusterStatus: response format changed
- // - GetClusterHealth: response format changed
- // Layout endpoints
- router_v0::Endpoint::RevertClusterLayout => Ok(Self::RevertClusterLayout),
- // - GetClusterLayout: response format changed
- // - UpdateClusterLayout: query format changed
- // - ApplyCusterLayout: response format changed
-
- // Key endpoints
- router_v0::Endpoint::ListKeys => Ok(Self::ListKeys),
- router_v0::Endpoint::CreateKey => Ok(Self::CreateKey),
- router_v0::Endpoint::GetKeyInfo { id, search } => Ok(Self::GetKeyInfo {
+ /// Some endpoints work exactly the same in their v2/ version as they did in their v1/ version.
+ /// For these endpoints, we can convert a v1/ call to its equivalent as if it was made using
+ /// its v2/ URL.
+ pub async fn from_v1(
+ v1_endpoint: router_v1::Endpoint,
+ req: Request<IncomingBody>,
+ ) -> Result<Self, Error> {
+ use router_v1::Endpoint;
+
+ match v1_endpoint {
+ Endpoint::GetClusterStatus => {
+ Ok(AdminApiRequest::GetClusterStatus(GetClusterStatusRequest))
+ }
+ Endpoint::GetClusterHealth => {
+ Ok(AdminApiRequest::GetClusterHealth(GetClusterHealthRequest))
+ }
+ Endpoint::ConnectClusterNodes => {
+ let req = parse_json_body::<ConnectClusterNodesRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::ConnectClusterNodes(req))
+ }
+
+ // Layout
+ Endpoint::GetClusterLayout => {
+ Ok(AdminApiRequest::GetClusterLayout(GetClusterLayoutRequest))
+ }
+ Endpoint::UpdateClusterLayout => {
+ let updates = parse_json_body::<UpdateClusterLayoutRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::UpdateClusterLayout(updates))
+ }
+ Endpoint::ApplyClusterLayout => {
+ let param = parse_json_body::<ApplyClusterLayoutRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::ApplyClusterLayout(param))
+ }
+ Endpoint::RevertClusterLayout => Ok(AdminApiRequest::RevertClusterLayout(
+ RevertClusterLayoutRequest,
+ )),
+
+ // Keys
+ Endpoint::ListKeys => Ok(AdminApiRequest::ListKeys(ListKeysRequest)),
+ Endpoint::GetKeyInfo {
id,
search,
- show_secret_key: Some("true".into()),
- }),
- router_v0::Endpoint::DeleteKey { id } => Ok(Self::DeleteKey { id }),
- // - UpdateKey: response format changed (secret key no longer returned)
+ show_secret_key,
+ } => {
+ let show_secret_key = show_secret_key.map(|x| x == "true").unwrap_or(false);
+ Ok(AdminApiRequest::GetKeyInfo(GetKeyInfoRequest {
+ id,
+ search,
+ show_secret_key,
+ }))
+ }
+ Endpoint::CreateKey => {
+ let req = parse_json_body::<CreateKeyRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::CreateKey(req))
+ }
+ Endpoint::ImportKey => {
+ let req = parse_json_body::<ImportKeyRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::ImportKey(req))
+ }
+ Endpoint::UpdateKey { id } => {
+ let body = parse_json_body::<UpdateKeyRequestBody, _, Error>(req).await?;
+ Ok(AdminApiRequest::UpdateKey(UpdateKeyRequest { id, body }))
+ }
+ Endpoint::DeleteKey { id } => Ok(AdminApiRequest::DeleteKey(DeleteKeyRequest { id })),
- // Bucket endpoints
- router_v0::Endpoint::GetBucketInfo { id, global_alias } => {
- Ok(Self::GetBucketInfo { id, global_alias })
+ // Buckets
+ Endpoint::ListBuckets => Ok(AdminApiRequest::ListBuckets(ListBucketsRequest)),
+ Endpoint::GetBucketInfo { id, global_alias } => {
+ Ok(AdminApiRequest::GetBucketInfo(GetBucketInfoRequest {
+ id,
+ global_alias,
+ }))
+ }
+ Endpoint::CreateBucket => {
+ let req = parse_json_body::<CreateBucketRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::CreateBucket(req))
+ }
+ Endpoint::DeleteBucket { id } => {
+ Ok(AdminApiRequest::DeleteBucket(DeleteBucketRequest { id }))
+ }
+ Endpoint::UpdateBucket { id } => {
+ let body = parse_json_body::<UpdateBucketRequestBody, _, Error>(req).await?;
+ Ok(AdminApiRequest::UpdateBucket(UpdateBucketRequest {
+ id,
+ body,
+ }))
}
- router_v0::Endpoint::ListBuckets => Ok(Self::ListBuckets),
- router_v0::Endpoint::CreateBucket => Ok(Self::CreateBucket),
- router_v0::Endpoint::DeleteBucket { id } => Ok(Self::DeleteBucket { id }),
- router_v0::Endpoint::UpdateBucket { id } => Ok(Self::UpdateBucket { id }),
// Bucket-key permissions
- router_v0::Endpoint::BucketAllowKey => Ok(Self::BucketAllowKey),
- router_v0::Endpoint::BucketDenyKey => Ok(Self::BucketDenyKey),
-
- // Bucket alias endpoints
- router_v0::Endpoint::GlobalAliasBucket { id, alias } => {
- Ok(Self::GlobalAliasBucket { id, alias })
+ Endpoint::BucketAllowKey => {
+ let req = parse_json_body::<BucketKeyPermChangeRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::BucketAllowKey(BucketAllowKeyRequest(req)))
}
- router_v0::Endpoint::GlobalUnaliasBucket { id, alias } => {
- Ok(Self::GlobalUnaliasBucket { id, alias })
+ Endpoint::BucketDenyKey => {
+ let req = parse_json_body::<BucketKeyPermChangeRequest, _, Error>(req).await?;
+ Ok(AdminApiRequest::BucketDenyKey(BucketDenyKeyRequest(req)))
}
- router_v0::Endpoint::LocalAliasBucket {
+ // Bucket aliasing
+ Endpoint::GlobalAliasBucket { id, alias } => Ok(AdminApiRequest::GlobalAliasBucket(
+ GlobalAliasBucketRequest { id, alias },
+ )),
+ Endpoint::GlobalUnaliasBucket { id, alias } => Ok(
+ AdminApiRequest::GlobalUnaliasBucket(GlobalUnaliasBucketRequest { id, alias }),
+ ),
+ Endpoint::LocalAliasBucket {
id,
access_key_id,
alias,
- } => Ok(Self::LocalAliasBucket {
- id,
+ } => Ok(AdminApiRequest::LocalAliasBucket(LocalAliasBucketRequest {
access_key_id,
- alias,
- }),
- router_v0::Endpoint::LocalUnaliasBucket {
id,
- access_key_id,
alias,
- } => Ok(Self::LocalUnaliasBucket {
+ })),
+ Endpoint::LocalUnaliasBucket {
id,
access_key_id,
alias,
- }),
+ } => Ok(AdminApiRequest::LocalUnaliasBucket(
+ LocalUnaliasBucketRequest {
+ access_key_id,
+ id,
+ alias,
+ },
+ )),
// For endpoints that have different body content syntax, issue
// deprecation warning
_ => Err(Error::bad_request(format!(
- "v0/ endpoint is no longer supported: {}",
- v0_endpoint.name()
+ "v1/ endpoint is no longer supported: {}",
+ v1_endpoint.name()
))),
}
}
- */
+
/// Get the kind of authorization which is required to perform the operation.
pub fn authorization_type(&self) -> Authorization {
match self {
diff --git a/src/api/router_macros.rs b/src/api/router_macros.rs
index acbe097c..e8c99909 100644
--- a/src/api/router_macros.rs
+++ b/src/api/router_macros.rs
@@ -165,8 +165,8 @@ macro_rules! router_match {
.map_err(|_| Error::bad_request("Failed to parse query parameter"))?
}};
(@@parse_param $query:expr, parse_default($default:expr), $param:ident) => {{
- // extract and parse mandatory query parameter
- // both missing and un-parseable parameters are reported as errors
+ // extract and parse optional query parameter
+ // using provided value as default if paramter is missing
$query.$param.take().map(|x| x
.parse()
.map_err(|_| Error::bad_request("Failed to parse query parameter")))