redis_cloud/connectivity/
transit_gateway.rs

1//! AWS Transit Gateway operations
2//!
3//! Manages AWS Transit Gateway attachments for hub-and-spoke network topologies,
4//! enabling centralized connectivity management for Redis Cloud subscriptions.
5
6use crate::{CloudClient, Result};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10/// CIDR block definition
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub struct Cidr {
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub cidr_address: Option<String>,
16
17    /// Additional fields from the API
18    #[serde(flatten)]
19    pub extra: Value,
20}
21
22/// Transit Gateway CIDRs update request
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct TgwUpdateCidrsRequest {
26    /// Optional. List of transit gateway attachment CIDRs.
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub cidrs: Option<Vec<Cidr>>,
29
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub command_type: Option<String>,
32
33    /// Additional fields from the API
34    #[serde(flatten)]
35    pub extra: Value,
36}
37
38/// Transit Gateway attachment request
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct TgwAttachmentRequest {
42    /// AWS account ID
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub aws_account_id: Option<String>,
45
46    /// Transit Gateway ID
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub tgw_id: Option<String>,
49
50    /// CIDR blocks to route through the TGW
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub cidrs: Option<Vec<String>>,
53
54    /// Additional fields
55    #[serde(flatten)]
56    pub extra: Value,
57}
58
59/// Task state update response
60pub use crate::types::TaskStateUpdate;
61
62/// Transit Gateway handler
63pub struct TransitGatewayHandler {
64    client: CloudClient,
65}
66
67impl TransitGatewayHandler {
68    /// Create a new Transit Gateway handler
69    pub fn new(client: CloudClient) -> Self {
70        Self { client }
71    }
72
73    // ========================================================================
74    // Standard Transit Gateway Operations
75    // ========================================================================
76
77    /// Get Transit Gateway attachments
78    pub async fn get_attachments(&self, subscription_id: i32) -> Result<TaskStateUpdate> {
79        self.client
80            .get(&format!(
81                "/subscriptions/{}/transitGateways",
82                subscription_id
83            ))
84            .await
85    }
86
87    /// Get Transit Gateway shared invitations
88    pub async fn get_shared_invitations(&self, subscription_id: i32) -> Result<TaskStateUpdate> {
89        self.client
90            .get(&format!(
91                "/subscriptions/{}/tgw/shared-invitations",
92                subscription_id
93            ))
94            .await
95    }
96
97    /// Accept Transit Gateway resource share
98    pub async fn accept_resource_share(
99        &self,
100        subscription_id: i32,
101        invitation_id: String,
102    ) -> Result<TaskStateUpdate> {
103        self.client
104            .post(
105                &format!(
106                    "/subscriptions/{}/tgw/shared-invitations/{}/accept",
107                    subscription_id, invitation_id
108                ),
109                &serde_json::json!({}),
110            )
111            .await
112    }
113
114    /// Reject Transit Gateway resource share
115    pub async fn reject_resource_share(
116        &self,
117        subscription_id: i32,
118        invitation_id: String,
119    ) -> Result<TaskStateUpdate> {
120        self.client
121            .post(
122                &format!(
123                    "/subscriptions/{}/tgw/shared-invitations/{}/reject",
124                    subscription_id, invitation_id
125                ),
126                &serde_json::json!({}),
127            )
128            .await
129    }
130
131    /// Delete Transit Gateway attachment
132    pub async fn delete_attachment(
133        &self,
134        subscription_id: i32,
135        attachment_id: String,
136    ) -> Result<serde_json::Value> {
137        self.client
138            .delete(&format!(
139                "/subscriptions/{}/transitGateways/{}/attachment",
140                subscription_id, attachment_id
141            ))
142            .await?;
143        Ok(serde_json::Value::Null)
144    }
145
146    /// Create Transit Gateway attachment with tgw_id in path
147    pub async fn create_attachment_with_id(
148        &self,
149        subscription_id: i32,
150        tgw_id: &str,
151    ) -> Result<TaskStateUpdate> {
152        // Create an empty request body as the API might expect one
153        let request = TgwAttachmentRequest {
154            tgw_id: Some(tgw_id.to_string()),
155            aws_account_id: None,
156            cidrs: None,
157            extra: serde_json::Value::Object(serde_json::Map::new()),
158        };
159
160        self.client
161            .post(
162                &format!(
163                    "/subscriptions/{}/transitGateways/{}/attachment",
164                    subscription_id, tgw_id
165                ),
166                &request,
167            )
168            .await
169    }
170
171    /// Create Transit Gateway attachment
172    pub async fn create_attachment(
173        &self,
174        subscription_id: i32,
175        request: &TgwAttachmentRequest,
176    ) -> Result<TaskStateUpdate> {
177        self.client
178            .post(
179                &format!(
180                    "/subscriptions/{}/transitGateways/attachments",
181                    subscription_id
182                ),
183                request,
184            )
185            .await
186    }
187
188    /// Update Transit Gateway attachment CIDRs
189    pub async fn update_attachment_cidrs(
190        &self,
191        subscription_id: i32,
192        attachment_id: String,
193        request: &TgwAttachmentRequest,
194    ) -> Result<TaskStateUpdate> {
195        self.client
196            .put(
197                &format!(
198                    "/subscriptions/{}/transitGateways/{}/attachment",
199                    subscription_id, attachment_id
200                ),
201                request,
202            )
203            .await
204    }
205
206    // ========================================================================
207    // Active-Active Transit Gateway Operations
208    // ========================================================================
209
210    /// Get Active-Active Transit Gateway attachments
211    pub async fn get_attachments_active_active(
212        &self,
213        subscription_id: i32,
214    ) -> Result<TaskStateUpdate> {
215        self.client
216            .get(&format!(
217                "/subscriptions/{}/regions/transitGateways",
218                subscription_id
219            ))
220            .await
221    }
222
223    /// Get Active-Active Transit Gateway shared invitations
224    pub async fn get_shared_invitations_active_active(
225        &self,
226        subscription_id: i32,
227    ) -> Result<TaskStateUpdate> {
228        self.client
229            .get(&format!(
230                "/subscriptions/{}/regions/tgw/shared-invitations",
231                subscription_id
232            ))
233            .await
234    }
235
236    /// Accept Active-Active Transit Gateway resource share
237    pub async fn accept_resource_share_active_active(
238        &self,
239        subscription_id: i32,
240        region_id: i32,
241        invitation_id: String,
242    ) -> Result<TaskStateUpdate> {
243        self.client
244            .post(
245                &format!(
246                    "/subscriptions/{}/regions/{}/tgw/shared-invitations/{}/accept",
247                    subscription_id, region_id, invitation_id
248                ),
249                &serde_json::json!({}),
250            )
251            .await
252    }
253
254    /// Reject Active-Active Transit Gateway resource share
255    pub async fn reject_resource_share_active_active(
256        &self,
257        subscription_id: i32,
258        region_id: i32,
259        invitation_id: String,
260    ) -> Result<TaskStateUpdate> {
261        self.client
262            .post(
263                &format!(
264                    "/subscriptions/{}/regions/{}/tgw/shared-invitations/{}/reject",
265                    subscription_id, region_id, invitation_id
266                ),
267                &serde_json::json!({}),
268            )
269            .await
270    }
271
272    /// Delete Active-Active Transit Gateway attachment
273    pub async fn delete_attachment_active_active(
274        &self,
275        subscription_id: i32,
276        region_id: i32,
277        attachment_id: String,
278    ) -> Result<serde_json::Value> {
279        self.client
280            .delete(&format!(
281                "/subscriptions/{}/regions/{}/tgw/attachments/{}",
282                subscription_id, region_id, attachment_id
283            ))
284            .await?;
285        Ok(serde_json::Value::Null)
286    }
287
288    /// Create Active-Active Transit Gateway attachment
289    pub async fn create_attachment_active_active(
290        &self,
291        subscription_id: i32,
292        region_id: i32,
293        request: &TgwAttachmentRequest,
294    ) -> Result<TaskStateUpdate> {
295        self.client
296            .post(
297                &format!(
298                    "/subscriptions/{}/regions/{}/tgw/attachments",
299                    subscription_id, region_id
300                ),
301                request,
302            )
303            .await
304    }
305
306    /// Update Active-Active Transit Gateway attachment CIDRs
307    pub async fn update_attachment_cidrs_active_active(
308        &self,
309        subscription_id: i32,
310        region_id: i32,
311        attachment_id: String,
312        request: &TgwAttachmentRequest,
313    ) -> Result<TaskStateUpdate> {
314        self.client
315            .put(
316                &format!(
317                    "/subscriptions/{}/regions/{}/tgw/attachments/{}/cidrs",
318                    subscription_id, region_id, attachment_id
319                ),
320                request,
321            )
322            .await
323    }
324}