1use crate::{
8 AwsHttpClient, Result,
9 ops::rds::RdsOps,
10 types::rds::{
11 CreateDBSnapshotRequest, CreateDBSnapshotResponse, DeleteDBInstanceRequest,
12 DeleteDBInstanceResponse, DeleteDBSnapshotRequest, DeleteDBSnapshotResponse,
13 DescribeDBInstancesRequest, DescribeDBInstancesResponse,
14 DescribeDBSnapshotAttributesRequest, DescribeDBSnapshotAttributesResponse,
15 DescribeDBSnapshotsRequest, DescribeDBSnapshotsResponse, ModifyDBInstanceRequest,
16 ModifyDBInstanceResponse, ModifyDBSnapshotAttributeRequest,
17 ModifyDBSnapshotAttributeResponse, StartDBInstanceRequest, StartDBInstanceResponse,
18 StopDBInstanceRequest, StopDBInstanceResponse,
19 },
20};
21
22pub struct RdsClient<'a> {
24 ops: RdsOps<'a>,
25}
26
27impl<'a> RdsClient<'a> {
28 pub(crate) fn new(client: &'a AwsHttpClient) -> Self {
30 Self {
31 ops: RdsOps::new(client),
32 }
33 }
34
35 pub async fn describe_db_instances(
37 &self,
38 body: &DescribeDBInstancesRequest,
39 ) -> Result<DescribeDBInstancesResponse> {
40 self.ops.describe_db_instances(body).await
41 }
42
43 pub async fn describe_db_snapshots(
45 &self,
46 body: &DescribeDBSnapshotsRequest,
47 ) -> Result<DescribeDBSnapshotsResponse> {
48 self.ops.describe_db_snapshots(body).await
49 }
50
51 pub async fn describe_db_snapshot_attributes(
53 &self,
54 body: &DescribeDBSnapshotAttributesRequest,
55 ) -> Result<DescribeDBSnapshotAttributesResponse> {
56 self.ops.describe_db_snapshot_attributes(body).await
57 }
58
59 pub async fn modify_db_instance(
61 &self,
62 body: &ModifyDBInstanceRequest,
63 ) -> Result<ModifyDBInstanceResponse> {
64 self.ops.modify_db_instance(body).await
65 }
66
67 pub async fn stop_db_instance(
69 &self,
70 body: &StopDBInstanceRequest,
71 ) -> Result<StopDBInstanceResponse> {
72 self.ops.stop_db_instance(body).await
73 }
74
75 pub async fn start_db_instance(
77 &self,
78 body: &StartDBInstanceRequest,
79 ) -> Result<StartDBInstanceResponse> {
80 self.ops.start_db_instance(body).await
81 }
82
83 pub async fn delete_db_instance(
85 &self,
86 body: &DeleteDBInstanceRequest,
87 ) -> Result<DeleteDBInstanceResponse> {
88 self.ops.delete_db_instance(body).await
89 }
90
91 pub async fn create_db_snapshot(
93 &self,
94 body: &CreateDBSnapshotRequest,
95 ) -> Result<CreateDBSnapshotResponse> {
96 self.ops.create_db_snapshot(body).await
97 }
98
99 pub async fn delete_db_snapshot(
101 &self,
102 body: &DeleteDBSnapshotRequest,
103 ) -> Result<DeleteDBSnapshotResponse> {
104 self.ops.delete_db_snapshot(body).await
105 }
106
107 pub async fn modify_db_snapshot_attribute(
109 &self,
110 body: &ModifyDBSnapshotAttributeRequest,
111 ) -> Result<ModifyDBSnapshotAttributeResponse> {
112 self.ops.modify_db_snapshot_attribute(body).await
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use crate::types::rds::*;
119
120 #[tokio::test]
121 async fn describe_db_instances_returns_parsed_response() {
122 let mut mock = crate::MockClient::new();
123 mock.expect_post("/").returning_bytes(
124 r#"<DescribeDBInstancesResponse><DescribeDBInstancesResult>
125 <DBInstances>
126 <DBInstance>
127 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
128 <DBInstanceClass>db.t3.micro</DBInstanceClass>
129 <Engine>mysql</Engine>
130 <DBInstanceStatus>available</DBInstanceStatus>
131 <AllocatedStorage>20</AllocatedStorage>
132 <Endpoint>
133 <Address>my-db.abc.us-east-1.rds.amazonaws.com</Address>
134 <Port>3306</Port>
135 </Endpoint>
136 </DBInstance>
137 </DBInstances>
138 </DescribeDBInstancesResult></DescribeDBInstancesResponse>"#
139 .as_bytes()
140 .to_vec(),
141 );
142 let client = crate::AwsHttpClient::from_mock(mock);
143 let result = client
144 .rds()
145 .describe_db_instances(&DescribeDBInstancesRequest {
146 db_instance_identifier: Some("my-db".into()),
147 ..Default::default()
148 })
149 .await
150 .unwrap();
151 assert_eq!(result.db_instances.len(), 1);
152 let inst = &result.db_instances[0];
153 assert_eq!(inst.db_instance_identifier.as_deref(), Some("my-db"));
154 assert_eq!(inst.engine.as_deref(), Some("mysql"));
155 assert_eq!(inst.db_instance_status.as_deref(), Some("available"));
156 assert_eq!(inst.allocated_storage, Some(20));
157 let ep = inst.endpoint.as_ref().unwrap();
158 assert_eq!(
159 ep.address.as_deref(),
160 Some("my-db.abc.us-east-1.rds.amazonaws.com")
161 );
162 assert_eq!(ep.port, Some(3306));
163 }
164
165 #[tokio::test]
166 async fn describe_db_snapshots_returns_parsed_response() {
167 let mut mock = crate::MockClient::new();
168 mock.expect_post("/").returning_bytes(
169 r#"<DescribeDBSnapshotsResponse><DescribeDBSnapshotsResult>
170 <DBSnapshots>
171 <DBSnapshot>
172 <DBSnapshotIdentifier>my-snap</DBSnapshotIdentifier>
173 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
174 <Engine>mysql</Engine>
175 <Status>available</Status>
176 <AllocatedStorage>20</AllocatedStorage>
177 </DBSnapshot>
178 </DBSnapshots>
179 </DescribeDBSnapshotsResult></DescribeDBSnapshotsResponse>"#
180 .as_bytes()
181 .to_vec(),
182 );
183 let client = crate::AwsHttpClient::from_mock(mock);
184 let result = client
185 .rds()
186 .describe_db_snapshots(&DescribeDBSnapshotsRequest {
187 db_snapshot_identifier: Some("my-snap".into()),
188 ..Default::default()
189 })
190 .await
191 .unwrap();
192 assert_eq!(result.db_snapshots.len(), 1);
193 let snap = &result.db_snapshots[0];
194 assert_eq!(snap.db_snapshot_identifier.as_deref(), Some("my-snap"));
195 assert_eq!(snap.db_instance_identifier.as_deref(), Some("my-db"));
196 assert_eq!(snap.engine.as_deref(), Some("mysql"));
197 assert_eq!(snap.status.as_deref(), Some("available"));
198 }
199
200 #[tokio::test]
201 async fn describe_db_snapshot_attributes_returns_parsed_response() {
202 let mut mock = crate::MockClient::new();
203 mock.expect_post("/").returning_bytes(
204 r#"<DescribeDBSnapshotAttributesResponse><DescribeDBSnapshotAttributesResult>
205 <DBSnapshotAttributesResult>
206 <DBSnapshotIdentifier>my-snap</DBSnapshotIdentifier>
207 <DBSnapshotAttributes>
208 <DBSnapshotAttribute>
209 <AttributeName>restore</AttributeName>
210 <AttributeValues/>
211 </DBSnapshotAttribute>
212 </DBSnapshotAttributes>
213 </DBSnapshotAttributesResult>
214 </DescribeDBSnapshotAttributesResult></DescribeDBSnapshotAttributesResponse>"#
215 .as_bytes()
216 .to_vec(),
217 );
218 let client = crate::AwsHttpClient::from_mock(mock);
219 let result = client
220 .rds()
221 .describe_db_snapshot_attributes(&DescribeDBSnapshotAttributesRequest {
222 db_snapshot_identifier: "my-snap".into(),
223 })
224 .await
225 .unwrap();
226 let attrs = result.db_snapshot_attributes_result.as_ref().unwrap();
227 assert_eq!(attrs.db_snapshot_identifier.as_deref(), Some("my-snap"));
228 assert_eq!(attrs.db_snapshot_attributes.len(), 1);
229 assert_eq!(
230 attrs.db_snapshot_attributes[0].attribute_name.as_deref(),
231 Some("restore")
232 );
233 }
234
235 #[tokio::test]
236 async fn modify_db_instance_returns_parsed_response() {
237 let mut mock = crate::MockClient::new();
238 mock.expect_post("/").returning_bytes(
239 r#"<ModifyDBInstanceResponse><ModifyDBInstanceResult>
240 <DBInstance>
241 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
242 <DBInstanceClass>db.t3.micro</DBInstanceClass>
243 <Engine>mysql</Engine>
244 <DBInstanceStatus>available</DBInstanceStatus>
245 <BackupRetentionPeriod>1</BackupRetentionPeriod>
246 </DBInstance>
247 </ModifyDBInstanceResult></ModifyDBInstanceResponse>"#
248 .as_bytes()
249 .to_vec(),
250 );
251 let client = crate::AwsHttpClient::from_mock(mock);
252 let result = client
253 .rds()
254 .modify_db_instance(&ModifyDBInstanceRequest {
255 db_instance_identifier: "my-db".into(),
256 backup_retention_period: Some(1),
257 apply_immediately: Some(true),
258 ..Default::default()
259 })
260 .await
261 .unwrap();
262 let inst = result.db_instance.as_ref().unwrap();
263 assert_eq!(inst.db_instance_identifier.as_deref(), Some("my-db"));
264 assert_eq!(inst.db_instance_status.as_deref(), Some("available"));
265 assert_eq!(inst.backup_retention_period, Some(1));
266 }
267
268 #[tokio::test]
269 async fn stop_db_instance_returns_parsed_response() {
270 let mut mock = crate::MockClient::new();
271 mock.expect_post("/").returning_bytes(
272 r#"<StopDBInstanceResponse><StopDBInstanceResult>
273 <DBInstance>
274 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
275 <DBInstanceStatus>stopping</DBInstanceStatus>
276 <Engine>mysql</Engine>
277 </DBInstance>
278 </StopDBInstanceResult></StopDBInstanceResponse>"#
279 .as_bytes()
280 .to_vec(),
281 );
282 let client = crate::AwsHttpClient::from_mock(mock);
283 let result = client
284 .rds()
285 .stop_db_instance(&StopDBInstanceRequest {
286 db_instance_identifier: "my-db".into(),
287 ..Default::default()
288 })
289 .await
290 .unwrap();
291 let inst = result.db_instance.as_ref().unwrap();
292 assert_eq!(inst.db_instance_identifier.as_deref(), Some("my-db"));
293 assert_eq!(inst.db_instance_status.as_deref(), Some("stopping"));
294 }
295
296 #[tokio::test]
297 async fn start_db_instance_returns_parsed_response() {
298 let mut mock = crate::MockClient::new();
299 mock.expect_post("/").returning_bytes(
300 r#"<StartDBInstanceResponse><StartDBInstanceResult>
301 <DBInstance>
302 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
303 <DBInstanceStatus>starting</DBInstanceStatus>
304 <Engine>mysql</Engine>
305 </DBInstance>
306 </StartDBInstanceResult></StartDBInstanceResponse>"#
307 .as_bytes()
308 .to_vec(),
309 );
310 let client = crate::AwsHttpClient::from_mock(mock);
311 let result = client
312 .rds()
313 .start_db_instance(&StartDBInstanceRequest {
314 db_instance_identifier: "my-db".into(),
315 })
316 .await
317 .unwrap();
318 let inst = result.db_instance.as_ref().unwrap();
319 assert_eq!(inst.db_instance_identifier.as_deref(), Some("my-db"));
320 assert_eq!(inst.db_instance_status.as_deref(), Some("starting"));
321 }
322
323 #[tokio::test]
324 async fn delete_db_instance_returns_parsed_response() {
325 let mut mock = crate::MockClient::new();
326 mock.expect_post("/").returning_bytes(
327 r#"<DeleteDBInstanceResponse><DeleteDBInstanceResult>
328 <DBInstance>
329 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
330 <DBInstanceStatus>deleting</DBInstanceStatus>
331 <Engine>mysql</Engine>
332 </DBInstance>
333 </DeleteDBInstanceResult></DeleteDBInstanceResponse>"#
334 .as_bytes()
335 .to_vec(),
336 );
337 let client = crate::AwsHttpClient::from_mock(mock);
338 let result = client
339 .rds()
340 .delete_db_instance(&DeleteDBInstanceRequest {
341 db_instance_identifier: "my-db".into(),
342 skip_final_snapshot: Some(true),
343 delete_automated_backups: Some(true),
344 ..Default::default()
345 })
346 .await
347 .unwrap();
348 let inst = result.db_instance.as_ref().unwrap();
349 assert_eq!(inst.db_instance_identifier.as_deref(), Some("my-db"));
350 assert_eq!(inst.db_instance_status.as_deref(), Some("deleting"));
351 }
352
353 #[tokio::test]
354 async fn create_db_snapshot_returns_parsed_response() {
355 let mut mock = crate::MockClient::new();
356 mock.expect_post("/").returning_bytes(
357 r#"<CreateDBSnapshotResponse><CreateDBSnapshotResult>
358 <DBSnapshot>
359 <DBSnapshotIdentifier>my-snap</DBSnapshotIdentifier>
360 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
361 <Engine>mysql</Engine>
362 <Status>creating</Status>
363 <AllocatedStorage>20</AllocatedStorage>
364 </DBSnapshot>
365 </CreateDBSnapshotResult></CreateDBSnapshotResponse>"#
366 .as_bytes()
367 .to_vec(),
368 );
369 let client = crate::AwsHttpClient::from_mock(mock);
370 let result = client
371 .rds()
372 .create_db_snapshot(&CreateDBSnapshotRequest {
373 db_snapshot_identifier: "my-snap".into(),
374 db_instance_identifier: "my-db".into(),
375 ..Default::default()
376 })
377 .await
378 .unwrap();
379 let snap = result.db_snapshot.as_ref().unwrap();
380 assert_eq!(snap.db_snapshot_identifier.as_deref(), Some("my-snap"));
381 assert_eq!(snap.db_instance_identifier.as_deref(), Some("my-db"));
382 assert_eq!(snap.status.as_deref(), Some("creating"));
383 }
384
385 #[tokio::test]
386 async fn delete_db_snapshot_returns_parsed_response() {
387 let mut mock = crate::MockClient::new();
388 mock.expect_post("/").returning_bytes(
389 r#"<DeleteDBSnapshotResponse><DeleteDBSnapshotResult>
390 <DBSnapshot>
391 <DBSnapshotIdentifier>my-snap</DBSnapshotIdentifier>
392 <DBInstanceIdentifier>my-db</DBInstanceIdentifier>
393 <Status>deleted</Status>
394 </DBSnapshot>
395 </DeleteDBSnapshotResult></DeleteDBSnapshotResponse>"#
396 .as_bytes()
397 .to_vec(),
398 );
399 let client = crate::AwsHttpClient::from_mock(mock);
400 let result = client
401 .rds()
402 .delete_db_snapshot(&DeleteDBSnapshotRequest {
403 db_snapshot_identifier: "my-snap".into(),
404 })
405 .await
406 .unwrap();
407 let snap = result.db_snapshot.as_ref().unwrap();
408 assert_eq!(snap.db_snapshot_identifier.as_deref(), Some("my-snap"));
409 assert_eq!(snap.status.as_deref(), Some("deleted"));
410 }
411
412 #[tokio::test]
413 async fn modify_db_snapshot_attribute_returns_parsed_response() {
414 let mut mock = crate::MockClient::new();
415 mock.expect_post("/").returning_bytes(
416 r#"<ModifyDBSnapshotAttributeResponse><ModifyDBSnapshotAttributeResult>
417 <DBSnapshotAttributesResult>
418 <DBSnapshotIdentifier>my-snap</DBSnapshotIdentifier>
419 <DBSnapshotAttributes>
420 <DBSnapshotAttribute>
421 <AttributeName>restore</AttributeName>
422 <AttributeValues>
423 <AttributeValue>123456789012</AttributeValue>
424 </AttributeValues>
425 </DBSnapshotAttribute>
426 </DBSnapshotAttributes>
427 </DBSnapshotAttributesResult>
428 </ModifyDBSnapshotAttributeResult></ModifyDBSnapshotAttributeResponse>"#
429 .as_bytes()
430 .to_vec(),
431 );
432 let client = crate::AwsHttpClient::from_mock(mock);
433 let result = client
434 .rds()
435 .modify_db_snapshot_attribute(&ModifyDBSnapshotAttributeRequest {
436 db_snapshot_identifier: "my-snap".into(),
437 attribute_name: "restore".into(),
438 values_to_add: vec!["123456789012".into()],
439 ..Default::default()
440 })
441 .await
442 .unwrap();
443 let attrs = result.db_snapshot_attributes_result.as_ref().unwrap();
444 assert_eq!(attrs.db_snapshot_identifier.as_deref(), Some("my-snap"));
445 assert_eq!(attrs.db_snapshot_attributes.len(), 1);
446 assert_eq!(
447 attrs.db_snapshot_attributes[0].attribute_name.as_deref(),
448 Some("restore")
449 );
450 assert!(
451 attrs.db_snapshot_attributes[0]
452 .attribute_values
453 .contains(&"123456789012".to_string())
454 );
455 }
456}