use std::collections::HashMap;
use std::ops::Not;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use serde_with::skip_serializing_none;
use uuid::Uuid;
pub const VERSION: &str = "2020-12-31";
pub static AWS_SUPPORTED_REGIONS: &[&str] = &[
"ap-northeast-1",
"ap-northeast-2",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-1",
"us-west-2",
];
pub static AZURE_SUPPORTED_REGIONS: &[&str] = &[
"centralus",
"eastus",
"eastus2",
"francecentral",
"japaneast",
"northeurope",
"southeastasia",
"uksouth",
"westeurope",
"westus2",
];
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Realm {
pub name: String,
pub created: DateTime<Utc>,
#[serde(flatten)]
pub realm: RealmType,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Realms {
pub realms: Vec<Realm>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RealmCreate {
pub name: String,
#[serde(flatten)]
pub realm: RealmTypeCreate,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RealmType {
Aws {
role_arn: String,
},
Azure {
subscription_id: String,
tenant_id: String,
client_id: String,
},
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(untagged)]
pub enum RealmTypeCreate {
Aws {
r#type: String,
role_arn: String,
external_id: String,
},
Azure {
r#type: String,
subscription_id: String,
tenant_id: String,
client_id: String,
client_secret: String,
},
}
#[skip_serializing_none]
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct VolumeCreate {
pub id: Option<Uuid>,
pub name: String,
pub size_gb: Option<u64>,
pub description: Option<String>,
pub replicas: Vec<ReplicaCreate>,
pub source: Option<VolumeSource>,
}
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct VolumeCreateExt {
pub id: Option<Uuid>,
pub name: String,
pub size_gb: Option<u64>,
pub provisioned_iops: Option<u64>,
pub description: Option<String>,
pub replicas: Vec<ReplicaCreate>,
pub source: Option<VolumeSourceExt>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct PrivateLinkNlb {
pub private_link_endpoint_id: String,
pub vendor_nlb: VendorPrivateLinkNlb,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum VendorPrivateLinkNlb {
Aws(AwsPrivateLink),
Azure(AzurePrivateLink),
}
impl Default for VendorPrivateLinkNlb {
fn default() -> Self {
Self::Aws(AwsPrivateLink::default())
}
}
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct AwsPrivateLink {
pub service_id: String,
pub subnet: String,
pub vpc: String,
pub target_group: String,
}
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct AzurePrivateLink {
pub service_id: String,
pub backend_subnet_id: String,
pub loadbalancer_id: String,
}
impl From<VolumeCreate> for Option<VolumeCreateExt> {
fn from(volume_create: VolumeCreate) -> Self {
Some(VolumeCreateExt {
id: volume_create.id,
description: volume_create.description,
name: volume_create.name,
size_gb: volume_create.size_gb,
provisioned_iops: None,
replicas: volume_create.replicas,
source: volume_create.source.map(VolumeSourceExt::from),
})
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum VolumeSource {
AwsSnapshot(AwsSnapshot),
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum VolumeSourceExt {
AwsSnapshot(AwsSnapshot),
NativeDevices(HashMap<String, Option<String>>),
}
impl From<VolumeSource> for VolumeSourceExt {
fn from(volume_source: VolumeSource) -> Self {
match volume_source {
VolumeSource::AwsSnapshot(snapshot) => Self::AwsSnapshot(snapshot),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct AwsSnapshot {
pub realm: String,
pub region: String,
pub id: String,
}
impl Default for ReplicaCreateRealm {
fn default() -> Self {
Self::Aws(AwsReplicaCreateRealm {
realm: String::default(),
region: String::default(),
subnet: String::default(),
})
}
}
#[skip_serializing_none]
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct ReplicaCreate {
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: Option<String>,
#[serde(flatten)]
pub realm: ReplicaCreateRealm,
pub iscsi_portal: Option<String>,
#[serde(default, skip_serializing_if = "Not::not")]
pub primary: bool,
pub private_link: Option<PrivateLinkNlb>,
}
#[derive(Default, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct AwsReplicaCreate {
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: Option<String>,
#[serde(flatten)]
pub realm: AwsReplicaCreateRealm,
pub iscsi_portal: Option<String>,
#[serde(default)]
pub primary: bool,
}
#[derive(Default, Clone, Debug, Deserialize, Serialize)]
pub struct AzureReplicaCreate {
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: Option<String>,
#[serde(flatten)]
pub realm: AzureReplicaCreateRealm,
pub iscsi_portal: Option<String>,
#[serde(default)]
pub primary: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ReplicaCreateRealm {
Aws(AwsReplicaCreateRealm),
Azure(AzureReplicaCreateRealm),
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
pub struct AwsReplicaCreateRealm {
pub realm: String,
pub region: String,
pub subnet: String,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
pub struct AzureReplicaCreateRealm {
pub realm: String,
pub resource_group: String,
pub subnet: String,
}
impl ReplicaCreateRealm {
pub fn vendor(&self) -> &str {
match self {
Self::Aws { .. } => "aws",
Self::Azure { .. } => "azure",
}
}
pub fn realm(&self) -> String {
match self {
Self::Aws(AwsReplicaCreateRealm { realm, .. }) => realm.clone(),
Self::Azure(AzureReplicaCreateRealm { realm, .. }) => realm.clone(),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Volume {
pub name: String,
pub id: Uuid,
pub description: String,
pub size_gb: u64,
pub source: Option<VolumeSource>,
pub replicas: Vec<Replica>,
pub iqn: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub job: Option<Uuid>,
pub created: Option<DateTime<Utc>>,
pub modified: Option<DateTime<Utc>>,
pub status: Status,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct Status {
pub value: String,
pub message: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Replica {
#[serde(default)]
pub name: String,
pub description: String,
#[serde(flatten)]
pub realm: ReplicaRealm,
#[serde(default)]
pub primary: bool,
pub iscsi_portal: Option<String>,
#[serde(default)]
pub status: Status,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ReplicaRealm {
Aws {
realm: String,
region: String,
subnet: String,
},
Azure {
realm: String,
resource_group: String,
subnet: String,
},
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct Snapshot {
pub id: String,
pub name: String,
pub created: Option<DateTime<Utc>>,
#[serde(default)]
pub status: Status,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SnapshotCreate {
pub name: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SnapshotExport {
pub id: String,
pub status: Status,
#[serde(flatten)]
pub vendor_export: VendorSnapshotExport,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum VendorSnapshotExport {
Aws(AwsSnapshotExport),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AwsSnapshotExport {
pub realm: String,
pub region: String,
pub id: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SnapshotExportCreate {
Aws(AwsSnapshotExportCreate),
}
impl Default for SnapshotExportCreate {
fn default() -> Self {
Self::Aws(AwsSnapshotExportCreate::default())
}
}
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct AwsSnapshotExportCreate {
pub realm: String,
pub region: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum StatusValue {
Uninitialized,
Provisioning,
Starting,
Syncing,
Stopping,
Deleting,
Reconfiguring,
Online,
Offline,
Degraded,
Error,
}
impl Default for StatusValue {
fn default() -> Self {
Self::Uninitialized
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct JobStatus {
pub value: JobStatusValue,
pub message: Option<String>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum JobStatusValue {
Pending,
InProgress,
Done,
Error,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub struct Job {
pub parent: Option<Uuid>,
pub id: Uuid,
pub r#type: String,
pub created: DateTime<Utc>,
pub modified: DateTime<Utc>,
pub status: Status,
pub details: Map<String, Value>,
pub children: usize,
pub sub_jobs: Vec<Job>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JobAccepted {
pub job_id: Uuid,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Error {
pub http_code: u16,
pub http_status: String,
pub error: Option<serde_json::Value>,
pub message: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum WsEvent {
Job(Job),
Volume(Volume),
}
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct QueryParams {
#[serde(default)]
include: String,
}
impl QueryParams {
pub fn include(&self, field: &str) -> bool {
self.include.split(',').any(|f| f == field)
}
pub fn include_job(&self) -> bool {
self.include("job")
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Version {
pub release: String,
pub name: String,
pub version: String,
pub build: String,
pub profile: String,
pub allocator: String,
pub branch: String,
pub tag: String,
pub commit: String,
pub extra: String,
pub metadata: Vec<String>,
}