diff options
Diffstat (limited to 'src/api/admin/api.rs')
-rw-r--r-- | src/api/admin/api.rs | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs new file mode 100644 index 00000000..a2dc95c2 --- /dev/null +++ b/src/api/admin/api.rs @@ -0,0 +1,486 @@ +use std::net::SocketAddr; + +use serde::{Deserialize, Serialize}; + +use crate::helpers::is_default; + +pub enum AdminApiRequest { + // Cluster operations + GetClusterStatus(GetClusterStatusRequest), + GetClusterHealth(GetClusterHealthRequest), + ConnectClusterNodes(ConnectClusterNodesRequest), + GetClusterLayout(GetClusterLayoutRequest), + UpdateClusterLayout(UpdateClusterLayoutRequest), + ApplyClusterLayout(ApplyClusterLayoutRequest), + RevertClusterLayout(RevertClusterLayoutRequest), +} + +pub enum AdminApiResponse { + // Cluster operations + GetClusterStatus(GetClusterStatusResponse), + GetClusterHealth(GetClusterHealthResponse), + ConnectClusterNodes(ConnectClusterNodesResponse), + GetClusterLayout(GetClusterLayoutResponse), + UpdateClusterLayout(UpdateClusterLayoutResponse), + ApplyClusterLayout(ApplyClusterLayoutResponse), + RevertClusterLayout(RevertClusterLayoutResponse), +} + +// ********************************************** +// Metrics-related endpoints +// ********************************************** + +// TODO: do we want this here ?? + +// ---- Metrics ---- + +pub struct MetricsRequest; + +// ---- Health ---- + +pub struct HealthRequest; + +// ********************************************** +// Cluster operations +// ********************************************** + +// ---- GetClusterStatus ---- + +pub struct GetClusterStatusRequest; + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetClusterStatusResponse { + pub node: String, + pub garage_version: &'static str, + pub garage_features: Option<&'static [&'static str]>, + pub rust_version: &'static str, + pub db_engine: String, + pub layout_version: u64, + pub nodes: Vec<NodeResp>, +} + +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct NodeResp { + pub id: String, + pub role: Option<NodeRoleResp>, + pub addr: Option<SocketAddr>, + pub hostname: Option<String>, + pub is_up: bool, + pub last_seen_secs_ago: Option<u64>, + pub draining: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub data_partition: Option<FreeSpaceResp>, + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata_partition: Option<FreeSpaceResp>, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NodeRoleResp { + pub id: String, + pub zone: String, + pub capacity: Option<u64>, + pub tags: Vec<String>, +} + +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct FreeSpaceResp { + pub available: u64, + pub total: u64, +} + +// ---- GetClusterHealth ---- + +pub struct GetClusterHealthRequest; + +#[derive(Debug, Clone, Copy, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetClusterHealthResponse { + pub status: &'static str, + pub known_nodes: usize, + pub connected_nodes: usize, + pub storage_nodes: usize, + pub storage_nodes_ok: usize, + pub partitions: usize, + pub partitions_quorum: usize, + pub partitions_all_ok: usize, +} + +// ---- ConnectClusterNodes ---- + +#[derive(Debug, Clone, Deserialize)] +pub struct ConnectClusterNodesRequest(pub Vec<String>); + +#[derive(Serialize)] +pub struct ConnectClusterNodesResponse(pub Vec<ConnectClusterNodeResponse>); + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ConnectClusterNodeResponse { + pub success: bool, + pub error: Option<String>, +} + +// ---- GetClusterLayout ---- + +pub struct GetClusterLayoutRequest; + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetClusterLayoutResponse { + pub version: u64, + pub roles: Vec<NodeRoleResp>, + pub staged_role_changes: Vec<NodeRoleChange>, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NodeRoleChange { + pub id: String, + #[serde(flatten)] + pub action: NodeRoleChangeEnum, +} + +#[derive(Serialize, Deserialize)] +#[serde(untagged)] +pub enum NodeRoleChangeEnum { + #[serde(rename_all = "camelCase")] + Remove { remove: bool }, + #[serde(rename_all = "camelCase")] + Update { + zone: String, + capacity: Option<u64>, + tags: Vec<String>, + }, +} + +// ---- UpdateClusterLayout ---- + +#[derive(Deserialize)] +pub struct UpdateClusterLayoutRequest(pub Vec<NodeRoleChange>); + +#[derive(Serialize)] +pub struct UpdateClusterLayoutResponse(pub GetClusterLayoutResponse); + +// ---- ApplyClusterLayout ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ApplyClusterLayoutRequest { + pub version: u64, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ApplyClusterLayoutResponse { + pub message: Vec<String>, + pub layout: GetClusterLayoutResponse, +} + +// ---- RevertClusterLayout ---- + +pub struct RevertClusterLayoutRequest; + +#[derive(Serialize)] +pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse); + +// ********************************************** +// Access key operations +// ********************************************** + +// ---- ListKeys ---- + +pub struct ListKeysRequest; + +#[derive(Serialize)] +pub struct ListKeysResponse(pub Vec<ListKeysResponseItem>); + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ListKeysResponseItem { + pub id: String, + pub name: String, +} + +// ---- GetKeyInfo ---- + +pub struct GetKeyInfoRequest { + pub id: Option<String>, + pub search: Option<String>, + pub show_secret_key: bool, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetKeyInfoResponse { + pub name: String, + pub access_key_id: String, + #[serde(skip_serializing_if = "is_default")] + pub secret_access_key: Option<String>, + pub permissions: KeyPerm, + pub buckets: Vec<KeyInfoBucketResponse>, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct KeyPerm { + #[serde(default)] + pub create_bucket: bool, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KeyInfoBucketResponse { + pub id: String, + pub global_aliases: Vec<String>, + pub local_aliases: Vec<String>, + pub permissions: ApiBucketKeyPerm, +} + +#[derive(Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct ApiBucketKeyPerm { + #[serde(default)] + pub read: bool, + #[serde(default)] + pub write: bool, + #[serde(default)] + pub owner: bool, +} + +// ---- CreateKey ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateKeyRequest { + pub name: Option<String>, +} + +#[derive(Serialize)] +pub struct CreateKeyResponse(pub GetKeyInfoResponse); + +// ---- ImportKey ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ImportKeyRequest { + pub access_key_id: String, + pub secret_access_key: String, + pub name: Option<String>, +} + +#[derive(Serialize)] +pub struct ImportKeyResponse(pub GetKeyInfoResponse); + +// ---- UpdateKey ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UpdateKeyRequest { + // TODO: id (get parameter) goes here + pub name: Option<String>, + pub allow: Option<KeyPerm>, + pub deny: Option<KeyPerm>, +} + +#[derive(Serialize)] +pub struct UpdateKeyResponse(pub GetKeyInfoResponse); + +// ---- DeleteKey ---- + +pub struct DeleteKeyRequest { + pub id: String, +} + +pub struct DeleteKeyResponse; + +// ********************************************** +// Bucket operations +// ********************************************** + +// ---- ListBuckets ---- + +pub struct ListBucketsRequest; + +pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>); + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ListBucketsResponseItem { + pub id: String, + pub global_aliases: Vec<String>, + pub local_aliases: Vec<BucketLocalAlias>, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct BucketLocalAlias { + pub access_key_id: String, + pub alias: String, +} + +// ---- GetBucketInfo ---- + +pub struct GetBucketInfoRequest { + pub id: Option<String>, + pub global_alias: Option<String>, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBucketInfoResponse { + pub id: String, + pub global_aliases: Vec<String>, + pub website_access: bool, + #[serde(default)] + pub website_config: Option<GetBucketInfoWebsiteResponse>, + pub keys: Vec<GetBucketInfoKey>, + pub objects: i64, + pub bytes: i64, + pub unfinished_uploads: i64, + pub unfinished_multipart_uploads: i64, + pub unfinished_multipart_upload_parts: i64, + pub unfinished_multipart_upload_bytes: i64, + pub quotas: ApiBucketQuotas, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBucketInfoWebsiteResponse { + pub index_document: String, + pub error_document: Option<String>, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBucketInfoKey { + pub access_key_id: String, + pub name: String, + pub permissions: ApiBucketKeyPerm, + pub bucket_local_aliases: Vec<String>, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ApiBucketQuotas { + pub max_size: Option<u64>, + pub max_objects: Option<u64>, +} + +// ---- CreateBucket ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateBucketRequest { + pub global_alias: Option<String>, + pub local_alias: Option<CreateBucketLocalAlias>, +} + +#[derive(Serialize)] +pub struct CreateBucketResponse(GetBucketInfoResponse); + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateBucketLocalAlias { + pub access_key_id: String, + pub alias: String, + #[serde(default)] + pub allow: ApiBucketKeyPerm, +} + +// ---- UpdateBucket ---- + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UpdateBucketRequest { + pub website_access: Option<UpdateBucketWebsiteAccess>, + pub quotas: Option<ApiBucketQuotas>, +} + +#[derive(Serialize)] +pub struct UpdateBucketResponse(GetBucketInfoResponse); + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UpdateBucketWebsiteAccess { + pub enabled: bool, + pub index_document: Option<String>, + pub error_document: Option<String>, +} + +// ---- DeleteBucket ---- + +pub struct DeleteBucketRequest { + pub id: String, +} + +pub struct DeleteBucketResponse; + +// ********************************************** +// Operations on permissions for keys on buckets +// ********************************************** + +// ---- BucketAllowKey ---- + +pub struct BucketAllowKeyRequest(pub BucketKeyPermChangeRequest); + +pub struct BucketAllowKeyResponse; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BucketKeyPermChangeRequest { + pub bucket_id: String, + pub access_key_id: String, + pub permissions: ApiBucketKeyPerm, +} + +// ---- BucketDenyKey ---- + +pub struct BucketDenyKeyRequest(pub BucketKeyPermChangeRequest); + +pub struct BucketDenyKeyResponse; + +// ********************************************** +// Operations on bucket aliases +// ********************************************** + +// ---- GlobalAliasBucket ---- + +pub struct GlobalAliasBucketRequest { + pub id: String, + pub alias: String, +} + +pub struct GlobalAliasBucketReponse; + +// ---- GlobalUnaliasBucket ---- + +pub struct GlobalUnaliasBucketRequest { + pub id: String, + pub alias: String, +} + +pub struct GlobalUnaliasBucketReponse; + +// ---- LocalAliasBucket ---- + +pub struct LocalAliasBucketRequest { + pub id: String, + pub access_key_id: String, + pub alias: String, +} + +pub struct LocalAliasBucketReponse; + +// ---- LocalUnaliasBucket ---- + +pub struct LocalUnaliasBucketRequest { + pub id: String, + pub access_key_id: String, + pub alias: String, +} + +pub struct LocalUnaliasBucketReponse; |