diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs index 9929fc55..3421b453 100644 --- a/src/api/admin/api.rs +++ b/src/api/admin/api.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::convert::TryFrom; use std::net::SocketAddr; use std::sync::Arc; @@ -70,8 +71,13 @@ admin_endpoints![ // Operations on bucket aliases AddBucketAlias, RemoveBucketAlias, + + // Worker operations + GetWorkerParam, ]; +local_admin_endpoints![GetWorkerParam,]; + // ********************************************** // Special endpoints // @@ -579,3 +585,15 @@ pub struct RemoveBucketAliasRequest { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse); + +// ********************************************** +// Worker operations +// ********************************************** + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LocalGetWorkerParamRequest { + param: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LocalGetWorkerParamResponse(HashMap); diff --git a/src/api/admin/macros.rs b/src/api/admin/macros.rs index 9521616e..31fffd42 100644 --- a/src/api/admin/macros.rs +++ b/src/api/admin/macros.rs @@ -91,4 +91,86 @@ macro_rules! admin_endpoints { }; } +macro_rules! local_admin_endpoints { + [ + $($endpoint:ident,)* + ] => { + paste! { + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum LocalAdminApiRequest { + $( + $endpoint( [] ), + )* + } + + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum LocalAdminApiResponse { + $( + $endpoint( [] ), + )* + } + + $( + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct [< $endpoint Request >] { + node: String, + body: [< Local $endpoint Request >], + } + + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct [< $endpoint Response >](HashMap] >); + + impl From< [< Local $endpoint Request >] > for LocalAdminApiRequest { + fn from(req: [< Local $endpoint Request >]) -> LocalAdminApiRequest { + LocalAdminApiRequest::$endpoint(req) + } + } + + impl TryFrom for [< Local $endpoint Response >] { + type Error = LocalAdminApiResponse; + fn try_from(resp: LocalAdminApiResponse) -> Result< [< Local $endpoint Response >], LocalAdminApiResponse> { + match resp { + LocalAdminApiResponse::$endpoint(v) => Ok(v), + x => Err(x), + } + } + } + + #[async_trait] + impl EndpointHandler for [< $endpoint Request >] { + type Response = [< $endpoint Response >]; + + async fn handle(self, garage: &Arc) -> Result { + todo!() + } + } + )* + + impl LocalAdminApiRequest { + pub fn name(&self) -> &'static str { + match self { + $( + Self::$endpoint(_) => stringify!($endpoint), + )* + } + } + } + + #[async_trait] + impl EndpointHandler for LocalAdminApiRequest { + type Response = LocalAdminApiResponse; + + async fn handle(self, garage: &Arc) -> Result { + Ok(match self { + $( + LocalAdminApiRequest::$endpoint(req) => LocalAdminApiResponse::$endpoint(req.handle(garage).await?), + )* + }) + } + } + } + }; +} + pub(crate) use admin_endpoints; +pub(crate) use local_admin_endpoints; diff --git a/src/api/admin/mod.rs b/src/api/admin/mod.rs index 86f5bcac..2cdd019e 100644 --- a/src/api/admin/mod.rs +++ b/src/api/admin/mod.rs @@ -7,11 +7,15 @@ mod router_v0; mod router_v1; mod router_v2; +pub mod rpc; + mod bucket; mod cluster; mod key; mod special; +mod worker; + use std::sync::Arc; use async_trait::async_trait; diff --git a/src/api/admin/rpc.rs b/src/api/admin/rpc.rs new file mode 100644 index 00000000..ecdddcee --- /dev/null +++ b/src/api/admin/rpc.rs @@ -0,0 +1,75 @@ +use std::fmt::Write; +use std::sync::Arc; + +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; + +use garage_util::background::BackgroundRunner; +use garage_util::error::Error; + +use garage_rpc::*; + +use garage_model::garage::Garage; + +use crate::admin::api::{LocalAdminApiRequest, LocalAdminApiResponse}; +use crate::admin::EndpointHandler as AdminApiEndpoint; +use crate::generic_server::ApiError; + +pub const ADMIN_RPC_PATH: &str = "garage_api/admin/rpc.rs/Rpc"; + +#[derive(Debug, Serialize, Deserialize)] +pub struct AdminRpc(LocalAdminApiRequest); + +#[derive(Debug, Serialize, Deserialize)] +pub enum AdminRpcResponse { + ApiOkResponse(LocalAdminApiResponse), + ApiErrorResponse { + http_code: u16, + error_code: String, + message: String, + }, +} + +impl Rpc for AdminRpc { + type Response = Result; +} + +pub struct AdminRpcHandler { + garage: Arc, + background: Arc, + endpoint: Arc>, +} + +impl AdminRpcHandler { + pub fn new(garage: Arc, background: Arc) -> Arc { + let endpoint = garage.system.netapp.endpoint(ADMIN_RPC_PATH.into()); + let admin = Arc::new(Self { + garage, + background, + endpoint, + }); + admin.endpoint.set_handler(admin.clone()); + admin + } +} + +#[async_trait] +impl EndpointHandler for AdminRpcHandler { + async fn handle( + self: &Arc, + message: &AdminRpc, + _from: NodeID, + ) -> Result { + let req = message.0.clone(); + info!("Proxied admin API request: {}", req.name()); + let res = req.handle(&self.garage).await; + match res { + Ok(res) => Ok(AdminRpcResponse::ApiOkResponse(res)), + Err(e) => Ok(AdminRpcResponse::ApiErrorResponse { + http_code: e.http_status_code().as_u16(), + error_code: e.code().to_string(), + message: e.to_string(), + }), + } + } +} diff --git a/src/api/admin/worker.rs b/src/api/admin/worker.rs new file mode 100644 index 00000000..973f35cb --- /dev/null +++ b/src/api/admin/worker.rs @@ -0,0 +1,18 @@ +use std::sync::Arc; + +use async_trait::async_trait; + +use garage_model::garage::Garage; + +use crate::admin::api::*; +use crate::admin::error::Error; +use crate::admin::EndpointHandler; + +#[async_trait] +impl EndpointHandler for LocalGetWorkerParamRequest { + type Response = LocalGetWorkerParamResponse; + + async fn handle(self, garage: &Arc) -> Result { + todo!() + } +}