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, ProcessorResponse};
57use crate::{CloudClient, Result};
58use serde::{Deserialize, Serialize};
59
60// ============================================================================
61// Models
62// ============================================================================
63
64/// Cloud account update request
65#[derive(Debug, Clone, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct CloudAccountUpdateRequest {
68    /// Cloud account display name
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub name: Option<String>,
71
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub cloud_account_id: Option<i32>,
74
75    /// Cloud provider access key.
76    pub access_key_id: String,
77
78    /// Cloud provider secret key.
79    pub access_secret_key: String,
80
81    /// Cloud provider management console username.
82    pub console_username: String,
83
84    /// Cloud provider management console password.
85    pub console_password: String,
86
87    /// Optional. Cloud provider management console login URL.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub sign_in_login_url: Option<String>,
90
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub command_type: Option<String>,
93}
94
95/// Cloud provider account information
96#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(rename_all = "camelCase")]
98pub struct CloudAccount {
99    /// Cloud account ID
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub id: Option<i32>,
102
103    /// Cloud account display name
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub name: Option<String>,
106
107    /// Account status (e.g., "active", "error")
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub status: Option<String>,
110
111    /// Cloud provider (e.g., "AWS", "GCP", "Azure")
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub provider: Option<String>,
114
115    /// Cloud provider access key ID
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub access_key_id: Option<String>,
118
119    /// Cloud provider secret key (typically masked in responses)
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub access_secret_key: Option<String>,
122
123    /// AWS Console Role ARN (AWS-specific)
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub aws_console_role_arn: Option<String>,
126
127    /// AWS User ARN (AWS-specific)
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub aws_user_arn: Option<String>,
130
131    /// Cloud provider management console username
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub console_username: Option<String>,
134
135    /// Cloud provider management console password (typically masked)
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub console_password: Option<String>,
138
139    /// Cloud provider management console login URL
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub sign_in_login_url: Option<String>,
142
143    /// HATEOAS links for API navigation
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub links: Option<Vec<Link>>,
146}
147
148/// Cloud account create request
149#[derive(Debug, Clone, Serialize, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct CloudAccountCreateRequest {
152    /// Cloud account display name.
153    pub name: String,
154
155    /// Optional. Cloud provider. Default: 'AWS'
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub provider: Option<String>,
158
159    /// Cloud provider access key.
160    pub access_key_id: String,
161
162    /// Cloud provider secret key.
163    pub access_secret_key: String,
164
165    /// Cloud provider management console username.
166    pub console_username: String,
167
168    /// Cloud provider management console password.
169    pub console_password: String,
170
171    /// Cloud provider management console login URL.
172    pub sign_in_login_url: String,
173
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub command_type: Option<String>,
176}
177
178/// Cloud accounts response
179///
180/// Response from GET /cloud-accounts containing list of cloud provider integrations
181#[derive(Debug, Clone, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub struct CloudAccounts {
184    /// Account ID
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub account_id: Option<i32>,
187
188    /// List of cloud provider accounts
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub cloud_accounts: Option<Vec<CloudAccount>>,
191
192    /// HATEOAS links for API navigation
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub links: Option<Vec<Link>>,
195}
196
197/// Task state update response
198#[derive(Debug, Clone, Serialize, Deserialize)]
199#[serde(rename_all = "camelCase")]
200pub struct TaskStateUpdate {
201    /// Task ID (UUID)
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub task_id: Option<String>,
204
205    /// Command type
206    #[serde(skip_serializing_if = "Option::is_none")]
207    pub command_type: Option<String>,
208
209    /// Task status
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub status: Option<String>,
212
213    /// Task description
214    #[serde(skip_serializing_if = "Option::is_none")]
215    pub description: Option<String>,
216
217    /// Timestamp
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub timestamp: Option<String>,
220
221    /// Task response with resource info
222    #[serde(skip_serializing_if = "Option::is_none")]
223    pub response: Option<ProcessorResponse>,
224
225    /// HATEOAS links
226    #[serde(skip_serializing_if = "Option::is_none")]
227    pub links: Option<Vec<Link>>,
228}
229
230// ============================================================================
231// Handler
232// ============================================================================
233
234/// Handler for cloud provider account operations
235///
236/// Manages integration with AWS, GCP, and Azure accounts, including
237/// credential management and provider-specific configurations.
238pub struct CloudAccountsHandler {
239    client: CloudClient,
240}
241
242impl CloudAccountsHandler {
243    /// Create a new handler
244    #[must_use]
245    pub fn new(client: CloudClient) -> Self {
246        Self { client }
247    }
248
249    /// Get cloud accounts
250    ///
251    /// Gets a list of all configured cloud accounts.
252    ///
253    /// # API Endpoint
254    ///
255    /// `GET /cloud-accounts`
256    ///
257    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccounts`
258    pub async fn get_cloud_accounts(&self) -> Result<CloudAccounts> {
259        self.client.get("/cloud-accounts").await
260    }
261
262    /// Create cloud account
263    ///
264    /// Creates a cloud account.
265    ///
266    /// # API Endpoint
267    ///
268    /// `POST /cloud-accounts`
269    ///
270    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `createCloudAccount`
271    pub async fn create_cloud_account(
272        &self,
273        request: &CloudAccountCreateRequest,
274    ) -> Result<TaskStateUpdate> {
275        self.client.post("/cloud-accounts", request).await
276    }
277
278    /// Delete cloud account
279    ///
280    /// Deletes a cloud account.
281    ///
282    /// # API Endpoint
283    ///
284    /// `DELETE /cloud-accounts/{cloudAccountId}`
285    ///
286    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `deleteCloudAccount`
287    pub async fn delete_cloud_account(&self, cloud_account_id: i32) -> Result<TaskStateUpdate> {
288        let response = self
289            .client
290            .delete_raw(&format!("/cloud-accounts/{cloud_account_id}"))
291            .await?;
292        serde_json::from_value(response).map_err(Into::into)
293    }
294
295    /// Get a single cloud account
296    ///
297    /// Gets details on a single cloud account.
298    ///
299    /// # API Endpoint
300    ///
301    /// `GET /cloud-accounts/{cloudAccountId}`
302    ///
303    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `getCloudAccountById`
304    pub async fn get_cloud_account_by_id(&self, cloud_account_id: i32) -> Result<CloudAccount> {
305        self.client
306            .get(&format!("/cloud-accounts/{cloud_account_id}"))
307            .await
308    }
309
310    /// Update cloud account
311    ///
312    /// Updates cloud account details.
313    ///
314    /// # API Endpoint
315    ///
316    /// `PUT /cloud-accounts/{cloudAccountId}`
317    ///
318    /// See [OpenAPI Spec](https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json) - `updateCloudAccount`
319    pub async fn update_cloud_account(
320        &self,
321        cloud_account_id: i32,
322        request: &CloudAccountUpdateRequest,
323    ) -> Result<TaskStateUpdate> {
324        self.client
325            .put(&format!("/cloud-accounts/{cloud_account_id}"), request)
326            .await
327    }
328}