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
960pub struct SecretsManagerClient<'a> {
963 fc: &'a FakeCloud,
964}
965
966impl SecretsManagerClient<'_> {
967 pub async fn tick_rotation(&self) -> Result<RotationTickResponse, Error> {
969 let resp = self
970 .fc
971 .client
972 .post(format!(
973 "{}/_fakecloud/secretsmanager/rotation-scheduler/tick",
974 self.fc.base_url
975 ))
976 .send()
977 .await?;
978 FakeCloud::parse(resp).await
979 }
980}
981
982pub struct CognitoClient<'a> {
985 fc: &'a FakeCloud,
986}
987
988impl CognitoClient<'_> {
989 pub async fn get_user_codes(
991 &self,
992 pool_id: &str,
993 username: &str,
994 ) -> Result<UserConfirmationCodes, Error> {
995 let resp = self
996 .fc
997 .client
998 .get(format!(
999 "{}/_fakecloud/cognito/confirmation-codes/{}/{}",
1000 self.fc.base_url, pool_id, username
1001 ))
1002 .send()
1003 .await?;
1004 FakeCloud::parse(resp).await
1005 }
1006
1007 pub async fn get_confirmation_codes(&self) -> Result<ConfirmationCodesResponse, Error> {
1009 let resp = self
1010 .fc
1011 .client
1012 .get(format!(
1013 "{}/_fakecloud/cognito/confirmation-codes",
1014 self.fc.base_url
1015 ))
1016 .send()
1017 .await?;
1018 FakeCloud::parse(resp).await
1019 }
1020
1021 pub async fn confirm_user(
1023 &self,
1024 req: &ConfirmUserRequest,
1025 ) -> Result<ConfirmUserResponse, Error> {
1026 let resp = self
1027 .fc
1028 .client
1029 .post(format!(
1030 "{}/_fakecloud/cognito/confirm-user",
1031 self.fc.base_url
1032 ))
1033 .json(req)
1034 .send()
1035 .await?;
1036 let status = resp.status().as_u16();
1037 let body: ConfirmUserResponse = resp.json().await?;
1038 if status >= 400 {
1039 return Err(Error::Api {
1040 status,
1041 body: body.error.unwrap_or_default(),
1042 });
1043 }
1044 Ok(body)
1045 }
1046
1047 pub async fn get_tokens(&self) -> Result<TokensResponse, Error> {
1049 let resp = self
1050 .fc
1051 .client
1052 .get(format!("{}/_fakecloud/cognito/tokens", self.fc.base_url))
1053 .send()
1054 .await?;
1055 FakeCloud::parse(resp).await
1056 }
1057
1058 pub async fn expire_tokens(
1060 &self,
1061 req: &ExpireTokensRequest,
1062 ) -> Result<ExpireTokensResponse, Error> {
1063 let resp = self
1064 .fc
1065 .client
1066 .post(format!(
1067 "{}/_fakecloud/cognito/expire-tokens",
1068 self.fc.base_url
1069 ))
1070 .json(req)
1071 .send()
1072 .await?;
1073 FakeCloud::parse(resp).await
1074 }
1075
1076 pub async fn get_auth_events(&self) -> Result<AuthEventsResponse, Error> {
1078 let resp = self
1079 .fc
1080 .client
1081 .get(format!(
1082 "{}/_fakecloud/cognito/auth-events",
1083 self.fc.base_url
1084 ))
1085 .send()
1086 .await?;
1087 FakeCloud::parse(resp).await
1088 }
1089
1090 pub async fn get_pre_token_gen_invocations(
1096 &self,
1097 ) -> Result<PreTokenGenInvocationsResponse, Error> {
1098 let resp = self
1099 .fc
1100 .client
1101 .get(format!(
1102 "{}/_fakecloud/cognito/pretokengen/invocations",
1103 self.fc.base_url
1104 ))
1105 .send()
1106 .await?;
1107 FakeCloud::parse(resp).await
1108 }
1109
1110 pub async fn mint_authorization_code(
1114 &self,
1115 req: &MintAuthorizationCodeRequest,
1116 ) -> Result<MintAuthorizationCodeResponse, Error> {
1117 let resp = self
1118 .fc
1119 .client
1120 .post(format!(
1121 "{}/_fakecloud/cognito/authorization-codes",
1122 self.fc.base_url
1123 ))
1124 .json(req)
1125 .send()
1126 .await?;
1127 FakeCloud::parse(resp).await
1128 }
1129
1130 pub async fn set_compromised_passwords(
1135 &self,
1136 req: &CognitoCompromisedPasswordsRequest,
1137 ) -> Result<CompromisedPasswordsResponse, Error> {
1138 let resp = self
1139 .fc
1140 .client
1141 .post(format!(
1142 "{}/_fakecloud/cognito/compromised-passwords",
1143 self.fc.base_url
1144 ))
1145 .json(req)
1146 .send()
1147 .await?;
1148 FakeCloud::parse(resp).await
1149 }
1150
1151 pub async fn get_webauthn_credentials(&self) -> Result<WebAuthnCredentialsResponse, Error> {
1153 let resp = self
1154 .fc
1155 .client
1156 .get(format!(
1157 "{}/_fakecloud/cognito/webauthn-credentials",
1158 self.fc.base_url
1159 ))
1160 .send()
1161 .await?;
1162 FakeCloud::parse(resp).await
1163 }
1164}
1165
1166pub struct ApiGatewayV2Client<'a> {
1169 fc: &'a FakeCloud,
1170}
1171
1172impl ApiGatewayV2Client<'_> {
1173 pub async fn get_requests(&self) -> Result<ApiGatewayV2RequestsResponse, Error> {
1175 let resp = self
1176 .fc
1177 .client
1178 .get(format!(
1179 "{}/_fakecloud/apigatewayv2/requests",
1180 self.fc.base_url
1181 ))
1182 .send()
1183 .await?;
1184 FakeCloud::parse(resp).await
1185 }
1186
1187 pub async fn connections(&self) -> Result<ApiGatewayV2ConnectionsResponse, Error> {
1190 let resp = self
1191 .fc
1192 .client
1193 .get(format!(
1194 "{}/_fakecloud/apigatewayv2/connections",
1195 self.fc.base_url
1196 ))
1197 .send()
1198 .await?;
1199 FakeCloud::parse(resp).await
1200 }
1201
1202 pub async fn mtls_info(&self, name: &str) -> Result<serde_json::Value, Error> {
1206 let resp = self
1207 .fc
1208 .client
1209 .get(format!(
1210 "{}/_fakecloud/apigatewayv2/domain-names/{}/mtls-info",
1211 self.fc.base_url, name
1212 ))
1213 .send()
1214 .await?;
1215 FakeCloud::parse(resp).await
1216 }
1217
1218 pub fn ws_url(&self, api_id: &str, stage: Option<&str>) -> String {
1222 let base = self
1223 .fc
1224 .base_url
1225 .replacen("https://", "wss://", 1)
1226 .replacen("http://", "ws://", 1);
1227 let url = reqwest::Url::parse(&format!("{}/_fakecloud/apigatewayv2/ws/{}", base, api_id))
1231 .expect("base url + api id form a valid URL");
1232 match stage {
1233 Some(s) => {
1234 let mut u = url;
1235 u.query_pairs_mut().append_pair("stage", s);
1236 u.to_string()
1237 }
1238 None => url.to_string(),
1239 }
1240 }
1241}
1242
1243pub struct StepFunctionsClient<'a> {
1246 fc: &'a FakeCloud,
1247}
1248
1249impl StepFunctionsClient<'_> {
1250 pub async fn get_executions(&self) -> Result<StepFunctionsExecutionsResponse, Error> {
1252 let resp = self
1253 .fc
1254 .client
1255 .get(format!(
1256 "{}/_fakecloud/stepfunctions/executions",
1257 self.fc.base_url
1258 ))
1259 .send()
1260 .await?;
1261 FakeCloud::parse(resp).await
1262 }
1263
1264 pub async fn get_sync_executions(&self) -> Result<StepFunctionsSyncExecutionsResponse, Error> {
1268 let resp = self
1269 .fc
1270 .client
1271 .get(format!(
1272 "{}/_fakecloud/stepfunctions/sync-executions",
1273 self.fc.base_url
1274 ))
1275 .send()
1276 .await?;
1277 FakeCloud::parse(resp).await
1278 }
1279
1280 pub async fn enqueue_activity_task(
1288 &self,
1289 req: &SfnEnqueueActivityTaskRequest,
1290 ) -> Result<SfnEnqueueActivityTaskResponse, Error> {
1291 let resp = self
1292 .fc
1293 .client
1294 .post(format!(
1295 "{}/_fakecloud/stepfunctions/enqueue-activity-task",
1296 self.fc.base_url
1297 ))
1298 .json(req)
1299 .send()
1300 .await?;
1301 FakeCloud::parse(resp).await
1302 }
1303
1304 pub async fn get_execution_tree(
1305 &self,
1306 execution_arn: &str,
1307 ) -> Result<StepFunctionsExecutionTreeResponse, Error> {
1308 let mut encoded = String::with_capacity(execution_arn.len());
1309 for b in execution_arn.bytes() {
1310 match b {
1311 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1312 encoded.push(b as char);
1313 }
1314 _ => encoded.push_str(&format!("%{:02X}", b)),
1315 }
1316 }
1317 let resp = self
1318 .fc
1319 .client
1320 .get(format!(
1321 "{}/_fakecloud/stepfunctions/execution-tree/{}",
1322 self.fc.base_url, encoded
1323 ))
1324 .send()
1325 .await?;
1326 FakeCloud::parse(resp).await
1327 }
1328}
1329
1330pub struct BedrockClient<'a> {
1333 fc: &'a FakeCloud,
1334}
1335
1336impl BedrockClient<'_> {
1337 pub async fn get_invocations(&self) -> Result<BedrockInvocationsResponse, Error> {
1340 let resp = self
1341 .fc
1342 .client
1343 .get(format!(
1344 "{}/_fakecloud/bedrock/invocations",
1345 self.fc.base_url
1346 ))
1347 .send()
1348 .await?;
1349 FakeCloud::parse(resp).await
1350 }
1351
1352 pub async fn set_model_response(
1354 &self,
1355 model_id: &str,
1356 response: &str,
1357 ) -> Result<BedrockModelResponseConfig, Error> {
1358 let resp = self
1359 .fc
1360 .client
1361 .post(format!(
1362 "{}/_fakecloud/bedrock/models/{}/response",
1363 self.fc.base_url, model_id
1364 ))
1365 .header("content-type", "text/plain")
1366 .body(response.to_string())
1367 .send()
1368 .await?;
1369 FakeCloud::parse(resp).await
1370 }
1371
1372 pub async fn set_response_rules(
1374 &self,
1375 model_id: &str,
1376 rules: &[BedrockResponseRule],
1377 ) -> Result<BedrockModelResponseConfig, Error> {
1378 let body = serde_json::json!({ "rules": rules });
1379 let resp = self
1380 .fc
1381 .client
1382 .post(format!(
1383 "{}/_fakecloud/bedrock/models/{}/responses",
1384 self.fc.base_url, model_id
1385 ))
1386 .json(&body)
1387 .send()
1388 .await?;
1389 FakeCloud::parse(resp).await
1390 }
1391
1392 pub async fn clear_response_rules(
1394 &self,
1395 model_id: &str,
1396 ) -> Result<BedrockModelResponseConfig, Error> {
1397 let resp = self
1398 .fc
1399 .client
1400 .delete(format!(
1401 "{}/_fakecloud/bedrock/models/{}/responses",
1402 self.fc.base_url, model_id
1403 ))
1404 .send()
1405 .await?;
1406 FakeCloud::parse(resp).await
1407 }
1408
1409 pub async fn queue_fault(
1411 &self,
1412 rule: &BedrockFaultRule,
1413 ) -> Result<BedrockStatusResponse, Error> {
1414 let resp = self
1415 .fc
1416 .client
1417 .post(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1418 .json(rule)
1419 .send()
1420 .await?;
1421 FakeCloud::parse(resp).await
1422 }
1423
1424 pub async fn get_faults(&self) -> Result<BedrockFaultsResponse, Error> {
1426 let resp = self
1427 .fc
1428 .client
1429 .get(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1430 .send()
1431 .await?;
1432 FakeCloud::parse(resp).await
1433 }
1434
1435 pub async fn clear_faults(&self) -> Result<BedrockStatusResponse, Error> {
1437 let resp = self
1438 .fc
1439 .client
1440 .delete(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1441 .send()
1442 .await?;
1443 FakeCloud::parse(resp).await
1444 }
1445}
1446
1447pub struct BedrockAgentClient<'a> {
1450 fc: &'a FakeCloud,
1451}
1452
1453impl BedrockAgentClient<'_> {
1454 pub async fn get_agents(&self) -> Result<BedrockAgentAgentsResponse, Error> {
1458 let resp = self
1459 .fc
1460 .client
1461 .get(format!(
1462 "{}/_fakecloud/bedrock-agent/agents",
1463 self.fc.base_url
1464 ))
1465 .send()
1466 .await?;
1467 FakeCloud::parse(resp).await
1468 }
1469}
1470
1471pub struct BedrockAgentRuntimeClient<'a> {
1474 fc: &'a FakeCloud,
1475}
1476
1477impl BedrockAgentRuntimeClient<'_> {
1478 pub async fn get_invocations(&self) -> Result<BedrockAgentRuntimeInvocationsResponse, Error> {
1481 let resp = self
1482 .fc
1483 .client
1484 .get(format!(
1485 "{}/_fakecloud/bedrock-agent-runtime/invocations",
1486 self.fc.base_url
1487 ))
1488 .send()
1489 .await?;
1490 FakeCloud::parse(resp).await
1491 }
1492}
1493
1494pub struct EcsClient<'a> {
1497 fc: &'a FakeCloud,
1498}
1499
1500impl EcsClient<'_> {
1501 pub async fn get_clusters(&self) -> Result<EcsClustersResponse, Error> {
1505 let resp = self
1506 .fc
1507 .client
1508 .get(format!("{}/_fakecloud/ecs/clusters", self.fc.base_url))
1509 .send()
1510 .await?;
1511 FakeCloud::parse(resp).await
1512 }
1513
1514 pub async fn get_tasks(
1517 &self,
1518 cluster: Option<&str>,
1519 status: Option<&str>,
1520 ) -> Result<EcsTasksResponse, Error> {
1521 fn encode(s: &str) -> String {
1522 let mut out = String::with_capacity(s.len());
1523 for b in s.bytes() {
1524 match b {
1525 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1526 out.push(b as char);
1527 }
1528 _ => out.push_str(&format!("%{:02X}", b)),
1529 }
1530 }
1531 out
1532 }
1533 let mut url = format!("{}/_fakecloud/ecs/tasks", self.fc.base_url);
1534 let mut sep = '?';
1535 if let Some(c) = cluster {
1536 url.push(sep);
1537 url.push_str("cluster=");
1538 url.push_str(&encode(c));
1539 sep = '&';
1540 }
1541 if let Some(s) = status {
1542 url.push(sep);
1543 url.push_str("status=");
1544 url.push_str(&encode(s));
1545 }
1546 let resp = self.fc.client.get(url).send().await?;
1547 FakeCloud::parse(resp).await
1548 }
1549
1550 pub async fn get_task_logs(&self, task_id: &str) -> Result<EcsTaskLogsResponse, Error> {
1554 let resp = self
1555 .fc
1556 .client
1557 .get(format!(
1558 "{}/_fakecloud/ecs/tasks/{}/logs",
1559 self.fc.base_url, task_id
1560 ))
1561 .send()
1562 .await?;
1563 FakeCloud::parse(resp).await
1564 }
1565
1566 pub async fn force_stop_task(&self, task_id: &str) -> Result<EcsTask, Error> {
1568 let resp = self
1569 .fc
1570 .client
1571 .post(format!(
1572 "{}/_fakecloud/ecs/tasks/{}/force-stop",
1573 self.fc.base_url, task_id
1574 ))
1575 .send()
1576 .await?;
1577 FakeCloud::parse(resp).await
1578 }
1579
1580 pub async fn mark_task_failed(
1583 &self,
1584 task_id: &str,
1585 req: &EcsMarkFailedRequest,
1586 ) -> Result<EcsTask, Error> {
1587 let resp = self
1588 .fc
1589 .client
1590 .post(format!(
1591 "{}/_fakecloud/ecs/tasks/{}/mark-failed",
1592 self.fc.base_url, task_id
1593 ))
1594 .json(req)
1595 .send()
1596 .await?;
1597 FakeCloud::parse(resp).await
1598 }
1599
1600 pub async fn get_events(&self) -> Result<EcsEventsResponse, Error> {
1602 let resp = self
1603 .fc
1604 .client
1605 .get(format!("{}/_fakecloud/ecs/events", self.fc.base_url))
1606 .send()
1607 .await?;
1608 FakeCloud::parse(resp).await
1609 }
1610
1611 pub async fn get_metadata_by_arn(&self, task_arn: &str) -> Result<serde_json::Value, Error> {
1618 let mut encoded = String::with_capacity(task_arn.len());
1619 for b in task_arn.bytes() {
1620 match b {
1621 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1622 encoded.push(b as char);
1623 }
1624 _ => encoded.push_str(&format!("%{:02X}", b)),
1625 }
1626 }
1627 let resp = self
1628 .fc
1629 .client
1630 .get(format!(
1631 "{}/_fakecloud/ecs/metadata/{}",
1632 self.fc.base_url, encoded
1633 ))
1634 .send()
1635 .await?;
1636 FakeCloud::parse(resp).await
1637 }
1638
1639 pub async fn task_credentials(
1644 &self,
1645 task_id: &str,
1646 ) -> Result<EcsTaskCredentialsResponse, Error> {
1647 let resp = self
1648 .fc
1649 .client
1650 .get(format!(
1651 "{}/_fakecloud/ecs/creds/{}",
1652 self.fc.base_url, task_id
1653 ))
1654 .send()
1655 .await?;
1656 FakeCloud::parse(resp).await
1657 }
1658
1659 pub async fn task_metadata_v3(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1665 let resp = self
1666 .fc
1667 .client
1668 .get(format!(
1669 "{}/_fakecloud/ecs/v3/{}",
1670 self.fc.base_url, task_id
1671 ))
1672 .send()
1673 .await?;
1674 FakeCloud::parse(resp).await
1675 }
1676
1677 pub async fn task_metadata_v4(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1681 let resp = self
1682 .fc
1683 .client
1684 .get(format!(
1685 "{}/_fakecloud/ecs/v4/{}",
1686 self.fc.base_url, task_id
1687 ))
1688 .send()
1689 .await?;
1690 FakeCloud::parse(resp).await
1691 }
1692}
1693
1694pub struct Route53Client<'a> {
1697 fc: &'a FakeCloud,
1698}
1699
1700impl Route53Client<'_> {
1701 pub async fn dnssec_material(
1705 &self,
1706 zone_id: &str,
1707 ) -> Result<Route53DnssecMaterialResponse, Error> {
1708 let resp = self
1709 .fc
1710 .client
1711 .get(format!(
1712 "{}/_fakecloud/route53/zones/{}/dnssec",
1713 self.fc.base_url, zone_id
1714 ))
1715 .send()
1716 .await?;
1717 FakeCloud::parse(resp).await
1718 }
1719
1720 pub async fn dnssec_sign(
1724 &self,
1725 zone_id: &str,
1726 req: &Route53DnssecSignRequest,
1727 ) -> Result<Route53DnssecSignResponse, Error> {
1728 let resp = self
1729 .fc
1730 .client
1731 .post(format!(
1732 "{}/_fakecloud/route53/zones/{}/dnssec/sign",
1733 self.fc.base_url, zone_id
1734 ))
1735 .json(req)
1736 .send()
1737 .await?;
1738 FakeCloud::parse(resp).await
1739 }
1740}
1741
1742pub struct AthenaClient<'a> {
1745 fc: &'a FakeCloud,
1746}
1747
1748impl AthenaClient<'_> {
1749 pub async fn get_named_queries(&self) -> Result<AthenaNamedQueriesResponse, Error> {
1754 let resp = self
1755 .fc
1756 .client
1757 .get(format!(
1758 "{}/_fakecloud/athena/named-queries",
1759 self.fc.base_url
1760 ))
1761 .send()
1762 .await?;
1763 FakeCloud::parse(resp).await
1764 }
1765}
1766
1767pub struct OrganizationsClient<'a> {
1770 fc: &'a FakeCloud,
1771}
1772
1773impl OrganizationsClient<'_> {
1774 pub async fn get_accounts(&self) -> Result<OrganizationsAccountsResponse, Error> {
1779 let resp = self
1780 .fc
1781 .client
1782 .get(format!(
1783 "{}/_fakecloud/organizations/accounts",
1784 self.fc.base_url
1785 ))
1786 .send()
1787 .await?;
1788 FakeCloud::parse(resp).await
1789 }
1790
1791 pub async fn get_responsibility_transfers(
1795 &self,
1796 ) -> Result<OrganizationsResponsibilityTransfersResponse, Error> {
1797 let resp = self
1798 .fc
1799 .client
1800 .get(format!(
1801 "{}/_fakecloud/organizations/responsibility-transfers",
1802 self.fc.base_url
1803 ))
1804 .send()
1805 .await?;
1806 FakeCloud::parse(resp).await
1807 }
1808}
1809
1810pub struct AcmClient<'a> {
1813 fc: &'a FakeCloud,
1814}
1815
1816impl AcmClient<'_> {
1817 fn certificate_id(arn_or_id: &str) -> String {
1818 match arn_or_id.rfind("certificate/") {
1819 Some(idx) => arn_or_id[idx + "certificate/".len()..].to_string(),
1820 None => arn_or_id.to_string(),
1821 }
1822 }
1823
1824 pub async fn set_certificate_status(
1829 &self,
1830 arn_or_id: &str,
1831 req: &AcmCertificateStatusRequest,
1832 ) -> Result<(), Error> {
1833 let id = Self::certificate_id(arn_or_id);
1834 let resp = self
1835 .fc
1836 .client
1837 .post(format!(
1838 "{}/_fakecloud/acm/certificates/{}/status",
1839 self.fc.base_url, id
1840 ))
1841 .json(req)
1842 .send()
1843 .await?;
1844 if !resp.status().is_success() {
1845 let status = resp.status().as_u16();
1846 let body = resp.text().await.unwrap_or_default();
1847 return Err(Error::Api { status, body });
1848 }
1849 Ok(())
1850 }
1851
1852 pub async fn get_certificate_chain_info(
1856 &self,
1857 arn_or_id: &str,
1858 ) -> Result<AcmCertificateChainInfo, Error> {
1859 let id = Self::certificate_id(arn_or_id);
1860 let resp = self
1861 .fc
1862 .client
1863 .get(format!(
1864 "{}/_fakecloud/acm/certificates/{}/chain-info",
1865 self.fc.base_url, id
1866 ))
1867 .send()
1868 .await?;
1869 FakeCloud::parse(resp).await
1870 }
1871
1872 pub async fn approve_certificate(&self, arn_or_id: &str) -> Result<(), Error> {
1876 let id = Self::certificate_id(arn_or_id);
1877 let resp = self
1878 .fc
1879 .client
1880 .post(format!(
1881 "{}/_fakecloud/acm/certificates/{}/approve",
1882 self.fc.base_url, id
1883 ))
1884 .send()
1885 .await?;
1886 if !resp.status().is_success() {
1887 let status = resp.status().as_u16();
1888 let body = resp.text().await.unwrap_or_default();
1889 return Err(Error::Api { status, body });
1890 }
1891 Ok(())
1892 }
1893}
1894
1895pub struct EcrClient<'a> {
1898 fc: &'a FakeCloud,
1899}
1900
1901impl EcrClient<'_> {
1902 pub async fn get_images(&self) -> Result<EcrImagesResponse, Error> {
1904 let resp = self
1905 .fc
1906 .client
1907 .get(format!("{}/_fakecloud/ecr/images", self.fc.base_url))
1908 .send()
1909 .await?;
1910 FakeCloud::parse(resp).await
1911 }
1912
1913 pub async fn get_repositories(&self) -> Result<EcrRepositoriesResponse, Error> {
1915 let resp = self
1916 .fc
1917 .client
1918 .get(format!("{}/_fakecloud/ecr/repositories", self.fc.base_url))
1919 .send()
1920 .await?;
1921 FakeCloud::parse(resp).await
1922 }
1923
1924 pub async fn get_pull_through_rules(&self) -> Result<EcrPullThroughRulesResponse, Error> {
1926 let resp = self
1927 .fc
1928 .client
1929 .get(format!(
1930 "{}/_fakecloud/ecr/pull-through-rules",
1931 self.fc.base_url
1932 ))
1933 .send()
1934 .await?;
1935 FakeCloud::parse(resp).await
1936 }
1937}
1938
1939pub struct Elbv2Client<'a> {
1942 fc: &'a FakeCloud,
1943}
1944
1945impl Elbv2Client<'_> {
1946 pub async fn get_load_balancers(&self) -> Result<Elbv2LoadBalancersResponse, Error> {
1948 let resp = self
1949 .fc
1950 .client
1951 .get(format!(
1952 "{}/_fakecloud/elbv2/load-balancers",
1953 self.fc.base_url
1954 ))
1955 .send()
1956 .await?;
1957 FakeCloud::parse(resp).await
1958 }
1959
1960 pub async fn get_listeners(&self) -> Result<Elbv2ListenersResponse, Error> {
1962 let resp = self
1963 .fc
1964 .client
1965 .get(format!("{}/_fakecloud/elbv2/listeners", self.fc.base_url))
1966 .send()
1967 .await?;
1968 FakeCloud::parse(resp).await
1969 }
1970
1971 pub async fn get_rules(&self) -> Result<Elbv2RulesResponse, Error> {
1973 let resp = self
1974 .fc
1975 .client
1976 .get(format!("{}/_fakecloud/elbv2/rules", self.fc.base_url))
1977 .send()
1978 .await?;
1979 FakeCloud::parse(resp).await
1980 }
1981
1982 pub async fn get_target_groups(&self) -> Result<Elbv2TargetGroupsResponse, Error> {
1985 let resp = self
1986 .fc
1987 .client
1988 .get(format!(
1989 "{}/_fakecloud/elbv2/target-groups",
1990 self.fc.base_url
1991 ))
1992 .send()
1993 .await?;
1994 FakeCloud::parse(resp).await
1995 }
1996
1997 pub async fn flush_access_logs(&self) -> Result<Elbv2AccessLogsFlushResponse, Error> {
2000 let resp = self
2001 .fc
2002 .client
2003 .post(format!(
2004 "{}/_fakecloud/elbv2/access-logs/flush",
2005 self.fc.base_url
2006 ))
2007 .send()
2008 .await?;
2009 FakeCloud::parse(resp).await
2010 }
2011}
2012
2013pub struct GlueClient<'a> {
2016 fc: &'a FakeCloud,
2017}
2018
2019impl GlueClient<'_> {
2020 pub async fn get_jobs(&self) -> Result<GlueJobsResponse, Error> {
2022 let resp = self
2023 .fc
2024 .client
2025 .get(format!("{}/_fakecloud/glue/jobs", self.fc.base_url))
2026 .send()
2027 .await?;
2028 FakeCloud::parse(resp).await
2029 }
2030
2031 pub async fn get_job_runs(&self, job_name: Option<&str>) -> Result<GlueJobRunsResponse, Error> {
2034 fn encode(s: &str) -> String {
2035 let mut out = String::with_capacity(s.len());
2036 for b in s.bytes() {
2037 match b {
2038 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
2039 out.push(b as char);
2040 }
2041 _ => out.push_str(&format!("%{:02X}", b)),
2042 }
2043 }
2044 out
2045 }
2046 let mut url = format!("{}/_fakecloud/glue/job-runs", self.fc.base_url);
2047 if let Some(name) = job_name {
2048 url.push_str("?job_name=");
2049 url.push_str(&encode(name));
2050 }
2051 let resp = self.fc.client.get(url).send().await?;
2052 FakeCloud::parse(resp).await
2053 }
2054
2055 pub async fn get_crawlers(&self) -> Result<GlueCrawlersResponse, Error> {
2057 let resp = self
2058 .fc
2059 .client
2060 .get(format!("{}/_fakecloud/glue/crawlers", self.fc.base_url))
2061 .send()
2062 .await?;
2063 FakeCloud::parse(resp).await
2064 }
2065}
2066
2067pub struct CloudWatchClient<'a> {
2070 fc: &'a FakeCloud,
2071}
2072
2073impl CloudWatchClient<'_> {
2074 pub async fn get_alarms(&self) -> Result<CloudWatchAlarmsResponse, Error> {
2077 let resp = self
2078 .fc
2079 .client
2080 .get(format!("{}/_fakecloud/cloudwatch/alarms", self.fc.base_url))
2081 .send()
2082 .await?;
2083 FakeCloud::parse(resp).await
2084 }
2085
2086 pub async fn get_metrics(&self) -> Result<CloudWatchMetricsResponse, Error> {
2089 let resp = self
2090 .fc
2091 .client
2092 .get(format!(
2093 "{}/_fakecloud/cloudwatch/metrics",
2094 self.fc.base_url
2095 ))
2096 .send()
2097 .await?;
2098 FakeCloud::parse(resp).await
2099 }
2100}
2101
2102pub struct FirehoseClient<'a> {
2105 fc: &'a FakeCloud,
2106}
2107
2108impl FirehoseClient<'_> {
2109 pub async fn get_delivery_streams(&self) -> Result<FirehoseDeliveryStreamsResponse, Error> {
2113 let resp = self
2114 .fc
2115 .client
2116 .get(format!(
2117 "{}/_fakecloud/firehose/delivery-streams",
2118 self.fc.base_url
2119 ))
2120 .send()
2121 .await?;
2122 FakeCloud::parse(resp).await
2123 }
2124}
2125
2126pub struct LogsClient<'a> {
2129 fc: &'a FakeCloud,
2130}
2131
2132impl LogsClient<'_> {
2133 pub async fn inject_anomaly(
2137 &self,
2138 req: &LogsAnomalyInjectRequest,
2139 ) -> Result<LogsAnomalyInjectResponse, Error> {
2140 let resp = self
2141 .fc
2142 .client
2143 .post(format!(
2144 "{}/_fakecloud/logs/anomalies/inject",
2145 self.fc.base_url
2146 ))
2147 .json(req)
2148 .send()
2149 .await?;
2150 FakeCloud::parse(resp).await
2151 }
2152
2153 pub async fn get_delivery_config(&self) -> Result<LogsDeliveryConfigResponse, Error> {
2157 let resp = self
2158 .fc
2159 .client
2160 .get(format!(
2161 "{}/_fakecloud/logs/delivery-config",
2162 self.fc.base_url
2163 ))
2164 .send()
2165 .await?;
2166 FakeCloud::parse(resp).await
2167 }
2168
2169 pub async fn get_field_indexes(
2173 &self,
2174 log_group_name: &str,
2175 ) -> Result<LogsFieldIndexesResponse, Error> {
2176 let resp = self
2177 .fc
2178 .client
2179 .get(format!(
2180 "{}/_fakecloud/logs/field-indexes/{}",
2181 self.fc.base_url,
2182 utf8_percent_encode(log_group_name, NON_ALPHANUMERIC)
2183 ))
2184 .send()
2185 .await?;
2186 FakeCloud::parse(resp).await
2187 }
2188}
2189
2190impl Route53Client<'_> {
2191 pub async fn set_health_check_status(
2196 &self,
2197 id: &str,
2198 req: &Route53HealthCheckStatusRequest,
2199 ) -> Result<(), Error> {
2200 let resp = self
2201 .fc
2202 .client
2203 .post(format!(
2204 "{}/_fakecloud/route53/health-checks/{}/status",
2205 self.fc.base_url, id
2206 ))
2207 .json(req)
2208 .send()
2209 .await?;
2210 if !resp.status().is_success() {
2211 let status = resp.status().as_u16();
2212 let body = resp.text().await.unwrap_or_default();
2213 return Err(Error::Api { status, body });
2214 }
2215 Ok(())
2216 }
2217}
2218
2219pub struct SchedulerClient<'a> {
2222 fc: &'a FakeCloud,
2223}
2224
2225impl SchedulerClient<'_> {
2226 pub async fn get_schedules(&self) -> Result<SchedulerSchedulesResponse, Error> {
2229 let resp = self
2230 .fc
2231 .client
2232 .get(format!(
2233 "{}/_fakecloud/scheduler/schedules",
2234 self.fc.base_url
2235 ))
2236 .send()
2237 .await?;
2238 FakeCloud::parse(resp).await
2239 }
2240
2241 pub async fn fire_schedule(
2245 &self,
2246 group: &str,
2247 name: &str,
2248 ) -> Result<FireScheduleResponse, Error> {
2249 let resp = self
2250 .fc
2251 .client
2252 .post(format!(
2253 "{}/_fakecloud/scheduler/fire/{}/{}",
2254 self.fc.base_url, group, name
2255 ))
2256 .send()
2257 .await?;
2258 FakeCloud::parse(resp).await
2259 }
2260}
2261
2262pub struct SsmClient<'a> {
2265 fc: &'a FakeCloud,
2266}
2267
2268impl SsmClient<'_> {
2269 pub async fn set_command_status(
2272 &self,
2273 command_id: &str,
2274 req: &SetSsmCommandStatusRequest,
2275 ) -> Result<SetSsmCommandStatusResponse, Error> {
2276 let resp = self
2277 .fc
2278 .client
2279 .post(format!(
2280 "{}/_fakecloud/ssm/commands/{}/status",
2281 self.fc.base_url, command_id
2282 ))
2283 .json(req)
2284 .send()
2285 .await?;
2286 FakeCloud::parse(resp).await
2287 }
2288
2289 pub async fn fail_command(
2293 &self,
2294 command_id: &str,
2295 req: Option<&FailSsmCommandRequest>,
2296 ) -> Result<FailSsmCommandResponse, Error> {
2297 let mut builder = self.fc.client.post(format!(
2298 "{}/_fakecloud/ssm/commands/{}/fail",
2299 self.fc.base_url, command_id
2300 ));
2301 if let Some(body) = req {
2302 builder = builder.json(body);
2303 }
2304 let resp = builder.send().await?;
2305 FakeCloud::parse(resp).await
2306 }
2307
2308 pub async fn parameter_policy_events(
2311 &self,
2312 account_id: Option<&str>,
2313 ) -> Result<SsmParameterPolicyEventsResponse, Error> {
2314 let mut url = format!(
2315 "{}/_fakecloud/ssm/parameter-policy-events",
2316 self.fc.base_url
2317 );
2318 if let Some(id) = account_id {
2319 url.push_str("?accountId=");
2320 url.push_str(id);
2321 }
2322 let resp = self.fc.client.get(url).send().await?;
2323 FakeCloud::parse(resp).await
2324 }
2325
2326 pub async fn inject_session(
2330 &self,
2331 req: &InjectSsmSessionRequest,
2332 ) -> Result<InjectSsmSessionResponse, Error> {
2333 let resp = self
2334 .fc
2335 .client
2336 .post(format!(
2337 "{}/_fakecloud/ssm/sessions/inject",
2338 self.fc.base_url
2339 ))
2340 .json(req)
2341 .send()
2342 .await?;
2343 FakeCloud::parse(resp).await
2344 }
2345}
2346
2347pub struct KmsClient<'a> {
2350 fc: &'a FakeCloud,
2351}
2352
2353impl KmsClient<'_> {
2354 pub async fn usage(&self) -> Result<KmsUsageResponse, Error> {
2356 let resp = self
2357 .fc
2358 .client
2359 .get(format!("{}/_fakecloud/kms/usage", self.fc.base_url))
2360 .send()
2361 .await?;
2362 FakeCloud::parse(resp).await
2363 }
2364}
2365
2366pub struct WafV2Client<'a> {
2369 fc: &'a FakeCloud,
2370}
2371
2372impl WafV2Client<'_> {
2373 pub async fn evaluate(&self, body: &serde_json::Value) -> Result<serde_json::Value, Error> {
2378 let resp = self
2379 .fc
2380 .client
2381 .post(format!("{}/_fakecloud/wafv2/evaluate", self.fc.base_url))
2382 .json(body)
2383 .send()
2384 .await?;
2385 FakeCloud::parse(resp).await
2386 }
2387}
2388
2389pub struct CloudFrontClient<'a> {
2392 fc: &'a FakeCloud,
2393}
2394
2395impl CloudFrontClient<'_> {
2396 pub async fn set_distribution_status(
2400 &self,
2401 distribution_id: &str,
2402 req: &CloudFrontDistributionStatusRequest,
2403 ) -> Result<(), Error> {
2404 let resp = self
2405 .fc
2406 .client
2407 .post(format!(
2408 "{}/_fakecloud/cloudfront/distributions/{}/status",
2409 self.fc.base_url, distribution_id
2410 ))
2411 .json(req)
2412 .send()
2413 .await?;
2414 let status = resp.status().as_u16();
2415 if !resp.status().is_success() {
2416 let body = resp.text().await.unwrap_or_default();
2417 return Err(Error::Api { status, body });
2418 }
2419 Ok(())
2420 }
2421}
2422
2423impl Elbv2Client<'_> {
2424 pub async fn waf_counts(&self) -> Result<Elbv2WafCountsResponse, Error> {
2428 let resp = self
2429 .fc
2430 .client
2431 .get(format!("{}/_fakecloud/elbv2/waf-counts", self.fc.base_url))
2432 .send()
2433 .await?;
2434 FakeCloud::parse(resp).await
2435 }
2436}