1use crate::error::Error;
2use crate::types::*;
3use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
4
5pub struct FakeCloud {
7 base_url: String,
8 client: reqwest::Client,
9}
10
11impl FakeCloud {
12 pub fn new(base_url: &str) -> Self {
14 Self {
15 base_url: base_url.trim_end_matches('/').to_string(),
16 client: reqwest::Client::new(),
17 }
18 }
19
20 pub async fn health(&self) -> Result<HealthResponse, Error> {
24 let resp = self
25 .client
26 .get(format!("{}/_fakecloud/health", self.base_url))
27 .send()
28 .await?;
29 Self::parse(resp).await
30 }
31
32 pub async fn reset(&self) -> Result<ResetResponse, Error> {
34 let resp = self
35 .client
36 .post(format!("{}/_reset", self.base_url))
37 .send()
38 .await?;
39 Self::parse(resp).await
40 }
41
42 pub async fn create_admin(
47 &self,
48 account_id: &str,
49 user_name: &str,
50 ) -> Result<CreateAdminResponse, Error> {
51 let resp = self
52 .client
53 .post(format!("{}/_fakecloud/iam/create-admin", self.base_url))
54 .json(&CreateAdminRequest {
55 account_id: account_id.to_string(),
56 user_name: user_name.to_string(),
57 })
58 .send()
59 .await?;
60 Self::parse(resp).await
61 }
62
63 pub async fn reset_service(&self, service: &str) -> Result<ResetServiceResponse, Error> {
65 let resp = self
66 .client
67 .post(format!("{}/_fakecloud/reset/{}", self.base_url, service))
68 .send()
69 .await?;
70 Self::parse(resp).await
71 }
72
73 pub async fn reset_service_for_account(
75 &self,
76 service: &str,
77 account_id: &str,
78 ) -> Result<ResetServiceResponse, Error> {
79 let resp = self
80 .client
81 .post(format!(
82 "{}/_fakecloud/reset/{}/{}",
83 self.base_url, service, account_id
84 ))
85 .send()
86 .await?;
87 Self::parse(resp).await
88 }
89
90 pub fn lambda(&self) -> LambdaClient<'_> {
93 LambdaClient { fc: self }
94 }
95
96 pub fn ses(&self) -> SesClient<'_> {
97 SesClient { fc: self }
98 }
99
100 pub fn sns(&self) -> SnsClient<'_> {
101 SnsClient { fc: self }
102 }
103
104 pub fn sqs(&self) -> SqsClient<'_> {
105 SqsClient { fc: self }
106 }
107
108 pub fn events(&self) -> EventsClient<'_> {
109 EventsClient { fc: self }
110 }
111
112 pub fn s3(&self) -> S3Client<'_> {
113 S3Client { fc: self }
114 }
115
116 pub fn dynamodb(&self) -> DynamoDbClient<'_> {
117 DynamoDbClient { fc: self }
118 }
119
120 pub fn secretsmanager(&self) -> SecretsManagerClient<'_> {
121 SecretsManagerClient { fc: self }
122 }
123
124 pub fn cognito(&self) -> CognitoClient<'_> {
125 CognitoClient { fc: self }
126 }
127
128 pub fn rds(&self) -> RdsClient<'_> {
129 RdsClient { fc: self }
130 }
131
132 pub fn ec2(&self) -> Ec2Client<'_> {
133 Ec2Client { fc: self }
134 }
135
136 pub fn elasticache(&self) -> ElastiCacheClient<'_> {
137 ElastiCacheClient { fc: self }
138 }
139
140 pub fn apigatewayv2(&self) -> ApiGatewayV2Client<'_> {
141 ApiGatewayV2Client { fc: self }
142 }
143
144 pub fn stepfunctions(&self) -> StepFunctionsClient<'_> {
145 StepFunctionsClient { fc: self }
146 }
147
148 pub fn bedrock(&self) -> BedrockClient<'_> {
149 BedrockClient { fc: self }
150 }
151
152 pub fn bedrock_agent(&self) -> BedrockAgentClient<'_> {
153 BedrockAgentClient { fc: self }
154 }
155
156 pub fn bedrock_agent_runtime(&self) -> BedrockAgentRuntimeClient<'_> {
157 BedrockAgentRuntimeClient { fc: self }
158 }
159
160 pub fn ecs(&self) -> EcsClient<'_> {
161 EcsClient { fc: self }
162 }
163
164 pub fn application_autoscaling(&self) -> ApplicationAutoScalingClient<'_> {
165 ApplicationAutoScalingClient { fc: self }
166 }
167
168 pub fn athena(&self) -> AthenaClient<'_> {
169 AthenaClient { fc: self }
170 }
171
172 pub fn organizations(&self) -> OrganizationsClient<'_> {
173 OrganizationsClient { fc: self }
174 }
175
176 pub fn acm(&self) -> AcmClient<'_> {
177 AcmClient { fc: self }
178 }
179
180 pub fn ecr(&self) -> EcrClient<'_> {
181 EcrClient { fc: self }
182 }
183
184 pub fn elbv2(&self) -> Elbv2Client<'_> {
185 Elbv2Client { fc: self }
186 }
187
188 pub fn glue(&self) -> GlueClient<'_> {
189 GlueClient { fc: self }
190 }
191
192 pub fn cloudwatch(&self) -> CloudWatchClient<'_> {
193 CloudWatchClient { fc: self }
194 }
195
196 pub fn firehose(&self) -> FirehoseClient<'_> {
197 FirehoseClient { fc: self }
198 }
199
200 pub fn logs(&self) -> LogsClient<'_> {
201 LogsClient { fc: self }
202 }
203
204 pub fn route53(&self) -> Route53Client<'_> {
205 Route53Client { fc: self }
206 }
207
208 pub fn scheduler(&self) -> SchedulerClient<'_> {
209 SchedulerClient { fc: self }
210 }
211
212 pub fn ssm(&self) -> SsmClient<'_> {
213 SsmClient { fc: self }
214 }
215
216 pub fn kms(&self) -> KmsClient<'_> {
217 KmsClient { fc: self }
218 }
219
220 pub fn wafv2(&self) -> WafV2Client<'_> {
221 WafV2Client { fc: self }
222 }
223
224 pub fn cloudfront(&self) -> CloudFrontClient<'_> {
225 CloudFrontClient { fc: self }
226 }
227
228 async fn parse<T: serde::de::DeserializeOwned>(resp: reqwest::Response) -> Result<T, Error> {
231 let status = resp.status().as_u16();
232 if !resp.status().is_success() {
233 let body = resp.text().await.unwrap_or_default();
234 return Err(Error::Api { status, body });
235 }
236 Ok(resp.json::<T>().await?)
237 }
238}
239
240pub struct Ec2Client<'a> {
243 fc: &'a FakeCloud,
244}
245
246impl Ec2Client<'_> {
247 pub async fn get_instances(&self) -> Result<Ec2InstancesResponse, Error> {
249 let resp = self
250 .fc
251 .client
252 .get(format!("{}/_fakecloud/ec2/instances", self.fc.base_url))
253 .send()
254 .await?;
255 FakeCloud::parse(resp).await
256 }
257
258 pub async fn get_instance_networks(&self) -> Result<Ec2InstanceNetworksResponse, Error> {
263 let resp = self
264 .fc
265 .client
266 .get(format!(
267 "{}/_fakecloud/ec2/instance-networks",
268 self.fc.base_url
269 ))
270 .send()
271 .await?;
272 FakeCloud::parse(resp).await
273 }
274}
275
276pub struct RdsClient<'a> {
277 fc: &'a FakeCloud,
278}
279
280impl RdsClient<'_> {
281 pub async fn get_instances(&self) -> Result<RdsInstancesResponse, Error> {
283 let resp = self
284 .fc
285 .client
286 .get(format!("{}/_fakecloud/rds/instances", self.fc.base_url))
287 .send()
288 .await?;
289 FakeCloud::parse(resp).await
290 }
291
292 pub async fn lambda_invoke(
297 &self,
298 req: &RdsLambdaInvokeRequest,
299 ) -> Result<RdsLambdaInvokeResponse, Error> {
300 let resp = self
301 .fc
302 .client
303 .post(format!("{}/_fakecloud/rds/lambda-invoke", self.fc.base_url))
304 .json(req)
305 .send()
306 .await?;
307 let status = resp.status().as_u16();
308 if status == 502 || resp.status().is_success() {
312 return Ok(resp.json::<RdsLambdaInvokeResponse>().await?);
313 }
314 let body = resp.text().await.unwrap_or_default();
315 Err(Error::Api { status, body })
316 }
317
318 pub async fn s3_import(&self, req: &RdsS3ImportRequest) -> Result<RdsS3ImportResponse, Error> {
321 let resp = self
322 .fc
323 .client
324 .post(format!("{}/_fakecloud/rds/s3-import", self.fc.base_url))
325 .json(req)
326 .send()
327 .await?;
328 FakeCloud::parse(resp).await
329 }
330
331 pub async fn s3_export(&self, req: &RdsS3ExportRequest) -> Result<RdsS3ExportResponse, Error> {
334 let resp = self
335 .fc
336 .client
337 .post(format!("{}/_fakecloud/rds/s3-export", self.fc.base_url))
338 .json(req)
339 .send()
340 .await?;
341 FakeCloud::parse(resp).await
342 }
343}
344
345pub struct ElastiCacheClient<'a> {
348 fc: &'a FakeCloud,
349}
350
351impl ElastiCacheClient<'_> {
352 pub async fn get_clusters(&self) -> Result<ElastiCacheClustersResponse, Error> {
354 let resp = self
355 .fc
356 .client
357 .get(format!(
358 "{}/_fakecloud/elasticache/clusters",
359 self.fc.base_url
360 ))
361 .send()
362 .await?;
363 FakeCloud::parse(resp).await
364 }
365
366 pub async fn get_replication_groups(
368 &self,
369 ) -> Result<ElastiCacheReplicationGroupsResponse, Error> {
370 let resp = self
371 .fc
372 .client
373 .get(format!(
374 "{}/_fakecloud/elasticache/replication-groups",
375 self.fc.base_url
376 ))
377 .send()
378 .await?;
379 FakeCloud::parse(resp).await
380 }
381
382 pub async fn get_serverless_caches(
384 &self,
385 ) -> Result<ElastiCacheServerlessCachesResponse, Error> {
386 let resp = self
387 .fc
388 .client
389 .get(format!(
390 "{}/_fakecloud/elasticache/serverless-caches",
391 self.fc.base_url
392 ))
393 .send()
394 .await?;
395 FakeCloud::parse(resp).await
396 }
397
398 pub async fn get_acls(&self) -> Result<ElastiCacheAclsResponse, Error> {
401 let resp = self
402 .fc
403 .client
404 .get(format!("{}/_fakecloud/elasticache/acls", self.fc.base_url))
405 .send()
406 .await?;
407 FakeCloud::parse(resp).await
408 }
409}
410
411pub struct LambdaClient<'a> {
414 fc: &'a FakeCloud,
415}
416
417impl LambdaClient<'_> {
418 pub async fn get_invocations(&self) -> Result<LambdaInvocationsResponse, Error> {
420 let resp = self
421 .fc
422 .client
423 .get(format!(
424 "{}/_fakecloud/lambda/invocations",
425 self.fc.base_url
426 ))
427 .send()
428 .await?;
429 FakeCloud::parse(resp).await
430 }
431
432 pub async fn get_warm_containers(&self) -> Result<WarmContainersResponse, Error> {
434 let resp = self
435 .fc
436 .client
437 .get(format!(
438 "{}/_fakecloud/lambda/warm-containers",
439 self.fc.base_url
440 ))
441 .send()
442 .await?;
443 FakeCloud::parse(resp).await
444 }
445
446 pub async fn evict_container(
448 &self,
449 function_name: &str,
450 ) -> Result<EvictContainerResponse, Error> {
451 let resp = self
452 .fc
453 .client
454 .post(format!(
455 "{}/_fakecloud/lambda/{}/evict-container",
456 self.fc.base_url, function_name
457 ))
458 .send()
459 .await?;
460 FakeCloud::parse(resp).await
461 }
462
463 pub async fn download_function_code(
467 &self,
468 account_id: &str,
469 function_name: &str,
470 qualifier_or_latest: &str,
471 ) -> Result<Vec<u8>, Error> {
472 let resp = self
473 .fc
474 .client
475 .get(format!(
476 "{}/_fakecloud/lambda/function-code/{}/{}/{}.zip",
477 self.fc.base_url, account_id, function_name, qualifier_or_latest
478 ))
479 .send()
480 .await?;
481 let status = resp.status().as_u16();
482 if !resp.status().is_success() {
483 let body = resp.text().await.unwrap_or_default();
484 return Err(Error::Api { status, body });
485 }
486 Ok(resp.bytes().await?.to_vec())
487 }
488
489 pub async fn download_layer_content(
491 &self,
492 account_id: &str,
493 layer_name: &str,
494 version: i64,
495 ) -> Result<Vec<u8>, Error> {
496 let resp = self
497 .fc
498 .client
499 .get(format!(
500 "{}/_fakecloud/lambda/layer-content/{}/{}/{}.zip",
501 self.fc.base_url, account_id, layer_name, version
502 ))
503 .send()
504 .await?;
505 let status = resp.status().as_u16();
506 if !resp.status().is_success() {
507 let body = resp.text().await.unwrap_or_default();
508 return Err(Error::Api { status, body });
509 }
510 Ok(resp.bytes().await?.to_vec())
511 }
512}
513
514pub struct SesClient<'a> {
517 fc: &'a FakeCloud,
518}
519
520impl SesClient<'_> {
521 pub async fn get_emails(&self) -> Result<SesEmailsResponse, Error> {
523 let resp = self
524 .fc
525 .client
526 .get(format!("{}/_fakecloud/ses/emails", self.fc.base_url))
527 .send()
528 .await?;
529 FakeCloud::parse(resp).await
530 }
531
532 pub async fn simulate_inbound(
534 &self,
535 req: &InboundEmailRequest,
536 ) -> Result<InboundEmailResponse, Error> {
537 let resp = self
538 .fc
539 .client
540 .post(format!("{}/_fakecloud/ses/inbound", self.fc.base_url))
541 .json(req)
542 .send()
543 .await?;
544 FakeCloud::parse(resp).await
545 }
546
547 pub async fn get_metrics(&self) -> Result<SesMetricsResponse, Error> {
550 let resp = self
551 .fc
552 .client
553 .get(format!("{}/_fakecloud/ses/metrics", self.fc.base_url))
554 .send()
555 .await?;
556 FakeCloud::parse(resp).await
557 }
558
559 pub async fn get_bounces(&self) -> Result<SesBouncesResponse, Error> {
561 let resp = self
562 .fc
563 .client
564 .get(format!("{}/_fakecloud/ses/bounces", self.fc.base_url))
565 .send()
566 .await?;
567 FakeCloud::parse(resp).await
568 }
569
570 pub async fn set_sandbox(&self, sandbox: bool) -> Result<SesSandboxResponse, Error> {
574 let resp = self
575 .fc
576 .client
577 .post(format!(
578 "{}/_fakecloud/ses/account/sandbox",
579 self.fc.base_url
580 ))
581 .json(&SesSandboxRequest { sandbox })
582 .send()
583 .await?;
584 FakeCloud::parse(resp).await
585 }
586
587 pub async fn get_event_destination_deliveries(
590 &self,
591 ) -> Result<SesEventDestinationDeliveriesResponse, Error> {
592 let resp = self
593 .fc
594 .client
595 .get(format!(
596 "{}/_fakecloud/ses/event-destinations/deliveries",
597 self.fc.base_url
598 ))
599 .send()
600 .await?;
601 FakeCloud::parse(resp).await
602 }
603
604 pub async fn get_dkim_public_key(
607 &self,
608 identity: &str,
609 ) -> Result<SesDkimPublicKeyResponse, Error> {
610 let resp = self
611 .fc
612 .client
613 .get(format!(
614 "{}/_fakecloud/ses/identities/{}/dkim-public-key",
615 self.fc.base_url, identity
616 ))
617 .send()
618 .await?;
619 FakeCloud::parse(resp).await
620 }
621
622 pub async fn set_mail_from_status(
625 &self,
626 identity: &str,
627 status: &str,
628 ) -> Result<SesMailFromStatusResponse, Error> {
629 let resp = self
630 .fc
631 .client
632 .post(format!(
633 "{}/_fakecloud/ses/identities/{}/mail-from-status",
634 self.fc.base_url, identity
635 ))
636 .json(&SesMailFromStatusRequest {
637 status: status.to_string(),
638 })
639 .send()
640 .await?;
641 FakeCloud::parse(resp).await
642 }
643
644 pub async fn get_message_insights(
647 &self,
648 message_id: &str,
649 ) -> Result<SesMessageInsightsResponse, Error> {
650 let resp = self
651 .fc
652 .client
653 .get(format!(
654 "{}/_fakecloud/ses/messages/{}/insights",
655 self.fc.base_url, message_id
656 ))
657 .send()
658 .await?;
659 FakeCloud::parse(resp).await
660 }
661
662 pub async fn get_smtp_submissions(&self) -> Result<SesSmtpSubmissionsResponse, Error> {
664 let resp = self
665 .fc
666 .client
667 .get(format!(
668 "{}/_fakecloud/ses/smtp/submissions",
669 self.fc.base_url
670 ))
671 .send()
672 .await?;
673 FakeCloud::parse(resp).await
674 }
675}
676
677pub struct SnsClient<'a> {
680 fc: &'a FakeCloud,
681}
682
683impl SnsClient<'_> {
684 pub async fn get_messages(&self) -> Result<SnsMessagesResponse, Error> {
686 let resp = self
687 .fc
688 .client
689 .get(format!("{}/_fakecloud/sns/messages", self.fc.base_url))
690 .send()
691 .await?;
692 FakeCloud::parse(resp).await
693 }
694
695 pub async fn get_pending_confirmations(&self) -> Result<PendingConfirmationsResponse, Error> {
697 let resp = self
698 .fc
699 .client
700 .get(format!(
701 "{}/_fakecloud/sns/pending-confirmations",
702 self.fc.base_url
703 ))
704 .send()
705 .await?;
706 FakeCloud::parse(resp).await
707 }
708
709 pub async fn confirm_subscription(
711 &self,
712 req: &ConfirmSubscriptionRequest,
713 ) -> Result<ConfirmSubscriptionResponse, Error> {
714 let resp = self
715 .fc
716 .client
717 .post(format!(
718 "{}/_fakecloud/sns/confirm-subscription",
719 self.fc.base_url
720 ))
721 .json(req)
722 .send()
723 .await?;
724 FakeCloud::parse(resp).await
725 }
726
727 pub async fn cert_pem(&self) -> Result<String, Error> {
732 let resp = self
733 .fc
734 .client
735 .get(format!("{}/_fakecloud/sns/cert.pem", self.fc.base_url))
736 .send()
737 .await?;
738 let status = resp.status().as_u16();
739 if !resp.status().is_success() {
740 let body = resp.text().await.unwrap_or_default();
741 return Err(Error::Api { status, body });
742 }
743 Ok(resp.text().await?)
744 }
745
746 pub async fn sms(&self) -> Result<SnsSmsResponse, Error> {
748 let resp = self
749 .fc
750 .client
751 .get(format!("{}/_fakecloud/sns/sms", self.fc.base_url))
752 .send()
753 .await?;
754 FakeCloud::parse(resp).await
755 }
756}
757
758pub struct SqsClient<'a> {
761 fc: &'a FakeCloud,
762}
763
764impl SqsClient<'_> {
765 pub async fn get_messages(&self) -> Result<SqsMessagesResponse, Error> {
767 let resp = self
768 .fc
769 .client
770 .get(format!("{}/_fakecloud/sqs/messages", self.fc.base_url))
771 .send()
772 .await?;
773 FakeCloud::parse(resp).await
774 }
775
776 pub async fn tick_expiration(&self) -> Result<ExpirationTickResponse, Error> {
778 let resp = self
779 .fc
780 .client
781 .post(format!(
782 "{}/_fakecloud/sqs/expiration-processor/tick",
783 self.fc.base_url
784 ))
785 .send()
786 .await?;
787 FakeCloud::parse(resp).await
788 }
789
790 pub async fn force_dlq(&self, queue_name: &str) -> Result<ForceDlqResponse, Error> {
792 let resp = self
793 .fc
794 .client
795 .post(format!(
796 "{}/_fakecloud/sqs/{}/force-dlq",
797 self.fc.base_url, queue_name
798 ))
799 .send()
800 .await?;
801 FakeCloud::parse(resp).await
802 }
803}
804
805pub struct ApplicationAutoScalingClient<'a> {
808 fc: &'a FakeCloud,
809}
810
811impl ApplicationAutoScalingClient<'_> {
812 pub async fn tick(&self) -> Result<AppAsTickResponse, Error> {
817 let resp = self
818 .fc
819 .client
820 .post(format!(
821 "{}/_fakecloud/application-autoscaling/tick",
822 self.fc.base_url
823 ))
824 .send()
825 .await?;
826 FakeCloud::parse(resp).await
827 }
828
829 pub async fn scheduled_tick(&self) -> Result<AppAsScheduledTickResponse, Error> {
834 let resp = self
835 .fc
836 .client
837 .post(format!(
838 "{}/_fakecloud/application-autoscaling/scheduled-tick",
839 self.fc.base_url
840 ))
841 .send()
842 .await?;
843 FakeCloud::parse(resp).await
844 }
845}
846
847pub struct EventsClient<'a> {
850 fc: &'a FakeCloud,
851}
852
853impl EventsClient<'_> {
854 pub async fn get_history(&self) -> Result<EventHistoryResponse, Error> {
856 let resp = self
857 .fc
858 .client
859 .get(format!("{}/_fakecloud/events/history", self.fc.base_url))
860 .send()
861 .await?;
862 FakeCloud::parse(resp).await
863 }
864
865 pub async fn fire_rule(&self, req: &FireRuleRequest) -> Result<FireRuleResponse, Error> {
867 let resp = self
868 .fc
869 .client
870 .post(format!("{}/_fakecloud/events/fire-rule", self.fc.base_url))
871 .json(req)
872 .send()
873 .await?;
874 FakeCloud::parse(resp).await
875 }
876}
877
878pub struct S3Client<'a> {
881 fc: &'a FakeCloud,
882}
883
884impl S3Client<'_> {
885 pub async fn get_notifications(&self) -> Result<S3NotificationsResponse, Error> {
887 let resp = self
888 .fc
889 .client
890 .get(format!("{}/_fakecloud/s3/notifications", self.fc.base_url))
891 .send()
892 .await?;
893 FakeCloud::parse(resp).await
894 }
895
896 pub async fn tick_lifecycle(&self) -> Result<LifecycleTickResponse, Error> {
898 let resp = self
899 .fc
900 .client
901 .post(format!(
902 "{}/_fakecloud/s3/lifecycle-processor/tick",
903 self.fc.base_url
904 ))
905 .send()
906 .await?;
907 FakeCloud::parse(resp).await
908 }
909
910 pub async fn get_access_points(&self) -> Result<S3AccessPointsResponse, Error> {
912 let resp = self
913 .fc
914 .client
915 .get(format!("{}/_fakecloud/s3/access-points", self.fc.base_url))
916 .send()
917 .await?;
918 FakeCloud::parse(resp).await
919 }
920
921 pub async fn get_object_lambda_responses(
923 &self,
924 ) -> Result<S3ObjectLambdaResponsesResponse, Error> {
925 let resp = self
926 .fc
927 .client
928 .get(format!(
929 "{}/_fakecloud/s3/object-lambda-responses",
930 self.fc.base_url
931 ))
932 .send()
933 .await?;
934 FakeCloud::parse(resp).await
935 }
936}
937
938pub struct DynamoDbClient<'a> {
941 fc: &'a FakeCloud,
942}
943
944impl DynamoDbClient<'_> {
945 pub async fn tick_ttl(&self) -> Result<TtlTickResponse, Error> {
947 let resp = self
948 .fc
949 .client
950 .post(format!(
951 "{}/_fakecloud/dynamodb/ttl-processor/tick",
952 self.fc.base_url
953 ))
954 .send()
955 .await?;
956 FakeCloud::parse(resp).await
957 }
958
959 pub async fn save_snapshot(
965 &self,
966 data_path: Option<&str>,
967 ) -> Result<DynamoDbSnapshotSaveResponse, Error> {
968 let resp = self
969 .fc
970 .client
971 .post(format!(
972 "{}/_fakecloud/dynamodb/snapshot/save",
973 self.fc.base_url
974 ))
975 .json(&DynamoDbSnapshotSaveRequest {
976 data_path: data_path.map(str::to_string),
977 })
978 .send()
979 .await?;
980 FakeCloud::parse(resp).await
981 }
982}
983
984pub struct SecretsManagerClient<'a> {
987 fc: &'a FakeCloud,
988}
989
990impl SecretsManagerClient<'_> {
991 pub async fn tick_rotation(&self) -> Result<RotationTickResponse, Error> {
993 let resp = self
994 .fc
995 .client
996 .post(format!(
997 "{}/_fakecloud/secretsmanager/rotation-scheduler/tick",
998 self.fc.base_url
999 ))
1000 .send()
1001 .await?;
1002 FakeCloud::parse(resp).await
1003 }
1004}
1005
1006pub struct CognitoClient<'a> {
1009 fc: &'a FakeCloud,
1010}
1011
1012impl CognitoClient<'_> {
1013 pub async fn get_user_codes(
1015 &self,
1016 pool_id: &str,
1017 username: &str,
1018 ) -> Result<UserConfirmationCodes, Error> {
1019 let resp = self
1020 .fc
1021 .client
1022 .get(format!(
1023 "{}/_fakecloud/cognito/confirmation-codes/{}/{}",
1024 self.fc.base_url, pool_id, username
1025 ))
1026 .send()
1027 .await?;
1028 FakeCloud::parse(resp).await
1029 }
1030
1031 pub async fn get_confirmation_codes(&self) -> Result<ConfirmationCodesResponse, Error> {
1033 let resp = self
1034 .fc
1035 .client
1036 .get(format!(
1037 "{}/_fakecloud/cognito/confirmation-codes",
1038 self.fc.base_url
1039 ))
1040 .send()
1041 .await?;
1042 FakeCloud::parse(resp).await
1043 }
1044
1045 pub async fn confirm_user(
1047 &self,
1048 req: &ConfirmUserRequest,
1049 ) -> Result<ConfirmUserResponse, Error> {
1050 let resp = self
1051 .fc
1052 .client
1053 .post(format!(
1054 "{}/_fakecloud/cognito/confirm-user",
1055 self.fc.base_url
1056 ))
1057 .json(req)
1058 .send()
1059 .await?;
1060 let status = resp.status().as_u16();
1061 let body: ConfirmUserResponse = resp.json().await?;
1062 if status >= 400 {
1063 return Err(Error::Api {
1064 status,
1065 body: body.error.unwrap_or_default(),
1066 });
1067 }
1068 Ok(body)
1069 }
1070
1071 pub async fn get_tokens(&self) -> Result<TokensResponse, Error> {
1073 let resp = self
1074 .fc
1075 .client
1076 .get(format!("{}/_fakecloud/cognito/tokens", self.fc.base_url))
1077 .send()
1078 .await?;
1079 FakeCloud::parse(resp).await
1080 }
1081
1082 pub async fn expire_tokens(
1084 &self,
1085 req: &ExpireTokensRequest,
1086 ) -> Result<ExpireTokensResponse, Error> {
1087 let resp = self
1088 .fc
1089 .client
1090 .post(format!(
1091 "{}/_fakecloud/cognito/expire-tokens",
1092 self.fc.base_url
1093 ))
1094 .json(req)
1095 .send()
1096 .await?;
1097 FakeCloud::parse(resp).await
1098 }
1099
1100 pub async fn get_auth_events(&self) -> Result<AuthEventsResponse, Error> {
1102 let resp = self
1103 .fc
1104 .client
1105 .get(format!(
1106 "{}/_fakecloud/cognito/auth-events",
1107 self.fc.base_url
1108 ))
1109 .send()
1110 .await?;
1111 FakeCloud::parse(resp).await
1112 }
1113
1114 pub async fn get_pre_token_gen_invocations(
1120 &self,
1121 ) -> Result<PreTokenGenInvocationsResponse, Error> {
1122 let resp = self
1123 .fc
1124 .client
1125 .get(format!(
1126 "{}/_fakecloud/cognito/pretokengen/invocations",
1127 self.fc.base_url
1128 ))
1129 .send()
1130 .await?;
1131 FakeCloud::parse(resp).await
1132 }
1133
1134 pub async fn mint_authorization_code(
1138 &self,
1139 req: &MintAuthorizationCodeRequest,
1140 ) -> Result<MintAuthorizationCodeResponse, Error> {
1141 let resp = self
1142 .fc
1143 .client
1144 .post(format!(
1145 "{}/_fakecloud/cognito/authorization-codes",
1146 self.fc.base_url
1147 ))
1148 .json(req)
1149 .send()
1150 .await?;
1151 FakeCloud::parse(resp).await
1152 }
1153
1154 pub async fn set_compromised_passwords(
1159 &self,
1160 req: &CognitoCompromisedPasswordsRequest,
1161 ) -> Result<CompromisedPasswordsResponse, Error> {
1162 let resp = self
1163 .fc
1164 .client
1165 .post(format!(
1166 "{}/_fakecloud/cognito/compromised-passwords",
1167 self.fc.base_url
1168 ))
1169 .json(req)
1170 .send()
1171 .await?;
1172 FakeCloud::parse(resp).await
1173 }
1174
1175 pub async fn get_webauthn_credentials(&self) -> Result<WebAuthnCredentialsResponse, Error> {
1177 let resp = self
1178 .fc
1179 .client
1180 .get(format!(
1181 "{}/_fakecloud/cognito/webauthn-credentials",
1182 self.fc.base_url
1183 ))
1184 .send()
1185 .await?;
1186 FakeCloud::parse(resp).await
1187 }
1188}
1189
1190pub struct ApiGatewayV2Client<'a> {
1193 fc: &'a FakeCloud,
1194}
1195
1196impl ApiGatewayV2Client<'_> {
1197 pub async fn get_requests(&self) -> Result<ApiGatewayV2RequestsResponse, Error> {
1199 let resp = self
1200 .fc
1201 .client
1202 .get(format!(
1203 "{}/_fakecloud/apigatewayv2/requests",
1204 self.fc.base_url
1205 ))
1206 .send()
1207 .await?;
1208 FakeCloud::parse(resp).await
1209 }
1210
1211 pub async fn connections(&self) -> Result<ApiGatewayV2ConnectionsResponse, Error> {
1214 let resp = self
1215 .fc
1216 .client
1217 .get(format!(
1218 "{}/_fakecloud/apigatewayv2/connections",
1219 self.fc.base_url
1220 ))
1221 .send()
1222 .await?;
1223 FakeCloud::parse(resp).await
1224 }
1225
1226 pub async fn mtls_info(&self, name: &str) -> Result<serde_json::Value, Error> {
1230 let resp = self
1231 .fc
1232 .client
1233 .get(format!(
1234 "{}/_fakecloud/apigatewayv2/domain-names/{}/mtls-info",
1235 self.fc.base_url, name
1236 ))
1237 .send()
1238 .await?;
1239 FakeCloud::parse(resp).await
1240 }
1241
1242 pub fn ws_url(&self, api_id: &str, stage: Option<&str>) -> String {
1246 let base = self
1247 .fc
1248 .base_url
1249 .replacen("https://", "wss://", 1)
1250 .replacen("http://", "ws://", 1);
1251 let url = reqwest::Url::parse(&format!("{}/_fakecloud/apigatewayv2/ws/{}", base, api_id))
1255 .expect("base url + api id form a valid URL");
1256 match stage {
1257 Some(s) => {
1258 let mut u = url;
1259 u.query_pairs_mut().append_pair("stage", s);
1260 u.to_string()
1261 }
1262 None => url.to_string(),
1263 }
1264 }
1265}
1266
1267pub struct StepFunctionsClient<'a> {
1270 fc: &'a FakeCloud,
1271}
1272
1273impl StepFunctionsClient<'_> {
1274 pub async fn get_executions(&self) -> Result<StepFunctionsExecutionsResponse, Error> {
1276 let resp = self
1277 .fc
1278 .client
1279 .get(format!(
1280 "{}/_fakecloud/stepfunctions/executions",
1281 self.fc.base_url
1282 ))
1283 .send()
1284 .await?;
1285 FakeCloud::parse(resp).await
1286 }
1287
1288 pub async fn get_sync_executions(&self) -> Result<StepFunctionsSyncExecutionsResponse, Error> {
1292 let resp = self
1293 .fc
1294 .client
1295 .get(format!(
1296 "{}/_fakecloud/stepfunctions/sync-executions",
1297 self.fc.base_url
1298 ))
1299 .send()
1300 .await?;
1301 FakeCloud::parse(resp).await
1302 }
1303
1304 pub async fn enqueue_activity_task(
1312 &self,
1313 req: &SfnEnqueueActivityTaskRequest,
1314 ) -> Result<SfnEnqueueActivityTaskResponse, Error> {
1315 let resp = self
1316 .fc
1317 .client
1318 .post(format!(
1319 "{}/_fakecloud/stepfunctions/enqueue-activity-task",
1320 self.fc.base_url
1321 ))
1322 .json(req)
1323 .send()
1324 .await?;
1325 FakeCloud::parse(resp).await
1326 }
1327
1328 pub async fn get_execution_tree(
1329 &self,
1330 execution_arn: &str,
1331 ) -> Result<StepFunctionsExecutionTreeResponse, Error> {
1332 let mut encoded = String::with_capacity(execution_arn.len());
1333 for b in execution_arn.bytes() {
1334 match b {
1335 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1336 encoded.push(b as char);
1337 }
1338 _ => encoded.push_str(&format!("%{:02X}", b)),
1339 }
1340 }
1341 let resp = self
1342 .fc
1343 .client
1344 .get(format!(
1345 "{}/_fakecloud/stepfunctions/execution-tree/{}",
1346 self.fc.base_url, encoded
1347 ))
1348 .send()
1349 .await?;
1350 FakeCloud::parse(resp).await
1351 }
1352}
1353
1354pub struct BedrockClient<'a> {
1357 fc: &'a FakeCloud,
1358}
1359
1360impl BedrockClient<'_> {
1361 pub async fn get_invocations(&self) -> Result<BedrockInvocationsResponse, Error> {
1364 let resp = self
1365 .fc
1366 .client
1367 .get(format!(
1368 "{}/_fakecloud/bedrock/invocations",
1369 self.fc.base_url
1370 ))
1371 .send()
1372 .await?;
1373 FakeCloud::parse(resp).await
1374 }
1375
1376 pub async fn set_model_response(
1378 &self,
1379 model_id: &str,
1380 response: &str,
1381 ) -> Result<BedrockModelResponseConfig, Error> {
1382 let resp = self
1383 .fc
1384 .client
1385 .post(format!(
1386 "{}/_fakecloud/bedrock/models/{}/response",
1387 self.fc.base_url, model_id
1388 ))
1389 .header("content-type", "text/plain")
1390 .body(response.to_string())
1391 .send()
1392 .await?;
1393 FakeCloud::parse(resp).await
1394 }
1395
1396 pub async fn set_response_rules(
1398 &self,
1399 model_id: &str,
1400 rules: &[BedrockResponseRule],
1401 ) -> Result<BedrockModelResponseConfig, Error> {
1402 let body = serde_json::json!({ "rules": rules });
1403 let resp = self
1404 .fc
1405 .client
1406 .post(format!(
1407 "{}/_fakecloud/bedrock/models/{}/responses",
1408 self.fc.base_url, model_id
1409 ))
1410 .json(&body)
1411 .send()
1412 .await?;
1413 FakeCloud::parse(resp).await
1414 }
1415
1416 pub async fn clear_response_rules(
1418 &self,
1419 model_id: &str,
1420 ) -> Result<BedrockModelResponseConfig, Error> {
1421 let resp = self
1422 .fc
1423 .client
1424 .delete(format!(
1425 "{}/_fakecloud/bedrock/models/{}/responses",
1426 self.fc.base_url, model_id
1427 ))
1428 .send()
1429 .await?;
1430 FakeCloud::parse(resp).await
1431 }
1432
1433 pub async fn queue_fault(
1435 &self,
1436 rule: &BedrockFaultRule,
1437 ) -> Result<BedrockStatusResponse, Error> {
1438 let resp = self
1439 .fc
1440 .client
1441 .post(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1442 .json(rule)
1443 .send()
1444 .await?;
1445 FakeCloud::parse(resp).await
1446 }
1447
1448 pub async fn get_faults(&self) -> Result<BedrockFaultsResponse, Error> {
1450 let resp = self
1451 .fc
1452 .client
1453 .get(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1454 .send()
1455 .await?;
1456 FakeCloud::parse(resp).await
1457 }
1458
1459 pub async fn clear_faults(&self) -> Result<BedrockStatusResponse, Error> {
1461 let resp = self
1462 .fc
1463 .client
1464 .delete(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1465 .send()
1466 .await?;
1467 FakeCloud::parse(resp).await
1468 }
1469}
1470
1471pub struct BedrockAgentClient<'a> {
1474 fc: &'a FakeCloud,
1475}
1476
1477impl BedrockAgentClient<'_> {
1478 pub async fn get_agents(&self) -> Result<BedrockAgentAgentsResponse, Error> {
1482 let resp = self
1483 .fc
1484 .client
1485 .get(format!(
1486 "{}/_fakecloud/bedrock-agent/agents",
1487 self.fc.base_url
1488 ))
1489 .send()
1490 .await?;
1491 FakeCloud::parse(resp).await
1492 }
1493}
1494
1495pub struct BedrockAgentRuntimeClient<'a> {
1498 fc: &'a FakeCloud,
1499}
1500
1501impl BedrockAgentRuntimeClient<'_> {
1502 pub async fn get_invocations(&self) -> Result<BedrockAgentRuntimeInvocationsResponse, Error> {
1505 let resp = self
1506 .fc
1507 .client
1508 .get(format!(
1509 "{}/_fakecloud/bedrock-agent-runtime/invocations",
1510 self.fc.base_url
1511 ))
1512 .send()
1513 .await?;
1514 FakeCloud::parse(resp).await
1515 }
1516}
1517
1518pub struct EcsClient<'a> {
1521 fc: &'a FakeCloud,
1522}
1523
1524impl EcsClient<'_> {
1525 pub async fn get_clusters(&self) -> Result<EcsClustersResponse, Error> {
1529 let resp = self
1530 .fc
1531 .client
1532 .get(format!("{}/_fakecloud/ecs/clusters", self.fc.base_url))
1533 .send()
1534 .await?;
1535 FakeCloud::parse(resp).await
1536 }
1537
1538 pub async fn get_tasks(
1541 &self,
1542 cluster: Option<&str>,
1543 status: Option<&str>,
1544 ) -> Result<EcsTasksResponse, Error> {
1545 fn encode(s: &str) -> String {
1546 let mut out = String::with_capacity(s.len());
1547 for b in s.bytes() {
1548 match b {
1549 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1550 out.push(b as char);
1551 }
1552 _ => out.push_str(&format!("%{:02X}", b)),
1553 }
1554 }
1555 out
1556 }
1557 let mut url = format!("{}/_fakecloud/ecs/tasks", self.fc.base_url);
1558 let mut sep = '?';
1559 if let Some(c) = cluster {
1560 url.push(sep);
1561 url.push_str("cluster=");
1562 url.push_str(&encode(c));
1563 sep = '&';
1564 }
1565 if let Some(s) = status {
1566 url.push(sep);
1567 url.push_str("status=");
1568 url.push_str(&encode(s));
1569 }
1570 let resp = self.fc.client.get(url).send().await?;
1571 FakeCloud::parse(resp).await
1572 }
1573
1574 pub async fn get_task_logs(&self, task_id: &str) -> Result<EcsTaskLogsResponse, Error> {
1578 let resp = self
1579 .fc
1580 .client
1581 .get(format!(
1582 "{}/_fakecloud/ecs/tasks/{}/logs",
1583 self.fc.base_url, task_id
1584 ))
1585 .send()
1586 .await?;
1587 FakeCloud::parse(resp).await
1588 }
1589
1590 pub async fn force_stop_task(&self, task_id: &str) -> Result<EcsTask, Error> {
1592 let resp = self
1593 .fc
1594 .client
1595 .post(format!(
1596 "{}/_fakecloud/ecs/tasks/{}/force-stop",
1597 self.fc.base_url, task_id
1598 ))
1599 .send()
1600 .await?;
1601 FakeCloud::parse(resp).await
1602 }
1603
1604 pub async fn mark_task_failed(
1607 &self,
1608 task_id: &str,
1609 req: &EcsMarkFailedRequest,
1610 ) -> Result<EcsTask, Error> {
1611 let resp = self
1612 .fc
1613 .client
1614 .post(format!(
1615 "{}/_fakecloud/ecs/tasks/{}/mark-failed",
1616 self.fc.base_url, task_id
1617 ))
1618 .json(req)
1619 .send()
1620 .await?;
1621 FakeCloud::parse(resp).await
1622 }
1623
1624 pub async fn get_events(&self) -> Result<EcsEventsResponse, Error> {
1626 let resp = self
1627 .fc
1628 .client
1629 .get(format!("{}/_fakecloud/ecs/events", self.fc.base_url))
1630 .send()
1631 .await?;
1632 FakeCloud::parse(resp).await
1633 }
1634
1635 pub async fn get_metadata_by_arn(&self, task_arn: &str) -> Result<serde_json::Value, Error> {
1642 let mut encoded = String::with_capacity(task_arn.len());
1643 for b in task_arn.bytes() {
1644 match b {
1645 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1646 encoded.push(b as char);
1647 }
1648 _ => encoded.push_str(&format!("%{:02X}", b)),
1649 }
1650 }
1651 let resp = self
1652 .fc
1653 .client
1654 .get(format!(
1655 "{}/_fakecloud/ecs/metadata/{}",
1656 self.fc.base_url, encoded
1657 ))
1658 .send()
1659 .await?;
1660 FakeCloud::parse(resp).await
1661 }
1662
1663 pub async fn task_credentials(
1668 &self,
1669 task_id: &str,
1670 ) -> Result<EcsTaskCredentialsResponse, Error> {
1671 let resp = self
1672 .fc
1673 .client
1674 .get(format!(
1675 "{}/_fakecloud/ecs/creds/{}",
1676 self.fc.base_url, task_id
1677 ))
1678 .send()
1679 .await?;
1680 FakeCloud::parse(resp).await
1681 }
1682
1683 pub async fn task_metadata_v3(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1689 let resp = self
1690 .fc
1691 .client
1692 .get(format!(
1693 "{}/_fakecloud/ecs/v3/{}",
1694 self.fc.base_url, task_id
1695 ))
1696 .send()
1697 .await?;
1698 FakeCloud::parse(resp).await
1699 }
1700
1701 pub async fn task_metadata_v4(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1705 let resp = self
1706 .fc
1707 .client
1708 .get(format!(
1709 "{}/_fakecloud/ecs/v4/{}",
1710 self.fc.base_url, task_id
1711 ))
1712 .send()
1713 .await?;
1714 FakeCloud::parse(resp).await
1715 }
1716}
1717
1718pub struct Route53Client<'a> {
1721 fc: &'a FakeCloud,
1722}
1723
1724impl Route53Client<'_> {
1725 pub async fn dnssec_material(
1729 &self,
1730 zone_id: &str,
1731 ) -> Result<Route53DnssecMaterialResponse, Error> {
1732 let resp = self
1733 .fc
1734 .client
1735 .get(format!(
1736 "{}/_fakecloud/route53/zones/{}/dnssec",
1737 self.fc.base_url, zone_id
1738 ))
1739 .send()
1740 .await?;
1741 FakeCloud::parse(resp).await
1742 }
1743
1744 pub async fn dnssec_sign(
1748 &self,
1749 zone_id: &str,
1750 req: &Route53DnssecSignRequest,
1751 ) -> Result<Route53DnssecSignResponse, Error> {
1752 let resp = self
1753 .fc
1754 .client
1755 .post(format!(
1756 "{}/_fakecloud/route53/zones/{}/dnssec/sign",
1757 self.fc.base_url, zone_id
1758 ))
1759 .json(req)
1760 .send()
1761 .await?;
1762 FakeCloud::parse(resp).await
1763 }
1764}
1765
1766pub struct AthenaClient<'a> {
1769 fc: &'a FakeCloud,
1770}
1771
1772impl AthenaClient<'_> {
1773 pub async fn get_named_queries(&self) -> Result<AthenaNamedQueriesResponse, Error> {
1778 let resp = self
1779 .fc
1780 .client
1781 .get(format!(
1782 "{}/_fakecloud/athena/named-queries",
1783 self.fc.base_url
1784 ))
1785 .send()
1786 .await?;
1787 FakeCloud::parse(resp).await
1788 }
1789}
1790
1791pub struct OrganizationsClient<'a> {
1794 fc: &'a FakeCloud,
1795}
1796
1797impl OrganizationsClient<'_> {
1798 pub async fn get_accounts(&self) -> Result<OrganizationsAccountsResponse, Error> {
1803 let resp = self
1804 .fc
1805 .client
1806 .get(format!(
1807 "{}/_fakecloud/organizations/accounts",
1808 self.fc.base_url
1809 ))
1810 .send()
1811 .await?;
1812 FakeCloud::parse(resp).await
1813 }
1814
1815 pub async fn get_responsibility_transfers(
1819 &self,
1820 ) -> Result<OrganizationsResponsibilityTransfersResponse, Error> {
1821 let resp = self
1822 .fc
1823 .client
1824 .get(format!(
1825 "{}/_fakecloud/organizations/responsibility-transfers",
1826 self.fc.base_url
1827 ))
1828 .send()
1829 .await?;
1830 FakeCloud::parse(resp).await
1831 }
1832}
1833
1834pub struct AcmClient<'a> {
1837 fc: &'a FakeCloud,
1838}
1839
1840impl AcmClient<'_> {
1841 fn certificate_id(arn_or_id: &str) -> String {
1842 match arn_or_id.rfind("certificate/") {
1843 Some(idx) => arn_or_id[idx + "certificate/".len()..].to_string(),
1844 None => arn_or_id.to_string(),
1845 }
1846 }
1847
1848 pub async fn set_certificate_status(
1853 &self,
1854 arn_or_id: &str,
1855 req: &AcmCertificateStatusRequest,
1856 ) -> Result<(), Error> {
1857 let id = Self::certificate_id(arn_or_id);
1858 let resp = self
1859 .fc
1860 .client
1861 .post(format!(
1862 "{}/_fakecloud/acm/certificates/{}/status",
1863 self.fc.base_url, id
1864 ))
1865 .json(req)
1866 .send()
1867 .await?;
1868 if !resp.status().is_success() {
1869 let status = resp.status().as_u16();
1870 let body = resp.text().await.unwrap_or_default();
1871 return Err(Error::Api { status, body });
1872 }
1873 Ok(())
1874 }
1875
1876 pub async fn get_certificate_chain_info(
1880 &self,
1881 arn_or_id: &str,
1882 ) -> Result<AcmCertificateChainInfo, Error> {
1883 let id = Self::certificate_id(arn_or_id);
1884 let resp = self
1885 .fc
1886 .client
1887 .get(format!(
1888 "{}/_fakecloud/acm/certificates/{}/chain-info",
1889 self.fc.base_url, id
1890 ))
1891 .send()
1892 .await?;
1893 FakeCloud::parse(resp).await
1894 }
1895
1896 pub async fn approve_certificate(&self, arn_or_id: &str) -> Result<(), Error> {
1900 let id = Self::certificate_id(arn_or_id);
1901 let resp = self
1902 .fc
1903 .client
1904 .post(format!(
1905 "{}/_fakecloud/acm/certificates/{}/approve",
1906 self.fc.base_url, id
1907 ))
1908 .send()
1909 .await?;
1910 if !resp.status().is_success() {
1911 let status = resp.status().as_u16();
1912 let body = resp.text().await.unwrap_or_default();
1913 return Err(Error::Api { status, body });
1914 }
1915 Ok(())
1916 }
1917}
1918
1919pub struct EcrClient<'a> {
1922 fc: &'a FakeCloud,
1923}
1924
1925impl EcrClient<'_> {
1926 pub async fn get_images(&self) -> Result<EcrImagesResponse, Error> {
1928 let resp = self
1929 .fc
1930 .client
1931 .get(format!("{}/_fakecloud/ecr/images", self.fc.base_url))
1932 .send()
1933 .await?;
1934 FakeCloud::parse(resp).await
1935 }
1936
1937 pub async fn get_repositories(&self) -> Result<EcrRepositoriesResponse, Error> {
1939 let resp = self
1940 .fc
1941 .client
1942 .get(format!("{}/_fakecloud/ecr/repositories", self.fc.base_url))
1943 .send()
1944 .await?;
1945 FakeCloud::parse(resp).await
1946 }
1947
1948 pub async fn get_pull_through_rules(&self) -> Result<EcrPullThroughRulesResponse, Error> {
1950 let resp = self
1951 .fc
1952 .client
1953 .get(format!(
1954 "{}/_fakecloud/ecr/pull-through-rules",
1955 self.fc.base_url
1956 ))
1957 .send()
1958 .await?;
1959 FakeCloud::parse(resp).await
1960 }
1961}
1962
1963pub struct Elbv2Client<'a> {
1966 fc: &'a FakeCloud,
1967}
1968
1969impl Elbv2Client<'_> {
1970 pub async fn get_load_balancers(&self) -> Result<Elbv2LoadBalancersResponse, Error> {
1972 let resp = self
1973 .fc
1974 .client
1975 .get(format!(
1976 "{}/_fakecloud/elbv2/load-balancers",
1977 self.fc.base_url
1978 ))
1979 .send()
1980 .await?;
1981 FakeCloud::parse(resp).await
1982 }
1983
1984 pub async fn get_listeners(&self) -> Result<Elbv2ListenersResponse, Error> {
1986 let resp = self
1987 .fc
1988 .client
1989 .get(format!("{}/_fakecloud/elbv2/listeners", self.fc.base_url))
1990 .send()
1991 .await?;
1992 FakeCloud::parse(resp).await
1993 }
1994
1995 pub async fn get_rules(&self) -> Result<Elbv2RulesResponse, Error> {
1997 let resp = self
1998 .fc
1999 .client
2000 .get(format!("{}/_fakecloud/elbv2/rules", self.fc.base_url))
2001 .send()
2002 .await?;
2003 FakeCloud::parse(resp).await
2004 }
2005
2006 pub async fn get_target_groups(&self) -> Result<Elbv2TargetGroupsResponse, Error> {
2009 let resp = self
2010 .fc
2011 .client
2012 .get(format!(
2013 "{}/_fakecloud/elbv2/target-groups",
2014 self.fc.base_url
2015 ))
2016 .send()
2017 .await?;
2018 FakeCloud::parse(resp).await
2019 }
2020
2021 pub async fn flush_access_logs(&self) -> Result<Elbv2AccessLogsFlushResponse, Error> {
2024 let resp = self
2025 .fc
2026 .client
2027 .post(format!(
2028 "{}/_fakecloud/elbv2/access-logs/flush",
2029 self.fc.base_url
2030 ))
2031 .send()
2032 .await?;
2033 FakeCloud::parse(resp).await
2034 }
2035}
2036
2037pub struct GlueClient<'a> {
2040 fc: &'a FakeCloud,
2041}
2042
2043impl GlueClient<'_> {
2044 pub async fn get_jobs(&self) -> Result<GlueJobsResponse, Error> {
2046 let resp = self
2047 .fc
2048 .client
2049 .get(format!("{}/_fakecloud/glue/jobs", self.fc.base_url))
2050 .send()
2051 .await?;
2052 FakeCloud::parse(resp).await
2053 }
2054
2055 pub async fn get_job_runs(&self, job_name: Option<&str>) -> Result<GlueJobRunsResponse, Error> {
2058 fn encode(s: &str) -> String {
2059 let mut out = String::with_capacity(s.len());
2060 for b in s.bytes() {
2061 match b {
2062 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
2063 out.push(b as char);
2064 }
2065 _ => out.push_str(&format!("%{:02X}", b)),
2066 }
2067 }
2068 out
2069 }
2070 let mut url = format!("{}/_fakecloud/glue/job-runs", self.fc.base_url);
2071 if let Some(name) = job_name {
2072 url.push_str("?job_name=");
2073 url.push_str(&encode(name));
2074 }
2075 let resp = self.fc.client.get(url).send().await?;
2076 FakeCloud::parse(resp).await
2077 }
2078
2079 pub async fn get_crawlers(&self) -> Result<GlueCrawlersResponse, Error> {
2081 let resp = self
2082 .fc
2083 .client
2084 .get(format!("{}/_fakecloud/glue/crawlers", self.fc.base_url))
2085 .send()
2086 .await?;
2087 FakeCloud::parse(resp).await
2088 }
2089}
2090
2091pub struct CloudWatchClient<'a> {
2094 fc: &'a FakeCloud,
2095}
2096
2097impl CloudWatchClient<'_> {
2098 pub async fn get_alarms(&self) -> Result<CloudWatchAlarmsResponse, Error> {
2101 let resp = self
2102 .fc
2103 .client
2104 .get(format!("{}/_fakecloud/cloudwatch/alarms", self.fc.base_url))
2105 .send()
2106 .await?;
2107 FakeCloud::parse(resp).await
2108 }
2109
2110 pub async fn get_metrics(&self) -> Result<CloudWatchMetricsResponse, Error> {
2113 let resp = self
2114 .fc
2115 .client
2116 .get(format!(
2117 "{}/_fakecloud/cloudwatch/metrics",
2118 self.fc.base_url
2119 ))
2120 .send()
2121 .await?;
2122 FakeCloud::parse(resp).await
2123 }
2124}
2125
2126pub struct FirehoseClient<'a> {
2129 fc: &'a FakeCloud,
2130}
2131
2132impl FirehoseClient<'_> {
2133 pub async fn get_delivery_streams(&self) -> Result<FirehoseDeliveryStreamsResponse, Error> {
2137 let resp = self
2138 .fc
2139 .client
2140 .get(format!(
2141 "{}/_fakecloud/firehose/delivery-streams",
2142 self.fc.base_url
2143 ))
2144 .send()
2145 .await?;
2146 FakeCloud::parse(resp).await
2147 }
2148}
2149
2150pub struct LogsClient<'a> {
2153 fc: &'a FakeCloud,
2154}
2155
2156impl LogsClient<'_> {
2157 pub async fn inject_anomaly(
2161 &self,
2162 req: &LogsAnomalyInjectRequest,
2163 ) -> Result<LogsAnomalyInjectResponse, Error> {
2164 let resp = self
2165 .fc
2166 .client
2167 .post(format!(
2168 "{}/_fakecloud/logs/anomalies/inject",
2169 self.fc.base_url
2170 ))
2171 .json(req)
2172 .send()
2173 .await?;
2174 FakeCloud::parse(resp).await
2175 }
2176
2177 pub async fn get_delivery_config(&self) -> Result<LogsDeliveryConfigResponse, Error> {
2181 let resp = self
2182 .fc
2183 .client
2184 .get(format!(
2185 "{}/_fakecloud/logs/delivery-config",
2186 self.fc.base_url
2187 ))
2188 .send()
2189 .await?;
2190 FakeCloud::parse(resp).await
2191 }
2192
2193 pub async fn get_field_indexes(
2197 &self,
2198 log_group_name: &str,
2199 ) -> Result<LogsFieldIndexesResponse, Error> {
2200 let resp = self
2201 .fc
2202 .client
2203 .get(format!(
2204 "{}/_fakecloud/logs/field-indexes/{}",
2205 self.fc.base_url,
2206 utf8_percent_encode(log_group_name, NON_ALPHANUMERIC)
2207 ))
2208 .send()
2209 .await?;
2210 FakeCloud::parse(resp).await
2211 }
2212}
2213
2214impl Route53Client<'_> {
2215 pub async fn set_health_check_status(
2220 &self,
2221 id: &str,
2222 req: &Route53HealthCheckStatusRequest,
2223 ) -> Result<(), Error> {
2224 let resp = self
2225 .fc
2226 .client
2227 .post(format!(
2228 "{}/_fakecloud/route53/health-checks/{}/status",
2229 self.fc.base_url, id
2230 ))
2231 .json(req)
2232 .send()
2233 .await?;
2234 if !resp.status().is_success() {
2235 let status = resp.status().as_u16();
2236 let body = resp.text().await.unwrap_or_default();
2237 return Err(Error::Api { status, body });
2238 }
2239 Ok(())
2240 }
2241}
2242
2243pub struct SchedulerClient<'a> {
2246 fc: &'a FakeCloud,
2247}
2248
2249impl SchedulerClient<'_> {
2250 pub async fn get_schedules(&self) -> Result<SchedulerSchedulesResponse, Error> {
2253 let resp = self
2254 .fc
2255 .client
2256 .get(format!(
2257 "{}/_fakecloud/scheduler/schedules",
2258 self.fc.base_url
2259 ))
2260 .send()
2261 .await?;
2262 FakeCloud::parse(resp).await
2263 }
2264
2265 pub async fn fire_schedule(
2269 &self,
2270 group: &str,
2271 name: &str,
2272 ) -> Result<FireScheduleResponse, Error> {
2273 let resp = self
2274 .fc
2275 .client
2276 .post(format!(
2277 "{}/_fakecloud/scheduler/fire/{}/{}",
2278 self.fc.base_url, group, name
2279 ))
2280 .send()
2281 .await?;
2282 FakeCloud::parse(resp).await
2283 }
2284}
2285
2286pub struct SsmClient<'a> {
2289 fc: &'a FakeCloud,
2290}
2291
2292impl SsmClient<'_> {
2293 pub async fn set_command_status(
2296 &self,
2297 command_id: &str,
2298 req: &SetSsmCommandStatusRequest,
2299 ) -> Result<SetSsmCommandStatusResponse, Error> {
2300 let resp = self
2301 .fc
2302 .client
2303 .post(format!(
2304 "{}/_fakecloud/ssm/commands/{}/status",
2305 self.fc.base_url, command_id
2306 ))
2307 .json(req)
2308 .send()
2309 .await?;
2310 FakeCloud::parse(resp).await
2311 }
2312
2313 pub async fn fail_command(
2317 &self,
2318 command_id: &str,
2319 req: Option<&FailSsmCommandRequest>,
2320 ) -> Result<FailSsmCommandResponse, Error> {
2321 let mut builder = self.fc.client.post(format!(
2322 "{}/_fakecloud/ssm/commands/{}/fail",
2323 self.fc.base_url, command_id
2324 ));
2325 if let Some(body) = req {
2326 builder = builder.json(body);
2327 }
2328 let resp = builder.send().await?;
2329 FakeCloud::parse(resp).await
2330 }
2331
2332 pub async fn parameter_policy_events(
2335 &self,
2336 account_id: Option<&str>,
2337 ) -> Result<SsmParameterPolicyEventsResponse, Error> {
2338 let mut url = format!(
2339 "{}/_fakecloud/ssm/parameter-policy-events",
2340 self.fc.base_url
2341 );
2342 if let Some(id) = account_id {
2343 url.push_str("?accountId=");
2344 url.push_str(id);
2345 }
2346 let resp = self.fc.client.get(url).send().await?;
2347 FakeCloud::parse(resp).await
2348 }
2349
2350 pub async fn inject_session(
2354 &self,
2355 req: &InjectSsmSessionRequest,
2356 ) -> Result<InjectSsmSessionResponse, Error> {
2357 let resp = self
2358 .fc
2359 .client
2360 .post(format!(
2361 "{}/_fakecloud/ssm/sessions/inject",
2362 self.fc.base_url
2363 ))
2364 .json(req)
2365 .send()
2366 .await?;
2367 FakeCloud::parse(resp).await
2368 }
2369}
2370
2371pub struct KmsClient<'a> {
2374 fc: &'a FakeCloud,
2375}
2376
2377impl KmsClient<'_> {
2378 pub async fn usage(&self) -> Result<KmsUsageResponse, Error> {
2380 let resp = self
2381 .fc
2382 .client
2383 .get(format!("{}/_fakecloud/kms/usage", self.fc.base_url))
2384 .send()
2385 .await?;
2386 FakeCloud::parse(resp).await
2387 }
2388}
2389
2390pub struct WafV2Client<'a> {
2393 fc: &'a FakeCloud,
2394}
2395
2396impl WafV2Client<'_> {
2397 pub async fn evaluate(&self, body: &serde_json::Value) -> Result<serde_json::Value, Error> {
2402 let resp = self
2403 .fc
2404 .client
2405 .post(format!("{}/_fakecloud/wafv2/evaluate", self.fc.base_url))
2406 .json(body)
2407 .send()
2408 .await?;
2409 FakeCloud::parse(resp).await
2410 }
2411}
2412
2413pub struct CloudFrontClient<'a> {
2416 fc: &'a FakeCloud,
2417}
2418
2419impl CloudFrontClient<'_> {
2420 pub async fn set_distribution_status(
2424 &self,
2425 distribution_id: &str,
2426 req: &CloudFrontDistributionStatusRequest,
2427 ) -> Result<(), Error> {
2428 let resp = self
2429 .fc
2430 .client
2431 .post(format!(
2432 "{}/_fakecloud/cloudfront/distributions/{}/status",
2433 self.fc.base_url, distribution_id
2434 ))
2435 .json(req)
2436 .send()
2437 .await?;
2438 let status = resp.status().as_u16();
2439 if !resp.status().is_success() {
2440 let body = resp.text().await.unwrap_or_default();
2441 return Err(Error::Api { status, body });
2442 }
2443 Ok(())
2444 }
2445}
2446
2447impl Elbv2Client<'_> {
2448 pub async fn waf_counts(&self) -> Result<Elbv2WafCountsResponse, Error> {
2452 let resp = self
2453 .fc
2454 .client
2455 .get(format!("{}/_fakecloud/elbv2/waf-counts", self.fc.base_url))
2456 .send()
2457 .await?;
2458 FakeCloud::parse(resp).await
2459 }
2460}