use std::collections::HashMap;
use std::convert::TryFrom;
use std::net::SocketAddr;
use std::sync::Arc;
use chrono::{DateTime, Utc};
use paste::paste;
use serde::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
use garage_rpc::*;
use garage_model::garage::Garage;
use garage_api_common::{common_error::CommonError, helpers::is_default};
use crate::api_server::{find_matching_nodes, AdminRpc, AdminRpcResponse};
use crate::error::Error;
use crate::macros::*;
use crate::{Admin, RequestHandler};
admin_endpoints![
@special Options,
@special CheckDomain,
@special Health,
@special Metrics,
GetClusterStatus,
GetClusterHealth,
GetClusterStatistics,
ConnectClusterNodes,
ListAdminTokens,
GetAdminTokenInfo,
CreateAdminToken,
UpdateAdminToken,
DeleteAdminToken,
GetCurrentAdminTokenInfo,
GetClusterLayout,
GetClusterLayoutHistory,
UpdateClusterLayout,
PreviewClusterLayoutChanges,
ApplyClusterLayout,
RevertClusterLayout,
ClusterLayoutSkipDeadNodes,
ListKeys,
GetKeyInfo,
CreateKey,
ImportKey,
UpdateKey,
DeleteKey,
ListBuckets,
GetBucketInfo,
CreateBucket,
UpdateBucket,
DeleteBucket,
CleanupIncompleteUploads,
InspectObject,
AllowBucketKey,
DenyBucketKey,
AddBucketAlias,
RemoveBucketAlias,
GetNodeInfo,
GetNodeStatistics,
CreateMetadataSnapshot,
LaunchRepairOperation,
ListWorkers,
GetWorkerInfo,
GetWorkerVariable,
SetWorkerVariable,
ListBlockErrors,
GetBlockInfo,
RetryBlockResync,
PurgeBlocks,
];
local_admin_endpoints![
GetNodeInfo,
GetNodeStatistics,
CreateMetadataSnapshot,
LaunchRepairOperation,
ListWorkers,
GetWorkerInfo,
GetWorkerVariable,
SetWorkerVariable,
ListBlockErrors,
GetBlockInfo,
RetryBlockResync,
PurgeBlocks,
];
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiRequest<RB> {
pub node: String,
pub body: RB,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct MultiResponse<RB> {
pub success: HashMap<String, RB>,
pub error: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct MultiRequestQueryParams {
pub node: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptionsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct CheckDomainRequest {
pub domain: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthRequest;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsRequest;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterStatusRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetClusterStatusResponse {
pub layout_version: u64,
pub nodes: Vec<NodeResp>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NodeResp {
pub id: String,
pub garage_version: Option<String>,
#[schema(value_type = Option<String>)]
pub addr: Option<SocketAddr>,
pub hostname: Option<String>,
pub is_up: bool,
pub last_seen_secs_ago: Option<u64>,
pub role: Option<NodeAssignedRole>,
pub draining: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub data_partition: Option<FreeSpaceResp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata_partition: Option<FreeSpaceResp>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NodeAssignedRole {
pub zone: String,
pub tags: Vec<String>,
pub capacity: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct FreeSpaceResp {
pub available: u64,
pub total: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterHealthRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetClusterHealthResponse {
pub status: String,
pub known_nodes: usize,
pub connected_nodes: usize,
pub storage_nodes: usize,
pub storage_nodes_up: usize,
pub partitions: usize,
pub partitions_quorum: usize,
pub partitions_all_ok: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct GetClusterStatisticsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct GetClusterStatisticsResponse {
pub freeform: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ConnectClusterNodesRequest(pub Vec<String>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ConnectClusterNodesResponse(pub Vec<ConnectNodeResponse>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ConnectNodeResponse {
pub success: bool,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListAdminTokensRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ListAdminTokensResponse(pub Vec<GetAdminTokenInfoResponse>);
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
#[serde(rename_all = "camelCase")]
pub struct GetAdminTokenInfoRequest {
pub id: Option<String>,
pub search: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetAdminTokenInfoResponse {
pub id: Option<String>,
pub created: Option<DateTime<Utc>>,
pub name: String,
pub expiration: Option<DateTime<Utc>>,
pub expired: bool,
pub scope: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateAdminTokenRequest(pub UpdateAdminTokenRequestBody);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateAdminTokenResponse {
pub secret_token: String,
#[serde(flatten)]
pub info: GetAdminTokenInfoResponse,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct UpdateAdminTokenRequest {
pub id: String,
#[param(ignore = true)]
pub body: UpdateAdminTokenRequestBody,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAdminTokenRequestBody {
pub name: Option<String>,
pub expiration: Option<DateTime<Utc>>,
#[serde(default)]
pub never_expires: bool,
pub scope: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateAdminTokenResponse(pub GetAdminTokenInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct DeleteAdminTokenRequest {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteAdminTokenResponse;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetCurrentAdminTokenInfoRequest {
pub admin_token: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetCurrentAdminTokenInfoResponse(pub GetAdminTokenInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterLayoutRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetClusterLayoutResponse {
pub version: u64,
pub roles: Vec<LayoutNodeRole>,
pub parameters: LayoutParameters,
pub partition_size: u64,
pub staged_role_changes: Vec<NodeRoleChange>,
pub staged_parameters: Option<LayoutParameters>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LayoutNodeRole {
pub id: String,
pub zone: String,
pub tags: Vec<String>,
pub capacity: Option<u64>,
pub stored_partitions: Option<u64>,
pub usable_capacity: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NodeRoleChange {
pub id: String,
#[serde(flatten)]
pub action: NodeRoleChangeEnum,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(untagged)]
pub enum NodeRoleChangeEnum {
#[serde(rename_all = "camelCase")]
Remove {
remove: bool,
},
#[serde(rename_all = "camelCase")]
Update(NodeAssignedRole),
}
#[derive(Copy, Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LayoutParameters {
pub zone_redundancy: ZoneRedundancy,
}
#[derive(Copy, Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub enum ZoneRedundancy {
AtLeast(usize),
Maximum,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetClusterLayoutHistoryRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetClusterLayoutHistoryResponse {
pub current_version: u64,
pub min_ack: u64,
pub versions: Vec<ClusterLayoutVersion>,
pub update_trackers: Option<HashMap<String, NodeUpdateTrackers>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ClusterLayoutVersion {
pub version: u64,
pub status: ClusterLayoutVersionStatus,
pub storage_nodes: u64,
pub gateway_nodes: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum ClusterLayoutVersionStatus {
Current,
Draining,
Historical,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NodeUpdateTrackers {
pub ack: u64,
pub sync: u64,
pub sync_ack: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateClusterLayoutRequest {
#[serde(default)]
pub roles: Vec<NodeRoleChange>,
#[serde(default)]
pub parameters: Option<LayoutParameters>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateClusterLayoutResponse(pub GetClusterLayoutResponse);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PreviewClusterLayoutChangesRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(untagged)]
pub enum PreviewClusterLayoutChangesResponse {
#[serde(rename_all = "camelCase")]
Error {
error: String,
},
#[serde(rename_all = "camelCase")]
Success {
message: Vec<String>,
new_layout: GetClusterLayoutResponse,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ApplyClusterLayoutRequest {
pub version: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ApplyClusterLayoutResponse {
pub message: Vec<String>,
pub layout: GetClusterLayoutResponse,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RevertClusterLayoutRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct RevertClusterLayoutResponse(pub GetClusterLayoutResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ClusterLayoutSkipDeadNodesRequest {
pub version: u64,
pub allow_missing_data: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ClusterLayoutSkipDeadNodesResponse {
pub ack_updated: Vec<String>,
pub sync_updated: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListKeysRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ListKeysResponse(pub Vec<ListKeysResponseItem>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ListKeysResponseItem {
pub id: String,
pub name: String,
pub created: Option<DateTime<Utc>>,
pub expiration: Option<DateTime<Utc>>,
pub expired: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
#[serde(rename_all = "camelCase")]
pub struct GetKeyInfoRequest {
pub id: Option<String>,
pub search: Option<String>,
#[serde(default)]
pub show_secret_key: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetKeyInfoResponse {
pub access_key_id: String,
pub created: Option<DateTime<Utc>>,
pub name: String,
pub expiration: Option<DateTime<Utc>>,
pub expired: bool,
#[serde(default, skip_serializing_if = "is_default")]
pub secret_access_key: Option<String>,
pub permissions: KeyPerm,
pub buckets: Vec<KeyInfoBucketResponse>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct KeyPerm {
#[serde(default)]
pub create_bucket: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct KeyInfoBucketResponse {
pub id: String,
pub global_aliases: Vec<String>,
pub local_aliases: Vec<String>,
pub permissions: ApiBucketKeyPerm,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ApiBucketKeyPerm {
#[serde(default)]
pub read: bool,
#[serde(default)]
pub write: bool,
#[serde(default)]
pub owner: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateKeyRequest(pub UpdateKeyRequestBody);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateKeyResponse(pub GetKeyInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ImportKeyRequest {
pub access_key_id: String,
pub secret_access_key: String,
pub name: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ImportKeyResponse(pub GetKeyInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct UpdateKeyRequest {
pub id: String,
#[param(ignore = true)]
pub body: UpdateKeyRequestBody,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateKeyResponse(pub GetKeyInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateKeyRequestBody {
pub name: Option<String>,
pub expiration: Option<DateTime<Utc>>,
#[serde(default)]
pub never_expires: bool,
pub allow: Option<KeyPerm>,
pub deny: Option<KeyPerm>,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct DeleteKeyRequest {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteKeyResponse;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListBucketsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ListBucketsResponseItem {
pub id: String,
pub created: DateTime<Utc>,
pub global_aliases: Vec<String>,
pub local_aliases: Vec<BucketLocalAlias>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BucketLocalAlias {
pub access_key_id: String,
pub alias: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
#[serde(rename_all = "camelCase")]
pub struct GetBucketInfoRequest {
pub id: Option<String>,
pub global_alias: Option<String>,
pub search: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetBucketInfoResponse {
pub id: String,
pub created: DateTime<Utc>,
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(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetBucketInfoWebsiteResponse {
pub index_document: String,
pub error_document: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[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(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ApiBucketQuotas {
pub max_size: Option<u64>,
pub max_objects: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateBucketRequest {
pub global_alias: Option<String>,
pub local_alias: Option<CreateBucketLocalAlias>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateBucketResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateBucketLocalAlias {
pub access_key_id: String,
pub alias: String,
#[serde(default)]
pub allow: ApiBucketKeyPerm,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct UpdateBucketRequest {
pub id: String,
#[param(ignore = true)]
pub body: UpdateBucketRequestBody,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateBucketResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBucketRequestBody {
pub website_access: Option<UpdateBucketWebsiteAccess>,
pub quotas: Option<ApiBucketQuotas>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBucketWebsiteAccess {
pub enabled: bool,
pub index_document: Option<String>,
pub error_document: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
pub struct DeleteBucketRequest {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteBucketResponse;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CleanupIncompleteUploadsRequest {
pub bucket_id: String,
pub older_than_secs: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CleanupIncompleteUploadsResponse {
pub uploads_deleted: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, IntoParams)]
#[into_params(parameter_in = Query)]
#[serde(rename_all = "camelCase")]
pub struct InspectObjectRequest {
pub bucket_id: String,
pub key: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct InspectObjectResponse {
pub bucket_id: String,
pub key: String,
pub versions: Vec<InspectObjectVersion>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct InspectObjectVersion {
pub uuid: String,
pub timestamp: DateTime<Utc>,
pub encrypted: bool,
pub uploading: bool,
pub aborted: bool,
pub delete_marker: bool,
pub inline: bool,
pub size: Option<u64>,
pub etag: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub headers: Vec<(String, String)>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub blocks: Vec<InspectObjectBlock>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct InspectObjectBlock {
pub part_number: u64,
pub offset: u64,
pub hash: String,
pub size: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AllowBucketKeyRequest(pub BucketKeyPermChangeRequest);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AllowBucketKeyResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BucketKeyPermChangeRequest {
pub bucket_id: String,
pub access_key_id: String,
pub permissions: ApiBucketKeyPerm,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DenyBucketKeyRequest(pub BucketKeyPermChangeRequest);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DenyBucketKeyResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct AddBucketAliasRequest {
pub bucket_id: String,
#[serde(flatten)]
pub alias: BucketAliasEnum,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AddBucketAliasResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(untagged)]
pub enum BucketAliasEnum {
#[serde(rename_all = "camelCase")]
Global { global_alias: String },
#[serde(rename_all = "camelCase")]
Local {
local_alias: String,
access_key_id: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct RemoveBucketAliasRequest {
pub bucket_id: String,
#[serde(flatten)]
pub alias: BucketAliasEnum,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LocalGetNodeInfoRequest;
#[derive(Debug, Clone, Serialize, Deserialize, Default, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalGetNodeInfoResponse {
pub node_id: String,
pub garage_version: String,
pub garage_features: Option<Vec<String>>,
pub rust_version: String,
pub db_engine: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LocalGetNodeStatisticsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalGetNodeStatisticsResponse {
pub freeform: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LocalCreateMetadataSnapshotRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalCreateMetadataSnapshotResponse;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalLaunchRepairOperationRequest {
pub repair_type: RepairType,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub enum RepairType {
Tables,
Blocks,
Versions,
MultipartUploads,
BlockRefs,
BlockRc,
Rebalance,
Scrub(ScrubCommand),
Aliases,
ClearResyncQueue,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub enum ScrubCommand {
Start,
Pause,
Resume,
Cancel,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalLaunchRepairOperationResponse;
#[derive(Debug, Clone, Serialize, Deserialize, Default, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalListWorkersRequest {
#[serde(default)]
pub busy_only: bool,
#[serde(default)]
pub error_only: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalListWorkersResponse(pub Vec<WorkerInfoResp>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct WorkerInfoResp {
pub id: u64,
pub name: String,
pub state: WorkerStateResp,
pub errors: u64,
pub consecutive_errors: u64,
pub last_error: Option<WorkerLastError>,
pub tranquility: Option<u32>,
pub progress: Option<String>,
pub queue_length: Option<u64>,
pub persistent_errors: Option<u64>,
pub freeform: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub enum WorkerStateResp {
Busy,
#[serde(rename_all = "camelCase")]
Throttled {
duration_secs: f32,
},
Idle,
Done,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct WorkerLastError {
pub message: String,
pub secs_ago: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalGetWorkerInfoRequest {
pub id: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalGetWorkerInfoResponse(pub WorkerInfoResp);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalGetWorkerVariableRequest {
pub variable: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalGetWorkerVariableResponse(pub HashMap<String, String>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalSetWorkerVariableRequest {
pub variable: String,
pub value: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalSetWorkerVariableResponse {
pub variable: String,
pub value: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LocalListBlockErrorsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LocalListBlockErrorsResponse(pub Vec<BlockError>);
#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BlockError {
pub block_hash: String,
pub refcount: u64,
pub error_count: u64,
pub last_try_secs_ago: u64,
pub next_try_in_secs: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalGetBlockInfoRequest {
pub block_hash: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalGetBlockInfoResponse {
pub block_hash: String,
pub refcount: u64,
pub versions: Vec<BlockVersion>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BlockVersion {
pub version_id: String,
pub ref_deleted: bool,
pub version_deleted: bool,
pub garbage_collected: bool,
pub backlink: Option<BlockVersionBacklink>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub enum BlockVersionBacklink {
#[serde(rename_all = "camelCase")]
Object { bucket_id: String, key: String },
#[serde(rename_all = "camelCase")]
Upload {
upload_id: String,
upload_deleted: bool,
upload_garbage_collected: bool,
bucket_id: Option<String>,
key: Option<String>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(untagged)]
pub enum LocalRetryBlockResyncRequest {
#[serde(rename_all = "camelCase")]
All { all: bool },
#[serde(rename_all = "camelCase")]
Blocks { block_hashes: Vec<String> },
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalRetryBlockResyncResponse {
pub count: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalPurgeBlocksRequest(pub Vec<String>);
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct LocalPurgeBlocksResponse {
pub blocks_purged: u64,
pub objects_deleted: u64,
pub uploads_deleted: u64,
pub versions_deleted: u64,
pub block_refs_purged: u64,
}