Skip to main content

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::types::Link;
57pub use crate::types::TaskStateUpdate;
58use crate::{CloudClient, Result};
59use serde::{Deserialize, Serialize};
60
61// ============================================================================
62// Models
63// ============================================================================
64
65/// Cloud account update request
66#[derive(Debug, Clone, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct CloudAccountUpdateRequest {
69    /// Cloud account display name
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub name: Option<String>,
72
73    /// Cloud account ID being updated. Server-populated from the path.
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub cloud_account_id: Option<i32>,
76
77    /// Cloud provider access key.
78    pub access_key_id: String,
79
80    /// Cloud provider secret key.
81    pub access_secret_key: String,
82
83    /// Cloud provider management console username.
84    pub console_username: String,
85
86    /// Cloud provider management console password.
87    pub console_password: String,
88
89    /// Optional. Cloud provider management console login URL.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub sign_in_login_url: Option<String>,
92
93    /// Read-only on the response; populated by the server with the
94    /// operation type (e.g. `"UPDATE_CLOUD_ACCOUNT"`).
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub command_type: Option<String>,
97}
98
99/// Cloud provider account information
100#[derive(Debug, Clone, Serialize, Deserialize)]
101#[serde(rename_all = "camelCase")]
102pub struct CloudAccount {
103    /// Cloud account ID
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub id: Option<i32>,
106
107    /// Cloud account display name
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub name: Option<String>,
110
111    /// Account status (e.g., "active", "error")
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub status: Option<String>,
114
115    /// Cloud provider (e.g., "AWS", "GCP", "Azure")
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub provider: Option<String>,
118
119    /// Cloud provider access key ID
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub access_key_id: Option<String>,
122
123    /// Cloud provider secret key (typically masked in responses)
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub access_secret_key: Option<String>,
126
127    /// AWS Console Role ARN (AWS-specific)
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub aws_console_role_arn: Option<String>,
130
131    /// AWS User ARN (AWS-specific)
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub aws_user_arn: Option<String>,
134
135    /// Cloud provider management console username
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub console_username: Option<String>,
138
139    /// Cloud provider management console password (typically masked)
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub console_password: Option<String>,
142
143    /// Cloud provider management console login URL
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub sign_in_login_url: Option<String>,
146
147    /// HATEOAS links for API navigation
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub links: Option<Vec<Link>>,
150}
151
152/// Cloud account create request
153#[derive(Debug, Clone, Serialize, Deserialize)]
154#[serde(rename_all = "camelCase")]
155pub struct CloudAccountCreateRequest {
156    /// Cloud account display name.
157    pub name: String,
158
159    /// Optional. Cloud provider. Default: 'AWS'
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub provider: Option<String>,
162
163    /// Cloud provider access key.
164    pub access_key_id: String,
165
166    /// Cloud provider secret key.
167    pub access_secret_key: String,
168
169    /// Cloud provider management console username.
170    pub console_username: String,
171
172    /// Cloud provider management console password.
173    pub console_password: String,
174
175    /// Cloud provider management console login URL.
176    pub sign_in_login_url: String,
177
178    /// Read-only on the response; populated by the server with the
179    /// operation type (e.g. `"CREATE_CLOUD_ACCOUNT"`).
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub command_type: Option<String>,
182}
183
184/// Cloud accounts response
185///
186/// Response from GET /cloud-accounts containing list of cloud provider integrations
187#[derive(Debug, Clone, Serialize, Deserialize)]
188#[serde(rename_all = "camelCase")]
189pub struct CloudAccounts {
190    /// Account ID
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub account_id: Option<i32>,
193
194    /// List of cloud provider accounts
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub cloud_accounts: Option<Vec<CloudAccount>>,
197
198    /// HATEOAS links for API navigation
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub links: Option<Vec<Link>>,
201}
202
203// ============================================================================
204// Handler
205// ============================================================================
206
207/// Handler for cloud provider account operations
208///
209/// Manages integration with AWS, GCP, and Azure accounts, including
210/// credential management and provider-specific configurations.
211pub struct CloudAccountsHandler {
212    client: CloudClient,
213}
214
215impl CloudAccountsHandler {
216    /// Create a new handler
217    #[must_use]
218    pub fn new(client: CloudClient) -> Self {
219        Self { client }
220    }
221
222    /// Get cloud accounts
223    ///
224    /// Gets a list of all configured cloud accounts.
225    ///
226    /// # API Endpoint
227    ///
228    /// `GET /cloud-accounts`
229    ///
230    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccounts`
231    pub async fn get_cloud_accounts(&self) -> Result<CloudAccounts> {
232        self.client.get("/cloud-accounts").await
233    }
234
235    /// Create cloud account
236    ///
237    /// Creates a cloud account.
238    ///
239    /// # API Endpoint
240    ///
241    /// `POST /cloud-accounts`
242    ///
243    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `createCloudAccount`
244    pub async fn create_cloud_account(
245        &self,
246        request: &CloudAccountCreateRequest,
247    ) -> Result<TaskStateUpdate> {
248        self.client.post("/cloud-accounts", request).await
249    }
250
251    /// Delete cloud account
252    ///
253    /// Deletes a cloud account.
254    ///
255    /// # API Endpoint
256    ///
257    /// `DELETE /cloud-accounts/{cloudAccountId}`
258    ///
259    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `deleteCloudAccount`
260    pub async fn delete_cloud_account(&self, cloud_account_id: i32) -> Result<TaskStateUpdate> {
261        let response = self
262            .client
263            .delete_raw(&format!("/cloud-accounts/{cloud_account_id}"))
264            .await?;
265        serde_json::from_value(response).map_err(Into::into)
266    }
267
268    /// Get a single cloud account
269    ///
270    /// Gets details on a single cloud account.
271    ///
272    /// # API Endpoint
273    ///
274    /// `GET /cloud-accounts/{cloudAccountId}`
275    ///
276    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccountById`
277    pub async fn get_cloud_account_by_id(&self, cloud_account_id: i32) -> Result<CloudAccount> {
278        self.client
279            .get(&format!("/cloud-accounts/{cloud_account_id}"))
280            .await
281    }
282
283    /// Update cloud account
284    ///
285    /// Updates cloud account details.
286    ///
287    /// # API Endpoint
288    ///
289    /// `PUT /cloud-accounts/{cloudAccountId}`
290    ///
291    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `updateCloudAccount`
292    pub async fn update_cloud_account(
293        &self,
294        cloud_account_id: i32,
295        request: &CloudAccountUpdateRequest,
296    ) -> Result<TaskStateUpdate> {
297        self.client
298            .put(&format!("/cloud-accounts/{cloud_account_id}"), request)
299            .await
300    }
301
302    // ============================================================================
303    // Simplified aliases
304    // ============================================================================
305
306    /// List cloud accounts (simplified)
307    ///
308    /// Alias for [`get_cloud_accounts`](Self::get_cloud_accounts).
309    ///
310    /// # Example
311    ///
312    /// ```no_run
313    /// use redis_cloud::CloudClient;
314    ///
315    /// # async fn example() -> redis_cloud::Result<()> {
316    /// let client = CloudClient::builder()
317    ///     .api_key("your-api-key")
318    ///     .api_secret("your-api-secret")
319    ///     .build()?;
320    ///
321    /// let accounts = client.cloud_accounts().list().await?;
322    /// # Ok(())
323    /// # }
324    /// ```
325    pub async fn list(&self) -> Result<CloudAccounts> {
326        self.get_cloud_accounts().await
327    }
328
329    /// Create a cloud account (simplified)
330    ///
331    /// Alias for [`create_cloud_account`](Self::create_cloud_account).
332    ///
333    /// # Arguments
334    ///
335    /// * `request` - The cloud account creation request
336    ///
337    /// # Example
338    ///
339    /// ```no_run
340    /// use redis_cloud::CloudClient;
341    /// use redis_cloud::cloud_accounts::CloudAccountCreateRequest;
342    ///
343    /// # async fn example() -> redis_cloud::Result<()> {
344    /// let client = CloudClient::builder()
345    ///     .api_key("your-api-key")
346    ///     .api_secret("your-api-secret")
347    ///     .build()?;
348    ///
349    /// let request = CloudAccountCreateRequest {
350    ///     name: "my-aws-account".to_string(),
351    ///     provider: Some("AWS".to_string()),
352    ///     access_key_id: "key".to_string(),
353    ///     access_secret_key: "secret".to_string(),
354    ///     console_username: "user".to_string(),
355    ///     console_password: "pass".to_string(),
356    ///     sign_in_login_url: "https://console.aws.amazon.com".to_string(),
357    ///     command_type: None,
358    /// };
359    ///
360    /// let task = client.cloud_accounts().create(&request).await?;
361    /// # Ok(())
362    /// # }
363    /// ```
364    pub async fn create(&self, request: &CloudAccountCreateRequest) -> Result<TaskStateUpdate> {
365        self.create_cloud_account(request).await
366    }
367
368    /// Delete a cloud account (simplified)
369    ///
370    /// Alias for [`delete_cloud_account`](Self::delete_cloud_account).
371    ///
372    /// # Arguments
373    ///
374    /// * `cloud_account_id` - The cloud account ID
375    ///
376    /// # Example
377    ///
378    /// ```no_run
379    /// use redis_cloud::CloudClient;
380    ///
381    /// # async fn example() -> redis_cloud::Result<()> {
382    /// let client = CloudClient::builder()
383    ///     .api_key("your-api-key")
384    ///     .api_secret("your-api-secret")
385    ///     .build()?;
386    ///
387    /// let task = client.cloud_accounts().delete(123).await?;
388    /// # Ok(())
389    /// # }
390    /// ```
391    pub async fn delete(&self, cloud_account_id: i32) -> Result<TaskStateUpdate> {
392        self.delete_cloud_account(cloud_account_id).await
393    }
394
395    /// Get a cloud account by ID (simplified)
396    ///
397    /// Alias for [`get_cloud_account_by_id`](Self::get_cloud_account_by_id).
398    ///
399    /// # Arguments
400    ///
401    /// * `cloud_account_id` - The cloud account ID
402    ///
403    /// # Example
404    ///
405    /// ```no_run
406    /// use redis_cloud::CloudClient;
407    ///
408    /// # async fn example() -> redis_cloud::Result<()> {
409    /// let client = CloudClient::builder()
410    ///     .api_key("your-api-key")
411    ///     .api_secret("your-api-secret")
412    ///     .build()?;
413    ///
414    /// let account = client.cloud_accounts().get(123).await?;
415    /// # Ok(())
416    /// # }
417    /// ```
418    pub async fn get(&self, cloud_account_id: i32) -> Result<CloudAccount> {
419        self.get_cloud_account_by_id(cloud_account_id).await
420    }
421
422    /// Update a cloud account (simplified)
423    ///
424    /// Alias for [`update_cloud_account`](Self::update_cloud_account).
425    ///
426    /// # Arguments
427    ///
428    /// * `cloud_account_id` - The cloud account ID
429    /// * `request` - The cloud account update request
430    ///
431    /// # Example
432    ///
433    /// ```no_run
434    /// use redis_cloud::CloudClient;
435    /// use redis_cloud::cloud_accounts::CloudAccountUpdateRequest;
436    ///
437    /// # async fn example() -> redis_cloud::Result<()> {
438    /// let client = CloudClient::builder()
439    ///     .api_key("your-api-key")
440    ///     .api_secret("your-api-secret")
441    ///     .build()?;
442    ///
443    /// let request = CloudAccountUpdateRequest {
444    ///     name: Some("renamed-account".to_string()),
445    ///     cloud_account_id: None,
446    ///     access_key_id: "key".to_string(),
447    ///     access_secret_key: "secret".to_string(),
448    ///     console_username: "user".to_string(),
449    ///     console_password: "pass".to_string(),
450    ///     sign_in_login_url: None,
451    ///     command_type: None,
452    /// };
453    ///
454    /// let task = client.cloud_accounts().update(123, &request).await?;
455    /// # Ok(())
456    /// # }
457    /// ```
458    pub async fn update(
459        &self,
460        cloud_account_id: i32,
461        request: &CloudAccountUpdateRequest,
462    ) -> Result<TaskStateUpdate> {
463        self.update_cloud_account(cloud_account_id, request).await
464    }
465}