redis_cloud/
cloud_accounts.rs

1//! Cloud provider account management operations and models
2//!
3//! This module handles the integration between Redis Cloud and your cloud provider
4//! accounts (AWS, GCP, Azure). It manages cloud account credentials, access keys,
5//! and provider-specific configurations.
6//!
7//! # Overview
8//!
9//! Cloud accounts are the bridge between Redis Cloud and your infrastructure provider.
10//! They store the credentials and permissions needed for Redis Cloud to provision
11//! resources in your cloud environment.
12//!
13//! # Supported Providers
14//!
15//! - **AWS**: Amazon Web Services accounts with IAM roles or access keys
16//! - **GCP**: Google Cloud Platform projects with service accounts
17//! - **Azure**: Microsoft Azure subscriptions with service principals
18//!
19//! # Key Features
20//!
21//! - **Account Registration**: Register cloud provider accounts with Redis Cloud
22//! - **Credential Management**: Securely store and manage cloud credentials
23//! - **Access Key Operations**: Create, update, and delete cloud access keys
24//! - **Provider Details**: Retrieve provider-specific account information
25//! - **Multi-cloud Support**: Manage accounts across different cloud providers
26//!
27//! # API Reference
28//!
29//! All operations in this module map to the Redis Cloud REST API's Cloud Accounts endpoints.
30//! For detailed API documentation, see the [Redis Cloud OpenAPI Specification].
31//!
32//! [Redis Cloud OpenAPI Specification]: https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json
33//!
34//! # Example Usage
35//!
36//! ```no_run
37//! use redis_cloud::{CloudClient, CloudAccountHandler};
38//!
39//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
40//! let client = CloudClient::builder()
41//!     .api_key("your-api-key")
42//!     .api_secret("your-api-secret")
43//!     .build()?;
44//!
45//! let handler = CloudAccountHandler::new(client);
46//!
47//! // List all cloud accounts
48//! let accounts = handler.get_cloud_accounts().await?;
49//!
50//! // Get specific account details (account ID 123)
51//! let account = handler.get_cloud_account_by_id(123).await?;
52//! # Ok(())
53//! # }
54//! ```
55
56use crate::{CloudClient, Result};
57use serde::{Deserialize, Serialize};
58use serde_json::Value;
59use std::collections::HashMap;
60
61// ============================================================================
62// Models
63// ============================================================================
64
65/// Cloud Account definition
66#[derive(Debug, Clone, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct CloudAccountUpdateRequest {
69    /// name
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub name: Option<String>,
72
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub cloud_account_id: Option<i32>,
75
76    /// Cloud provider access key.
77    pub access_key_id: String,
78
79    /// Cloud provider secret key.
80    pub access_secret_key: String,
81
82    /// Cloud provider management console username.
83    pub console_username: String,
84
85    /// Cloud provider management console password.
86    pub console_password: String,
87
88    /// Optional. Cloud provider management console login URL.
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub sign_in_login_url: Option<String>,
91
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub command_type: Option<String>,
94
95    /// Additional fields from the API
96    #[serde(flatten)]
97    pub extra: Value,
98}
99
100/// RedisLabs Cloud Account information
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103/// Cloud Account
104///
105/// Represents a cloud provider account integration with all known API fields
106pub struct CloudAccount {
107    /// Cloud account ID
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub id: Option<i32>,
110
111    /// Cloud account display name
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub name: Option<String>,
114
115    /// Account status (e.g., "active", "error")
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub status: Option<String>,
118
119    /// Cloud provider (e.g., "AWS", "GCP", "Azure")
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub provider: Option<String>,
122
123    /// Cloud provider access key ID
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub access_key_id: Option<String>,
126
127    /// Cloud provider secret key (typically masked in responses)
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub access_secret_key: Option<String>,
130
131    /// AWS Console Role ARN (AWS-specific)
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub aws_console_role_arn: Option<String>,
134
135    /// AWS User ARN (AWS-specific)
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub aws_user_arn: Option<String>,
138
139    /// Cloud provider management console username
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub console_username: Option<String>,
142
143    /// Cloud provider management console password (typically masked)
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub console_password: Option<String>,
146
147    /// Cloud provider management console login URL
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub sign_in_login_url: Option<String>,
150
151    /// HATEOAS links for API navigation
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub links: Option<Vec<HashMap<String, Value>>>,
154
155    /// Only for truly unknown/future API fields
156    #[serde(flatten)]
157    pub extra: Value,
158}
159
160/// Cloud Account definition
161#[derive(Debug, Clone, Serialize, Deserialize)]
162#[serde(rename_all = "camelCase")]
163pub struct CloudAccountCreateRequest {
164    /// Cloud account display name.
165    pub name: String,
166
167    /// Optional. Cloud provider. Default: 'AWS'
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub provider: Option<String>,
170
171    /// Cloud provider access key.
172    pub access_key_id: String,
173
174    /// Cloud provider secret key.
175    pub access_secret_key: String,
176
177    /// Cloud provider management console username.
178    pub console_username: String,
179
180    /// Cloud provider management console password.
181    pub console_password: String,
182
183    /// Cloud provider management console login URL.
184    pub sign_in_login_url: String,
185
186    #[serde(skip_serializing_if = "Option::is_none")]
187    pub command_type: Option<String>,
188
189    /// Additional fields from the API
190    #[serde(flatten)]
191    pub extra: Value,
192}
193
194/// RedisLabs Cloud Accounts information
195///
196/// Response from GET /cloud-accounts containing list of cloud provider integrations
197#[derive(Debug, Clone, Serialize, Deserialize)]
198#[serde(rename_all = "camelCase")]
199pub struct CloudAccounts {
200    /// Account ID
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub account_id: Option<i32>,
203
204    /// List of cloud provider accounts (typically in extra as 'cloudAccounts' array)
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub cloud_accounts: Option<Vec<CloudAccount>>,
207
208    /// HATEOAS links for API navigation
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub links: Option<Vec<HashMap<String, Value>>>,
211
212    /// Only for truly unknown/future API fields
213    #[serde(flatten)]
214    pub extra: Value,
215}
216
217/// ProcessorResponse
218#[derive(Debug, Clone, Serialize, Deserialize)]
219#[serde(rename_all = "camelCase")]
220pub struct ProcessorResponse {
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub resource_id: Option<i32>,
223
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub additional_resource_id: Option<i32>,
226
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub resource: Option<HashMap<String, Value>>,
229
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub error: Option<String>,
232
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub additional_info: Option<String>,
235
236    /// Additional fields from the API
237    #[serde(flatten)]
238    pub extra: Value,
239}
240
241/// TaskStateUpdate
242#[derive(Debug, Clone, Serialize, Deserialize)]
243#[serde(rename_all = "camelCase")]
244pub struct TaskStateUpdate {
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub task_id: Option<String>,
247
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub command_type: Option<String>,
250
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub status: Option<String>,
253
254    #[serde(skip_serializing_if = "Option::is_none")]
255    pub description: Option<String>,
256
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub timestamp: Option<String>,
259
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub response: Option<ProcessorResponse>,
262
263    /// HATEOAS links
264    #[serde(skip_serializing_if = "Option::is_none")]
265    pub links: Option<Vec<HashMap<String, Value>>>,
266
267    /// Additional fields from the API
268    #[serde(flatten)]
269    pub extra: Value,
270}
271
272// ============================================================================
273// Handler
274// ============================================================================
275
276/// Handler for cloud provider account operations
277///
278/// Manages integration with AWS, GCP, and Azure accounts, including
279/// credential management and provider-specific configurations.
280pub struct CloudAccountsHandler {
281    client: CloudClient,
282}
283
284impl CloudAccountsHandler {
285    /// Create a new handler
286    pub fn new(client: CloudClient) -> Self {
287        Self { client }
288    }
289
290    /// Get cloud accounts
291    ///
292    /// Gets a list of all configured cloud accounts.
293    ///
294    /// # API Endpoint
295    ///
296    /// `GET /cloud-accounts`
297    ///
298    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccounts`
299    pub async fn get_cloud_accounts(&self) -> Result<CloudAccounts> {
300        self.client.get("/cloud-accounts").await
301    }
302
303    /// Create cloud account
304    ///
305    /// Creates a cloud account.
306    ///
307    /// # API Endpoint
308    ///
309    /// `POST /cloud-accounts`
310    ///
311    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `createCloudAccount`
312    pub async fn create_cloud_account(
313        &self,
314        request: &CloudAccountCreateRequest,
315    ) -> Result<TaskStateUpdate> {
316        self.client.post("/cloud-accounts", request).await
317    }
318
319    /// Delete cloud account
320    ///
321    /// Deletes a cloud account.
322    ///
323    /// # API Endpoint
324    ///
325    /// `DELETE /cloud-accounts/{cloudAccountId}`
326    ///
327    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `deleteCloudAccount`
328    pub async fn delete_cloud_account(&self, cloud_account_id: i32) -> Result<TaskStateUpdate> {
329        let response = self
330            .client
331            .delete_raw(&format!("/cloud-accounts/{}", cloud_account_id))
332            .await?;
333        serde_json::from_value(response).map_err(Into::into)
334    }
335
336    /// Get a single cloud account
337    ///
338    /// Gets details on a single cloud account.
339    ///
340    /// # API Endpoint
341    ///
342    /// `GET /cloud-accounts/{cloudAccountId}`
343    ///
344    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccountById`
345    pub async fn get_cloud_account_by_id(&self, cloud_account_id: i32) -> Result<CloudAccount> {
346        self.client
347            .get(&format!("/cloud-accounts/{}", cloud_account_id))
348            .await
349    }
350
351    /// Update cloud account
352    ///
353    /// Updates cloud account details.
354    ///
355    /// # API Endpoint
356    ///
357    /// `PUT /cloud-accounts/{cloudAccountId}`
358    ///
359    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `updateCloudAccount`
360    pub async fn update_cloud_account(
361        &self,
362        cloud_account_id: i32,
363        request: &CloudAccountUpdateRequest,
364    ) -> Result<TaskStateUpdate> {
365        self.client
366            .put(&format!("/cloud-accounts/{}", cloud_account_id), request)
367            .await
368    }
369}