use crate::types::{Link, ProcessorResponse};
use crate::{CloudClient, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use typed_builder::TypedBuilder;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BaseSubscriptionUpdateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionUpdateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub payment_method_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub payment_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionSpec {
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cloud_account_id: Option<i32>,
pub regions: Vec<SubscriptionRegionSpec>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CustomerManagedKey {
pub resource_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LocalThroughput {
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub write_operations_per_second: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub read_operations_per_second: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CrdbRegionSpec {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub local_throughput_measurement: Option<LocalThroughput>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionUpdateCMKRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deletion_grace_period: Option<String>,
pub customer_managed_keys: Vec<CustomerManagedKey>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubscriptionPricings {
#[serde(skip_serializing_if = "Option::is_none")]
pub pricing: Option<Vec<SubscriptionPricing>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseThroughputSpec {
pub by: String,
pub value: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseModuleSpec {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<HashMap<String, Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CidrAllowlistUpdateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cidr_ips: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub security_group_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubscriptionMaintenanceWindowsSpec {
pub mode: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub windows: Option<Vec<MaintenanceWindowSpec>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MaintenanceWindowSkipStatus {
#[serde(skip_serializing_if = "Option::is_none")]
pub remaining_skips: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_skip_end: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ActiveActiveSubscriptionRegions {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<Vec<Link>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionPricing {
#[serde(skip_serializing_if = "Option::is_none")]
pub database_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_details: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity_measurement: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price_per_unit: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price_currency: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price_period: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionCreateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub dry_run: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub deployment_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub payment_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub payment_method_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub memory_storage: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub persistent_storage_encryption_type: Option<String>,
pub cloud_providers: Vec<SubscriptionSpec>,
pub databases: Vec<SubscriptionDatabaseSpec>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub redis_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CustomerManagedKeyAccessDetails {
#[serde(skip_serializing_if = "Option::is_none")]
pub redis_service_account: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub google_predefined_roles: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub google_custom_permissions: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redis_iam_role: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub required_key_policy_statements: Option<HashMap<String, Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deletion_grace_period_options: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionDatabaseSpec {
pub name: String,
pub protocol: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_limit_in_gb: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dataset_size_in_gb: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub support_oss_cluster_api: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data_persistence: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub replication: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub throughput_measurement: Option<DatabaseThroughputSpec>,
#[serde(skip_serializing_if = "Option::is_none")]
pub local_throughput_measurement: Option<Vec<LocalThroughput>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub modules: Option<Vec<DatabaseModuleSpec>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub average_item_size_in_bytes: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub resp_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redis_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sharding_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query_performance_factor: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionRegionNetworkingSpec {
#[serde(skip_serializing_if = "Option::is_none")]
pub deployment_cidr: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vpc_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subnet_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub security_group_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RedisVersion {
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub eol_date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_preview: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_default: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MaintenanceWindow {
#[serde(skip_serializing_if = "Option::is_none")]
pub days: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_hour: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_in_hours: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CloudDetail {
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cloud_account_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub aws_account_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_size_in_gb: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub regions: Option<Vec<SubscriptionRegion>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionRegion {
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub networking: Option<Vec<SubscriptionNetworking>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub preferred_availability_zones: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub multiple_availability_zones: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionNetworking {
#[serde(skip_serializing_if = "Option::is_none")]
pub deployment_cidr: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vpc_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subnet_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Subscription {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub payment_method_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub payment_method_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub payment_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_storage: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub persistent_storage_encryption_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deployment_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub number_of_databases: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cloud_details: Option<Vec<CloudDetail>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pricing: Option<Vec<SubscriptionPricing>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redis_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deletion_grace_period: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer_managed_key_access_details: Option<CustomerManagedKeyAccessDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub storage_encryption: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub public_endpoint_access: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_timestamp: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<Vec<Link>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MaintenanceWindowSpec {
pub start_hour: i32,
pub duration_in_hours: i32,
pub days: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountSubscriptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub account_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscriptions: Option<Vec<Subscription>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<Vec<Link>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ActiveActiveRegionCreateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vpc_id: Option<String>,
pub deployment_cidr: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub dry_run: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub databases: Option<Vec<CrdbRegionSpec>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub resp_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer_managed_key_resource_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RedisVersions {
#[serde(skip_serializing_if = "Option::is_none")]
pub redis_versions: Option<Vec<RedisVersion>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ActiveActiveRegionDeleteRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub regions: Option<Vec<ActiveActiveRegionToDelete>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dry_run: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActiveActiveRegionToDelete {
#[serde(skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskStateUpdate {
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub response: Option<ProcessorResponse>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<Vec<Link>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionRegionSpec {
pub region: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub multiple_availability_zones: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub preferred_availability_zones: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub networking: Option<SubscriptionRegionNetworkingSpec>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionMaintenanceWindows {
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_zone: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub windows: Option<Vec<MaintenanceWindow>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub skip_status: Option<MaintenanceWindowSkipStatus>,
}
pub struct SubscriptionHandler {
client: CloudClient,
}
impl SubscriptionHandler {
#[must_use]
pub fn new(client: CloudClient) -> Self {
Self { client }
}
pub async fn get_all_subscriptions(&self) -> Result<AccountSubscriptions> {
self.client.get("/subscriptions").await
}
pub async fn create_subscription(
&self,
request: &SubscriptionCreateRequest,
) -> Result<TaskStateUpdate> {
self.client.post("/subscriptions", request).await
}
pub async fn get_redis_versions(&self, subscription_id: Option<i32>) -> Result<RedisVersions> {
let mut query = Vec::new();
if let Some(v) = subscription_id {
query.push(format!("subscriptionId={v}"));
}
let query_string = if query.is_empty() {
String::new()
} else {
format!("?{}", query.join("&"))
};
self.client
.get(&format!("/subscriptions/redis-versions{query_string}"))
.await
}
pub async fn delete_subscription_by_id(&self, subscription_id: i32) -> Result<TaskStateUpdate> {
let response = self
.client
.delete_raw(&format!("/subscriptions/{subscription_id}"))
.await?;
serde_json::from_value(response).map_err(Into::into)
}
pub async fn get_subscription_by_id(&self, subscription_id: i32) -> Result<Subscription> {
self.client
.get(&format!("/subscriptions/{subscription_id}"))
.await
}
pub async fn update_subscription(
&self,
subscription_id: i32,
request: &BaseSubscriptionUpdateRequest,
) -> Result<TaskStateUpdate> {
self.client
.put(&format!("/subscriptions/{subscription_id}"), request)
.await
}
pub async fn get_cidr_allowlist(&self, subscription_id: i32) -> Result<TaskStateUpdate> {
self.client
.get(&format!("/subscriptions/{subscription_id}/cidr"))
.await
}
pub async fn update_subscription_cidr_allowlist(
&self,
subscription_id: i32,
request: &CidrAllowlistUpdateRequest,
) -> Result<TaskStateUpdate> {
self.client
.put(&format!("/subscriptions/{subscription_id}/cidr"), request)
.await
}
pub async fn get_subscription_maintenance_windows(
&self,
subscription_id: i32,
) -> Result<SubscriptionMaintenanceWindows> {
self.client
.get(&format!(
"/subscriptions/{subscription_id}/maintenance-windows"
))
.await
}
pub async fn update_subscription_maintenance_windows(
&self,
subscription_id: i32,
request: &SubscriptionMaintenanceWindowsSpec,
) -> Result<TaskStateUpdate> {
self.client
.put(
&format!("/subscriptions/{subscription_id}/maintenance-windows"),
request,
)
.await
}
pub async fn get_subscription_pricing(
&self,
subscription_id: i32,
) -> Result<SubscriptionPricings> {
self.client
.get(&format!("/subscriptions/{subscription_id}/pricing"))
.await
}
pub async fn delete_regions_from_active_active_subscription(
&self,
subscription_id: i32,
request: &ActiveActiveRegionDeleteRequest,
) -> Result<TaskStateUpdate> {
let _ = request; let response = self
.client
.delete_raw(&format!("/subscriptions/{subscription_id}/regions"))
.await?;
serde_json::from_value(response).map_err(Into::into)
}
pub async fn get_regions_from_active_active_subscription(
&self,
subscription_id: i32,
) -> Result<ActiveActiveSubscriptionRegions> {
self.client
.get(&format!("/subscriptions/{subscription_id}/regions"))
.await
}
pub async fn add_new_region_to_active_active_subscription(
&self,
subscription_id: i32,
request: &ActiveActiveRegionCreateRequest,
) -> Result<TaskStateUpdate> {
self.client
.post(
&format!("/subscriptions/{subscription_id}/regions"),
request,
)
.await
}
}