wip: proxy admin api requests through admin rpc, prepare new cli
Some checks failed
ci/woodpecker/push/debug Pipeline failed

This commit is contained in:
Alex 2025-01-30 10:44:08 +01:00
parent 6ed78abb5c
commit 145130481e
6 changed files with 194 additions and 78 deletions

View file

@ -1,3 +1,4 @@
use std::convert::TryFrom;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
@ -77,18 +78,18 @@ admin_endpoints![
// because they directly produce an http::Response // because they directly produce an http::Response
// ********************************************** // **********************************************
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptionsRequest; pub struct OptionsRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CheckDomainRequest { pub struct CheckDomainRequest {
pub domain: String, pub domain: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthRequest; pub struct HealthRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsRequest; pub struct MetricsRequest;
// ********************************************** // **********************************************
@ -97,10 +98,10 @@ pub struct MetricsRequest;
// ---- GetClusterStatus ---- // ---- GetClusterStatus ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterStatusRequest; pub struct GetClusterStatusRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetClusterStatusResponse { pub struct GetClusterStatusResponse {
pub node: String, pub node: String,
@ -112,7 +113,7 @@ pub struct GetClusterStatusResponse {
pub nodes: Vec<NodeResp>, pub nodes: Vec<NodeResp>,
} }
#[derive(Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct NodeResp { pub struct NodeResp {
pub id: String, pub id: String,
@ -128,7 +129,7 @@ pub struct NodeResp {
pub metadata_partition: Option<FreeSpaceResp>, pub metadata_partition: Option<FreeSpaceResp>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct NodeRoleResp { pub struct NodeRoleResp {
pub id: String, pub id: String,
@ -137,7 +138,7 @@ pub struct NodeRoleResp {
pub tags: Vec<String>, pub tags: Vec<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct FreeSpaceResp { pub struct FreeSpaceResp {
pub available: u64, pub available: u64,
@ -146,7 +147,7 @@ pub struct FreeSpaceResp {
// ---- GetClusterHealth ---- // ---- GetClusterHealth ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterHealthRequest; pub struct GetClusterHealthRequest;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -167,10 +168,10 @@ pub struct GetClusterHealthResponse {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectClusterNodesRequest(pub Vec<String>); pub struct ConnectClusterNodesRequest(pub Vec<String>);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectClusterNodesResponse(pub Vec<ConnectNodeResponse>); pub struct ConnectClusterNodesResponse(pub Vec<ConnectNodeResponse>);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ConnectNodeResponse { pub struct ConnectNodeResponse {
pub success: bool, pub success: bool,
@ -179,10 +180,10 @@ pub struct ConnectNodeResponse {
// ---- GetClusterLayout ---- // ---- GetClusterLayout ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterLayoutRequest; pub struct GetClusterLayoutRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetClusterLayoutResponse { pub struct GetClusterLayoutResponse {
pub version: u64, pub version: u64,
@ -190,7 +191,7 @@ pub struct GetClusterLayoutResponse {
pub staged_role_changes: Vec<NodeRoleChange>, pub staged_role_changes: Vec<NodeRoleChange>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct NodeRoleChange { pub struct NodeRoleChange {
pub id: String, pub id: String,
@ -198,7 +199,7 @@ pub struct NodeRoleChange {
pub action: NodeRoleChangeEnum, pub action: NodeRoleChangeEnum,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum NodeRoleChangeEnum { pub enum NodeRoleChangeEnum {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -213,21 +214,21 @@ pub enum NodeRoleChangeEnum {
// ---- UpdateClusterLayout ---- // ---- UpdateClusterLayout ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateClusterLayoutRequest(pub Vec<NodeRoleChange>); pub struct UpdateClusterLayoutRequest(pub Vec<NodeRoleChange>);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateClusterLayoutResponse(pub GetClusterLayoutResponse); pub struct UpdateClusterLayoutResponse(pub GetClusterLayoutResponse);
// ---- ApplyClusterLayout ---- // ---- ApplyClusterLayout ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ApplyClusterLayoutRequest { pub struct ApplyClusterLayoutRequest {
pub version: u64, pub version: u64,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ApplyClusterLayoutResponse { pub struct ApplyClusterLayoutResponse {
pub message: Vec<String>, pub message: Vec<String>,
@ -236,10 +237,10 @@ pub struct ApplyClusterLayoutResponse {
// ---- RevertClusterLayout ---- // ---- RevertClusterLayout ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RevertClusterLayoutRequest; pub struct RevertClusterLayoutRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse); pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse);
// ********************************************** // **********************************************
@ -248,13 +249,13 @@ pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse);
// ---- ListKeys ---- // ---- ListKeys ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListKeysRequest; pub struct ListKeysRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListKeysResponse(pub Vec<ListKeysResponseItem>); pub struct ListKeysResponse(pub Vec<ListKeysResponseItem>);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ListKeysResponseItem { pub struct ListKeysResponseItem {
pub id: String, pub id: String,
@ -263,14 +264,14 @@ pub struct ListKeysResponseItem {
// ---- GetKeyInfo ---- // ---- GetKeyInfo ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetKeyInfoRequest { pub struct GetKeyInfoRequest {
pub id: Option<String>, pub id: Option<String>,
pub search: Option<String>, pub search: Option<String>,
pub show_secret_key: bool, pub show_secret_key: bool,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetKeyInfoResponse { pub struct GetKeyInfoResponse {
pub name: String, pub name: String,
@ -281,14 +282,14 @@ pub struct GetKeyInfoResponse {
pub buckets: Vec<KeyInfoBucketResponse>, pub buckets: Vec<KeyInfoBucketResponse>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct KeyPerm { pub struct KeyPerm {
#[serde(default)] #[serde(default)]
pub create_bucket: bool, pub create_bucket: bool,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct KeyInfoBucketResponse { pub struct KeyInfoBucketResponse {
pub id: String, pub id: String,
@ -297,7 +298,7 @@ pub struct KeyInfoBucketResponse {
pub permissions: ApiBucketKeyPerm, pub permissions: ApiBucketKeyPerm,
} }
#[derive(Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ApiBucketKeyPerm { pub struct ApiBucketKeyPerm {
#[serde(default)] #[serde(default)]
@ -310,18 +311,18 @@ pub struct ApiBucketKeyPerm {
// ---- CreateKey ---- // ---- CreateKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CreateKeyRequest { pub struct CreateKeyRequest {
pub name: Option<String>, pub name: Option<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateKeyResponse(pub GetKeyInfoResponse); pub struct CreateKeyResponse(pub GetKeyInfoResponse);
// ---- ImportKey ---- // ---- ImportKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ImportKeyRequest { pub struct ImportKeyRequest {
pub access_key_id: String, pub access_key_id: String,
@ -329,21 +330,21 @@ pub struct ImportKeyRequest {
pub name: Option<String>, pub name: Option<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImportKeyResponse(pub GetKeyInfoResponse); pub struct ImportKeyResponse(pub GetKeyInfoResponse);
// ---- UpdateKey ---- // ---- UpdateKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateKeyRequest { pub struct UpdateKeyRequest {
pub id: String, pub id: String,
pub body: UpdateKeyRequestBody, pub body: UpdateKeyRequestBody,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateKeyResponse(pub GetKeyInfoResponse); pub struct UpdateKeyResponse(pub GetKeyInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UpdateKeyRequestBody { pub struct UpdateKeyRequestBody {
pub name: Option<String>, pub name: Option<String>,
@ -353,12 +354,12 @@ pub struct UpdateKeyRequestBody {
// ---- DeleteKey ---- // ---- DeleteKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteKeyRequest { pub struct DeleteKeyRequest {
pub id: String, pub id: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteKeyResponse; pub struct DeleteKeyResponse;
// ********************************************** // **********************************************
@ -367,13 +368,13 @@ pub struct DeleteKeyResponse;
// ---- ListBuckets ---- // ---- ListBuckets ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListBucketsRequest; pub struct ListBucketsRequest;
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>); pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ListBucketsResponseItem { pub struct ListBucketsResponseItem {
pub id: String, pub id: String,
@ -381,7 +382,7 @@ pub struct ListBucketsResponseItem {
pub local_aliases: Vec<BucketLocalAlias>, pub local_aliases: Vec<BucketLocalAlias>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BucketLocalAlias { pub struct BucketLocalAlias {
pub access_key_id: String, pub access_key_id: String,
@ -390,13 +391,13 @@ pub struct BucketLocalAlias {
// ---- GetBucketInfo ---- // ---- GetBucketInfo ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetBucketInfoRequest { pub struct GetBucketInfoRequest {
pub id: Option<String>, pub id: Option<String>,
pub global_alias: Option<String>, pub global_alias: Option<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetBucketInfoResponse { pub struct GetBucketInfoResponse {
pub id: String, pub id: String,
@ -414,14 +415,14 @@ pub struct GetBucketInfoResponse {
pub quotas: ApiBucketQuotas, pub quotas: ApiBucketQuotas,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetBucketInfoWebsiteResponse { pub struct GetBucketInfoWebsiteResponse {
pub index_document: String, pub index_document: String,
pub error_document: Option<String>, pub error_document: Option<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetBucketInfoKey { pub struct GetBucketInfoKey {
pub access_key_id: String, pub access_key_id: String,
@ -430,7 +431,7 @@ pub struct GetBucketInfoKey {
pub bucket_local_aliases: Vec<String>, pub bucket_local_aliases: Vec<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ApiBucketQuotas { pub struct ApiBucketQuotas {
pub max_size: Option<u64>, pub max_size: Option<u64>,
@ -439,17 +440,17 @@ pub struct ApiBucketQuotas {
// ---- CreateBucket ---- // ---- CreateBucket ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CreateBucketRequest { pub struct CreateBucketRequest {
pub global_alias: Option<String>, pub global_alias: Option<String>,
pub local_alias: Option<CreateBucketLocalAlias>, pub local_alias: Option<CreateBucketLocalAlias>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateBucketResponse(pub GetBucketInfoResponse); pub struct CreateBucketResponse(pub GetBucketInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CreateBucketLocalAlias { pub struct CreateBucketLocalAlias {
pub access_key_id: String, pub access_key_id: String,
@ -460,23 +461,23 @@ pub struct CreateBucketLocalAlias {
// ---- UpdateBucket ---- // ---- UpdateBucket ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateBucketRequest { pub struct UpdateBucketRequest {
pub id: String, pub id: String,
pub body: UpdateBucketRequestBody, pub body: UpdateBucketRequestBody,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateBucketResponse(pub GetBucketInfoResponse); pub struct UpdateBucketResponse(pub GetBucketInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UpdateBucketRequestBody { pub struct UpdateBucketRequestBody {
pub website_access: Option<UpdateBucketWebsiteAccess>, pub website_access: Option<UpdateBucketWebsiteAccess>,
pub quotas: Option<ApiBucketQuotas>, pub quotas: Option<ApiBucketQuotas>,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UpdateBucketWebsiteAccess { pub struct UpdateBucketWebsiteAccess {
pub enabled: bool, pub enabled: bool,
@ -486,12 +487,12 @@ pub struct UpdateBucketWebsiteAccess {
// ---- DeleteBucket ---- // ---- DeleteBucket ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteBucketRequest { pub struct DeleteBucketRequest {
pub id: String, pub id: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteBucketResponse; pub struct DeleteBucketResponse;
// ********************************************** // **********************************************
@ -500,13 +501,13 @@ pub struct DeleteBucketResponse;
// ---- AllowBucketKey ---- // ---- AllowBucketKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AllowBucketKeyRequest(pub BucketKeyPermChangeRequest); pub struct AllowBucketKeyRequest(pub BucketKeyPermChangeRequest);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AllowBucketKeyResponse(pub GetBucketInfoResponse); pub struct AllowBucketKeyResponse(pub GetBucketInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BucketKeyPermChangeRequest { pub struct BucketKeyPermChangeRequest {
pub bucket_id: String, pub bucket_id: String,
@ -516,10 +517,10 @@ pub struct BucketKeyPermChangeRequest {
// ---- DenyBucketKey ---- // ---- DenyBucketKey ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DenyBucketKeyRequest(pub BucketKeyPermChangeRequest); pub struct DenyBucketKeyRequest(pub BucketKeyPermChangeRequest);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse); pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse);
// ********************************************** // **********************************************
@ -528,7 +529,7 @@ pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse);
// ---- AddBucketAlias ---- // ---- AddBucketAlias ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddBucketAliasRequest { pub struct AddBucketAliasRequest {
pub bucket_id: String, pub bucket_id: String,
@ -536,10 +537,10 @@ pub struct AddBucketAliasRequest {
pub alias: BucketAliasEnum, pub alias: BucketAliasEnum,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddBucketAliasResponse(pub GetBucketInfoResponse); pub struct AddBucketAliasResponse(pub GetBucketInfoResponse);
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum BucketAliasEnum { pub enum BucketAliasEnum {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -553,7 +554,7 @@ pub enum BucketAliasEnum {
// ---- RemoveBucketAlias ---- // ---- RemoveBucketAlias ----
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RemoveBucketAliasRequest { pub struct RemoveBucketAliasRequest {
pub bucket_id: String, pub bucket_id: String,
@ -561,5 +562,5 @@ pub struct RemoveBucketAliasRequest {
pub alias: BucketAliasEnum, pub alias: BucketAliasEnum,
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse); pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);

View file

@ -56,7 +56,7 @@ impl From<HelperError> for Error {
impl CommonErrorDerivative for Error {} impl CommonErrorDerivative for Error {}
impl Error { impl Error {
fn code(&self) -> &'static str { pub fn code(&self) -> &'static str {
match self { match self {
Error::Common(c) => c.aws_code(), Error::Common(c) => c.aws_code(),
Error::NoSuchAccessKey(_) => "NoSuchAccessKey", Error::NoSuchAccessKey(_) => "NoSuchAccessKey",

View file

@ -4,7 +4,7 @@ macro_rules! admin_endpoints {
$($endpoint:ident,)* $($endpoint:ident,)*
] => { ] => {
paste! { paste! {
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminApiRequest { pub enum AdminApiRequest {
$( $(
$special_endpoint( [<$special_endpoint Request>] ), $special_endpoint( [<$special_endpoint Request>] ),
@ -14,7 +14,7 @@ macro_rules! admin_endpoints {
)* )*
} }
#[derive(Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum AdminApiResponse { pub enum AdminApiResponse {
$( $(
@ -22,7 +22,7 @@ macro_rules! admin_endpoints {
)* )*
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaggedAdminApiResponse { pub enum TaggedAdminApiResponse {
$( $(
$endpoint( [<$endpoint Response>] ), $endpoint( [<$endpoint Response>] ),
@ -43,7 +43,7 @@ macro_rules! admin_endpoints {
} }
impl AdminApiResponse { impl AdminApiResponse {
fn tagged(self) -> TaggedAdminApiResponse { pub fn tagged(self) -> TaggedAdminApiResponse {
match self { match self {
$( $(
Self::$endpoint(res) => TaggedAdminApiResponse::$endpoint(res), 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] #[async_trait]
impl EndpointHandler for AdminApiRequest { impl EndpointHandler for AdminApiRequest {
type Response = AdminApiResponse; type Response = AdminApiResponse;

View file

@ -30,6 +30,10 @@ use garage_model::key_table::*;
use garage_model::s3::mpu_table::MultipartUpload; use garage_model::s3::mpu_table::MultipartUpload;
use garage_model::s3::version_table::Version; use garage_model::s3::version_table::Version;
use garage_api::admin::api::{AdminApiRequest, TaggedAdminApiResponse};
use garage_api::admin::EndpointHandler as AdminApiEndpoint;
use garage_api::generic_server::ApiError;
use crate::cli::*; use crate::cli::*;
use crate::repair::online::launch_online_repair; use crate::repair::online::launch_online_repair;
@ -70,6 +74,15 @@ pub enum AdminRpc {
versions: Vec<Result<Version, Uuid>>, versions: Vec<Result<Version, Uuid>>,
uploads: Vec<MultipartUpload>, uploads: Vec<MultipartUpload>,
}, },
// Proxying HTTP Admin API endpoints
ApiRequest(AdminApiRequest),
ApiOkResponse(TaggedAdminApiResponse),
ApiErrorResponse {
http_code: u16,
error_code: String,
message: String,
},
} }
impl Rpc for AdminRpc { impl Rpc for AdminRpc {
@ -503,6 +516,24 @@ impl AdminRpcHandler {
} }
} }
} }
// ================== PROXYING ADMIN API REQUESTS ===================
async fn handle_api_request(
self: &Arc<Self>,
req: &AdminApiRequest,
) -> Result<AdminRpc, Error> {
let req = req.clone();
let res = req.handle(&self.garage).await;
match res {
Ok(res) => Ok(AdminRpc::ApiOkResponse(res.tagged())),
Err(e) => Ok(AdminRpc::ApiErrorResponse {
http_code: e.http_status_code().as_u16(),
error_code: e.code().to_string(),
message: e.to_string(),
}),
}
}
} }
#[async_trait] #[async_trait]
@ -520,6 +551,7 @@ impl EndpointHandler<AdminRpc> for AdminRpcHandler {
AdminRpc::Worker(wo) => self.handle_worker_cmd(wo).await, AdminRpc::Worker(wo) => self.handle_worker_cmd(wo).await,
AdminRpc::BlockOperation(bo) => self.handle_block_cmd(bo).await, AdminRpc::BlockOperation(bo) => self.handle_block_cmd(bo).await,
AdminRpc::MetaOperation(mo) => self.handle_meta_cmd(mo).await, AdminRpc::MetaOperation(mo) => self.handle_meta_cmd(mo).await,
AdminRpc::ApiRequest(r) => self.handle_api_request(r).await,
m => Err(GarageError::unexpected_rpc_message(m).into()), m => Err(GarageError::unexpected_rpc_message(m).into()),
} }
} }

63
src/garage/cli_v2/mod.rs Normal file
View file

@ -0,0 +1,63 @@
use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::sync::Arc;
use std::time::Duration;
use format_table::format_table;
use garage_util::error::*;
use garage_rpc::layout::*;
use garage_rpc::system::*;
use garage_rpc::*;
use garage_api::admin::api::*;
use garage_api::admin::EndpointHandler as AdminApiEndpoint;
use crate::admin::*;
use crate::cli::*;
pub struct Cli {
pub system_rpc_endpoint: Arc<Endpoint<SystemRpc, ()>>,
pub admin_rpc_endpoint: Arc<Endpoint<AdminRpc, ()>>,
pub rpc_host: NodeID,
}
impl Cli {
pub async fn handle(&self, cmd: Command) -> Result<(), Error> {
println!("{:?}", self.api_request(GetClusterStatusRequest).await?);
Ok(())
/*
match cmd {
_ => todo!(),
}
*/
}
pub async fn api_request<T>(&self, req: T) -> Result<<T as AdminApiEndpoint>::Response, Error>
where
T: AdminApiEndpoint,
AdminApiRequest: From<T>,
<T as AdminApiEndpoint>::Response: TryFrom<TaggedAdminApiResponse>,
{
let req = AdminApiRequest::from(req);
let req_name = req.name();
match self
.admin_rpc_endpoint
.call(&self.rpc_host, AdminRpc::ApiRequest(req), PRIO_NORMAL)
.await?
.ok_or_message("xoxo")?
{
AdminRpc::ApiOkResponse(resp) => <T as AdminApiEndpoint>::Response::try_from(resp)
.map_err(|_| Error::Message(format!("{} returned unexpected response", req_name))),
AdminRpc::ApiErrorResponse {
http_code,
error_code,
message,
} => Err(Error::Message(format!(
"{} returned {} ({}): {}",
req_name, error_code, http_code, message
))),
m => Err(Error::unexpected_rpc_message(m)),
}
}
}

View file

@ -6,6 +6,7 @@ extern crate tracing;
mod admin; mod admin;
mod cli; mod cli;
mod cli_v2;
mod repair; mod repair;
mod secrets; mod secrets;
mod server; mod server;
@ -284,10 +285,11 @@ async fn cli_command(opt: Opt) -> Result<(), Error> {
let system_rpc_endpoint = netapp.endpoint::<SystemRpc, ()>(SYSTEM_RPC_PATH.into()); let system_rpc_endpoint = netapp.endpoint::<SystemRpc, ()>(SYSTEM_RPC_PATH.into());
let admin_rpc_endpoint = netapp.endpoint::<AdminRpc, ()>(ADMIN_RPC_PATH.into()); let admin_rpc_endpoint = netapp.endpoint::<AdminRpc, ()>(ADMIN_RPC_PATH.into());
match cli_command_dispatch(opt.cmd, &system_rpc_endpoint, &admin_rpc_endpoint, id).await { let cli = cli_v2::Cli {
Err(HelperError::Internal(i)) => Err(Error::Message(format!("Internal error: {}", i))), system_rpc_endpoint,
Err(HelperError::BadRequest(b)) => Err(Error::Message(b)), admin_rpc_endpoint,
Err(e) => Err(Error::Message(format!("{}", e))), rpc_host: id,
Ok(x) => Ok(x), };
}
cli.handle(opt.cmd).await
} }