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}