admin api: small fixes
All checks were successful
ci/woodpecker/push/debug Pipeline was successful
ci/woodpecker/pr/debug Pipeline was successful

This commit is contained in:
Alex 2025-01-29 12:06:58 +01:00
parent 6d4c1ed23a
commit 8515060a08
6 changed files with 41 additions and 10 deletions

View file

@ -91,7 +91,7 @@ paths:
example: "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f" example: "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f"
garageVersion: garageVersion:
type: string type: string
example: "v0.9.0" example: "v2.0.0"
garageFeatures: garageFeatures:
type: array type: array
items: items:

View file

@ -53,7 +53,7 @@ Returns an HTTP status 200 if the node is ready to answer user's requests,
and an HTTP status 503 (Service Unavailable) if there are some partitions and an HTTP status 503 (Service Unavailable) if there are some partitions
for which a quorum of nodes is not available. for which a quorum of nodes is not available.
A simple textual message is also returned in a body with content-type `text/plain`. A simple textual message is also returned in a body with content-type `text/plain`.
See `/v2/health` for an API that also returns JSON output. See `/v2/GetClusterHealth` for an API that also returns JSON output.
### Other special endpoints ### Other special endpoints

View file

@ -13,9 +13,21 @@ use crate::admin::EndpointHandler;
use crate::helpers::is_default; use crate::helpers::is_default;
// This generates the following: // This generates the following:
//
// - An enum AdminApiRequest that contains a variant for all endpoints // - An enum AdminApiRequest that contains a variant for all endpoints
// - An enum AdminApiResponse that contains a variant for all non-special endpoints //
// - An enum AdminApiResponse that contains a variant for all non-special endpoints.
// This enum is serialized in api_server.rs, without the enum tag,
// which gives directly the JSON response corresponding to the API call.
// This enum does not implement Deserialize as its meaning can be ambiguous.
//
// - An enum TaggedAdminApiResponse that contains the same variants, but
// serializes as a tagged enum. This allows it to be transmitted through
// Garage RPC and deserialized correctly upon receival.
// Conversion from untagged to tagged can be done using the `.tagged()` method.
//
// - AdminApiRequest::name() that returns the name of the endpoint // - AdminApiRequest::name() that returns the name of the endpoint
//
// - impl EndpointHandler for AdminApiHandler, that uses the impl EndpointHandler // - impl EndpointHandler for AdminApiHandler, that uses the impl EndpointHandler
// of each request type below for non-special endpoints // of each request type below for non-special endpoints
admin_endpoints![ admin_endpoints![
@ -60,6 +72,9 @@ admin_endpoints![
// ********************************************** // **********************************************
// Special endpoints // Special endpoints
//
// These endpoints don't have associated *Response structs
// because they directly produce an http::Response
// ********************************************** // **********************************************
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -153,11 +168,11 @@ pub struct GetClusterHealthResponse {
pub struct ConnectClusterNodesRequest(pub Vec<String>); pub struct ConnectClusterNodesRequest(pub Vec<String>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct ConnectClusterNodesResponse(pub Vec<ConnectClusterNodeResponse>); pub struct ConnectClusterNodesResponse(pub Vec<ConnectNodeResponse>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ConnectClusterNodeResponse { pub struct ConnectNodeResponse {
pub success: bool, pub success: bool,
pub error: Option<String>, pub error: Option<String>,
} }
@ -331,7 +346,6 @@ pub struct UpdateKeyResponse(pub GetKeyInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UpdateKeyRequestBody { pub struct UpdateKeyRequestBody {
// TODO: id (get parameter) goes here
pub name: Option<String>, pub name: Option<String>,
pub allow: Option<KeyPerm>, pub allow: Option<KeyPerm>,
pub deny: Option<KeyPerm>, pub deny: Option<KeyPerm>,

View file

@ -176,7 +176,7 @@ impl ApiHandler for AdminApiServer {
impl ApiEndpoint for Endpoint { impl ApiEndpoint for Endpoint {
fn name(&self) -> Cow<'static, str> { fn name(&self) -> Cow<'static, str> {
match self { match self {
Self::Old(endpoint_v1) => Cow::Owned(format!("v1:{}", endpoint_v1.name())), Self::Old(endpoint_v1) => Cow::Borrowed(endpoint_v1.name()),
Self::New(path) => Cow::Owned(path.clone()), Self::New(path) => Cow::Owned(path.clone()),
} }
} }

View file

@ -151,11 +151,11 @@ impl EndpointHandler for ConnectClusterNodesRequest {
.await .await
.into_iter() .into_iter()
.map(|r| match r { .map(|r| match r {
Ok(()) => ConnectClusterNodeResponse { Ok(()) => ConnectNodeResponse {
success: true, success: true,
error: None, error: None,
}, },
Err(e) => ConnectClusterNodeResponse { Err(e) => ConnectNodeResponse {
success: false, success: false,
error: Some(format!("{}", e)), error: Some(format!("{}", e)),
}, },

View file

@ -14,7 +14,7 @@ macro_rules! admin_endpoints {
)* )*
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum AdminApiResponse { pub enum AdminApiResponse {
$( $(
@ -22,6 +22,13 @@ macro_rules! admin_endpoints {
)* )*
} }
#[derive(Serialize, Deserialize)]
pub enum TaggedAdminApiResponse {
$(
$endpoint( [<$endpoint Response>] ),
)*
}
impl AdminApiRequest { impl AdminApiRequest {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
match self { match self {
@ -35,6 +42,16 @@ macro_rules! admin_endpoints {
} }
} }
impl AdminApiResponse {
fn tagged(self) -> TaggedAdminApiResponse {
match self {
$(
Self::$endpoint(res) => TaggedAdminApiResponse::$endpoint(res),
)*
}
}
}
#[async_trait] #[async_trait]
impl EndpointHandler for AdminApiRequest { impl EndpointHandler for AdminApiRequest {
type Response = AdminApiResponse; type Response = AdminApiResponse;