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
259pub struct RdsClient<'a> {
260 fc: &'a FakeCloud,
261}
262
263impl RdsClient<'_> {
264 pub async fn get_instances(&self) -> Result<RdsInstancesResponse, Error> {
266 let resp = self
267 .fc
268 .client
269 .get(format!("{}/_fakecloud/rds/instances", self.fc.base_url))
270 .send()
271 .await?;
272 FakeCloud::parse(resp).await
273 }
274
275 pub async fn lambda_invoke(
280 &self,
281 req: &RdsLambdaInvokeRequest,
282 ) -> Result<RdsLambdaInvokeResponse, Error> {
283 let resp = self
284 .fc
285 .client
286 .post(format!("{}/_fakecloud/rds/lambda-invoke", self.fc.base_url))
287 .json(req)
288 .send()
289 .await?;
290 let status = resp.status().as_u16();
291 if status == 502 || resp.status().is_success() {
295 return Ok(resp.json::<RdsLambdaInvokeResponse>().await?);
296 }
297 let body = resp.text().await.unwrap_or_default();
298 Err(Error::Api { status, body })
299 }
300
301 pub async fn s3_import(&self, req: &RdsS3ImportRequest) -> Result<RdsS3ImportResponse, Error> {
304 let resp = self
305 .fc
306 .client
307 .post(format!("{}/_fakecloud/rds/s3-import", self.fc.base_url))
308 .json(req)
309 .send()
310 .await?;
311 FakeCloud::parse(resp).await
312 }
313
314 pub async fn s3_export(&self, req: &RdsS3ExportRequest) -> Result<RdsS3ExportResponse, Error> {
317 let resp = self
318 .fc
319 .client
320 .post(format!("{}/_fakecloud/rds/s3-export", self.fc.base_url))
321 .json(req)
322 .send()
323 .await?;
324 FakeCloud::parse(resp).await
325 }
326}
327
328pub struct ElastiCacheClient<'a> {
331 fc: &'a FakeCloud,
332}
333
334impl ElastiCacheClient<'_> {
335 pub async fn get_clusters(&self) -> Result<ElastiCacheClustersResponse, Error> {
337 let resp = self
338 .fc
339 .client
340 .get(format!(
341 "{}/_fakecloud/elasticache/clusters",
342 self.fc.base_url
343 ))
344 .send()
345 .await?;
346 FakeCloud::parse(resp).await
347 }
348
349 pub async fn get_replication_groups(
351 &self,
352 ) -> Result<ElastiCacheReplicationGroupsResponse, Error> {
353 let resp = self
354 .fc
355 .client
356 .get(format!(
357 "{}/_fakecloud/elasticache/replication-groups",
358 self.fc.base_url
359 ))
360 .send()
361 .await?;
362 FakeCloud::parse(resp).await
363 }
364
365 pub async fn get_serverless_caches(
367 &self,
368 ) -> Result<ElastiCacheServerlessCachesResponse, Error> {
369 let resp = self
370 .fc
371 .client
372 .get(format!(
373 "{}/_fakecloud/elasticache/serverless-caches",
374 self.fc.base_url
375 ))
376 .send()
377 .await?;
378 FakeCloud::parse(resp).await
379 }
380
381 pub async fn get_acls(&self) -> Result<ElastiCacheAclsResponse, Error> {
384 let resp = self
385 .fc
386 .client
387 .get(format!("{}/_fakecloud/elasticache/acls", self.fc.base_url))
388 .send()
389 .await?;
390 FakeCloud::parse(resp).await
391 }
392}
393
394pub struct LambdaClient<'a> {
397 fc: &'a FakeCloud,
398}
399
400impl LambdaClient<'_> {
401 pub async fn get_invocations(&self) -> Result<LambdaInvocationsResponse, Error> {
403 let resp = self
404 .fc
405 .client
406 .get(format!(
407 "{}/_fakecloud/lambda/invocations",
408 self.fc.base_url
409 ))
410 .send()
411 .await?;
412 FakeCloud::parse(resp).await
413 }
414
415 pub async fn get_warm_containers(&self) -> Result<WarmContainersResponse, Error> {
417 let resp = self
418 .fc
419 .client
420 .get(format!(
421 "{}/_fakecloud/lambda/warm-containers",
422 self.fc.base_url
423 ))
424 .send()
425 .await?;
426 FakeCloud::parse(resp).await
427 }
428
429 pub async fn evict_container(
431 &self,
432 function_name: &str,
433 ) -> Result<EvictContainerResponse, Error> {
434 let resp = self
435 .fc
436 .client
437 .post(format!(
438 "{}/_fakecloud/lambda/{}/evict-container",
439 self.fc.base_url, function_name
440 ))
441 .send()
442 .await?;
443 FakeCloud::parse(resp).await
444 }
445
446 pub async fn download_function_code(
450 &self,
451 account_id: &str,
452 function_name: &str,
453 qualifier_or_latest: &str,
454 ) -> Result<Vec<u8>, Error> {
455 let resp = self
456 .fc
457 .client
458 .get(format!(
459 "{}/_fakecloud/lambda/function-code/{}/{}/{}.zip",
460 self.fc.base_url, account_id, function_name, qualifier_or_latest
461 ))
462 .send()
463 .await?;
464 let status = resp.status().as_u16();
465 if !resp.status().is_success() {
466 let body = resp.text().await.unwrap_or_default();
467 return Err(Error::Api { status, body });
468 }
469 Ok(resp.bytes().await?.to_vec())
470 }
471
472 pub async fn download_layer_content(
474 &self,
475 account_id: &str,
476 layer_name: &str,
477 version: i64,
478 ) -> Result<Vec<u8>, Error> {
479 let resp = self
480 .fc
481 .client
482 .get(format!(
483 "{}/_fakecloud/lambda/layer-content/{}/{}/{}.zip",
484 self.fc.base_url, account_id, layer_name, version
485 ))
486 .send()
487 .await?;
488 let status = resp.status().as_u16();
489 if !resp.status().is_success() {
490 let body = resp.text().await.unwrap_or_default();
491 return Err(Error::Api { status, body });
492 }
493 Ok(resp.bytes().await?.to_vec())
494 }
495}
496
497pub struct SesClient<'a> {
500 fc: &'a FakeCloud,
501}
502
503impl SesClient<'_> {
504 pub async fn get_emails(&self) -> Result<SesEmailsResponse, Error> {
506 let resp = self
507 .fc
508 .client
509 .get(format!("{}/_fakecloud/ses/emails", self.fc.base_url))
510 .send()
511 .await?;
512 FakeCloud::parse(resp).await
513 }
514
515 pub async fn simulate_inbound(
517 &self,
518 req: &InboundEmailRequest,
519 ) -> Result<InboundEmailResponse, Error> {
520 let resp = self
521 .fc
522 .client
523 .post(format!("{}/_fakecloud/ses/inbound", self.fc.base_url))
524 .json(req)
525 .send()
526 .await?;
527 FakeCloud::parse(resp).await
528 }
529
530 pub async fn get_metrics(&self) -> Result<SesMetricsResponse, Error> {
533 let resp = self
534 .fc
535 .client
536 .get(format!("{}/_fakecloud/ses/metrics", self.fc.base_url))
537 .send()
538 .await?;
539 FakeCloud::parse(resp).await
540 }
541
542 pub async fn get_bounces(&self) -> Result<SesBouncesResponse, Error> {
544 let resp = self
545 .fc
546 .client
547 .get(format!("{}/_fakecloud/ses/bounces", self.fc.base_url))
548 .send()
549 .await?;
550 FakeCloud::parse(resp).await
551 }
552
553 pub async fn set_sandbox(&self, sandbox: bool) -> Result<SesSandboxResponse, Error> {
557 let resp = self
558 .fc
559 .client
560 .post(format!(
561 "{}/_fakecloud/ses/account/sandbox",
562 self.fc.base_url
563 ))
564 .json(&SesSandboxRequest { sandbox })
565 .send()
566 .await?;
567 FakeCloud::parse(resp).await
568 }
569
570 pub async fn get_event_destination_deliveries(
573 &self,
574 ) -> Result<SesEventDestinationDeliveriesResponse, Error> {
575 let resp = self
576 .fc
577 .client
578 .get(format!(
579 "{}/_fakecloud/ses/event-destinations/deliveries",
580 self.fc.base_url
581 ))
582 .send()
583 .await?;
584 FakeCloud::parse(resp).await
585 }
586
587 pub async fn get_dkim_public_key(
590 &self,
591 identity: &str,
592 ) -> Result<SesDkimPublicKeyResponse, Error> {
593 let resp = self
594 .fc
595 .client
596 .get(format!(
597 "{}/_fakecloud/ses/identities/{}/dkim-public-key",
598 self.fc.base_url, identity
599 ))
600 .send()
601 .await?;
602 FakeCloud::parse(resp).await
603 }
604
605 pub async fn set_mail_from_status(
608 &self,
609 identity: &str,
610 status: &str,
611 ) -> Result<SesMailFromStatusResponse, Error> {
612 let resp = self
613 .fc
614 .client
615 .post(format!(
616 "{}/_fakecloud/ses/identities/{}/mail-from-status",
617 self.fc.base_url, identity
618 ))
619 .json(&SesMailFromStatusRequest {
620 status: status.to_string(),
621 })
622 .send()
623 .await?;
624 FakeCloud::parse(resp).await
625 }
626
627 pub async fn get_message_insights(
630 &self,
631 message_id: &str,
632 ) -> Result<SesMessageInsightsResponse, Error> {
633 let resp = self
634 .fc
635 .client
636 .get(format!(
637 "{}/_fakecloud/ses/messages/{}/insights",
638 self.fc.base_url, message_id
639 ))
640 .send()
641 .await?;
642 FakeCloud::parse(resp).await
643 }
644
645 pub async fn get_smtp_submissions(&self) -> Result<SesSmtpSubmissionsResponse, Error> {
647 let resp = self
648 .fc
649 .client
650 .get(format!(
651 "{}/_fakecloud/ses/smtp/submissions",
652 self.fc.base_url
653 ))
654 .send()
655 .await?;
656 FakeCloud::parse(resp).await
657 }
658}
659
660pub struct SnsClient<'a> {
663 fc: &'a FakeCloud,
664}
665
666impl SnsClient<'_> {
667 pub async fn get_messages(&self) -> Result<SnsMessagesResponse, Error> {
669 let resp = self
670 .fc
671 .client
672 .get(format!("{}/_fakecloud/sns/messages", self.fc.base_url))
673 .send()
674 .await?;
675 FakeCloud::parse(resp).await
676 }
677
678 pub async fn get_pending_confirmations(&self) -> Result<PendingConfirmationsResponse, Error> {
680 let resp = self
681 .fc
682 .client
683 .get(format!(
684 "{}/_fakecloud/sns/pending-confirmations",
685 self.fc.base_url
686 ))
687 .send()
688 .await?;
689 FakeCloud::parse(resp).await
690 }
691
692 pub async fn confirm_subscription(
694 &self,
695 req: &ConfirmSubscriptionRequest,
696 ) -> Result<ConfirmSubscriptionResponse, Error> {
697 let resp = self
698 .fc
699 .client
700 .post(format!(
701 "{}/_fakecloud/sns/confirm-subscription",
702 self.fc.base_url
703 ))
704 .json(req)
705 .send()
706 .await?;
707 FakeCloud::parse(resp).await
708 }
709
710 pub async fn cert_pem(&self) -> Result<String, Error> {
715 let resp = self
716 .fc
717 .client
718 .get(format!("{}/_fakecloud/sns/cert.pem", self.fc.base_url))
719 .send()
720 .await?;
721 let status = resp.status().as_u16();
722 if !resp.status().is_success() {
723 let body = resp.text().await.unwrap_or_default();
724 return Err(Error::Api { status, body });
725 }
726 Ok(resp.text().await?)
727 }
728
729 pub async fn sms(&self) -> Result<SnsSmsResponse, Error> {
731 let resp = self
732 .fc
733 .client
734 .get(format!("{}/_fakecloud/sns/sms", self.fc.base_url))
735 .send()
736 .await?;
737 FakeCloud::parse(resp).await
738 }
739}
740
741pub struct SqsClient<'a> {
744 fc: &'a FakeCloud,
745}
746
747impl SqsClient<'_> {
748 pub async fn get_messages(&self) -> Result<SqsMessagesResponse, Error> {
750 let resp = self
751 .fc
752 .client
753 .get(format!("{}/_fakecloud/sqs/messages", self.fc.base_url))
754 .send()
755 .await?;
756 FakeCloud::parse(resp).await
757 }
758
759 pub async fn tick_expiration(&self) -> Result<ExpirationTickResponse, Error> {
761 let resp = self
762 .fc
763 .client
764 .post(format!(
765 "{}/_fakecloud/sqs/expiration-processor/tick",
766 self.fc.base_url
767 ))
768 .send()
769 .await?;
770 FakeCloud::parse(resp).await
771 }
772
773 pub async fn force_dlq(&self, queue_name: &str) -> Result<ForceDlqResponse, Error> {
775 let resp = self
776 .fc
777 .client
778 .post(format!(
779 "{}/_fakecloud/sqs/{}/force-dlq",
780 self.fc.base_url, queue_name
781 ))
782 .send()
783 .await?;
784 FakeCloud::parse(resp).await
785 }
786}
787
788pub struct ApplicationAutoScalingClient<'a> {
791 fc: &'a FakeCloud,
792}
793
794impl ApplicationAutoScalingClient<'_> {
795 pub async fn tick(&self) -> Result<AppAsTickResponse, Error> {
800 let resp = self
801 .fc
802 .client
803 .post(format!(
804 "{}/_fakecloud/application-autoscaling/tick",
805 self.fc.base_url
806 ))
807 .send()
808 .await?;
809 FakeCloud::parse(resp).await
810 }
811
812 pub async fn scheduled_tick(&self) -> Result<AppAsScheduledTickResponse, Error> {
817 let resp = self
818 .fc
819 .client
820 .post(format!(
821 "{}/_fakecloud/application-autoscaling/scheduled-tick",
822 self.fc.base_url
823 ))
824 .send()
825 .await?;
826 FakeCloud::parse(resp).await
827 }
828}
829
830pub struct EventsClient<'a> {
833 fc: &'a FakeCloud,
834}
835
836impl EventsClient<'_> {
837 pub async fn get_history(&self) -> Result<EventHistoryResponse, Error> {
839 let resp = self
840 .fc
841 .client
842 .get(format!("{}/_fakecloud/events/history", self.fc.base_url))
843 .send()
844 .await?;
845 FakeCloud::parse(resp).await
846 }
847
848 pub async fn fire_rule(&self, req: &FireRuleRequest) -> Result<FireRuleResponse, Error> {
850 let resp = self
851 .fc
852 .client
853 .post(format!("{}/_fakecloud/events/fire-rule", self.fc.base_url))
854 .json(req)
855 .send()
856 .await?;
857 FakeCloud::parse(resp).await
858 }
859}
860
861pub struct S3Client<'a> {
864 fc: &'a FakeCloud,
865}
866
867impl S3Client<'_> {
868 pub async fn get_notifications(&self) -> Result<S3NotificationsResponse, Error> {
870 let resp = self
871 .fc
872 .client
873 .get(format!("{}/_fakecloud/s3/notifications", self.fc.base_url))
874 .send()
875 .await?;
876 FakeCloud::parse(resp).await
877 }
878
879 pub async fn tick_lifecycle(&self) -> Result<LifecycleTickResponse, Error> {
881 let resp = self
882 .fc
883 .client
884 .post(format!(
885 "{}/_fakecloud/s3/lifecycle-processor/tick",
886 self.fc.base_url
887 ))
888 .send()
889 .await?;
890 FakeCloud::parse(resp).await
891 }
892
893 pub async fn get_access_points(&self) -> Result<S3AccessPointsResponse, Error> {
895 let resp = self
896 .fc
897 .client
898 .get(format!("{}/_fakecloud/s3/access-points", self.fc.base_url))
899 .send()
900 .await?;
901 FakeCloud::parse(resp).await
902 }
903
904 pub async fn get_object_lambda_responses(
906 &self,
907 ) -> Result<S3ObjectLambdaResponsesResponse, Error> {
908 let resp = self
909 .fc
910 .client
911 .get(format!(
912 "{}/_fakecloud/s3/object-lambda-responses",
913 self.fc.base_url
914 ))
915 .send()
916 .await?;
917 FakeCloud::parse(resp).await
918 }
919}
920
921pub struct DynamoDbClient<'a> {
924 fc: &'a FakeCloud,
925}
926
927impl DynamoDbClient<'_> {
928 pub async fn tick_ttl(&self) -> Result<TtlTickResponse, Error> {
930 let resp = self
931 .fc
932 .client
933 .post(format!(
934 "{}/_fakecloud/dynamodb/ttl-processor/tick",
935 self.fc.base_url
936 ))
937 .send()
938 .await?;
939 FakeCloud::parse(resp).await
940 }
941}
942
943pub struct SecretsManagerClient<'a> {
946 fc: &'a FakeCloud,
947}
948
949impl SecretsManagerClient<'_> {
950 pub async fn tick_rotation(&self) -> Result<RotationTickResponse, Error> {
952 let resp = self
953 .fc
954 .client
955 .post(format!(
956 "{}/_fakecloud/secretsmanager/rotation-scheduler/tick",
957 self.fc.base_url
958 ))
959 .send()
960 .await?;
961 FakeCloud::parse(resp).await
962 }
963}
964
965pub struct CognitoClient<'a> {
968 fc: &'a FakeCloud,
969}
970
971impl CognitoClient<'_> {
972 pub async fn get_user_codes(
974 &self,
975 pool_id: &str,
976 username: &str,
977 ) -> Result<UserConfirmationCodes, Error> {
978 let resp = self
979 .fc
980 .client
981 .get(format!(
982 "{}/_fakecloud/cognito/confirmation-codes/{}/{}",
983 self.fc.base_url, pool_id, username
984 ))
985 .send()
986 .await?;
987 FakeCloud::parse(resp).await
988 }
989
990 pub async fn get_confirmation_codes(&self) -> Result<ConfirmationCodesResponse, Error> {
992 let resp = self
993 .fc
994 .client
995 .get(format!(
996 "{}/_fakecloud/cognito/confirmation-codes",
997 self.fc.base_url
998 ))
999 .send()
1000 .await?;
1001 FakeCloud::parse(resp).await
1002 }
1003
1004 pub async fn confirm_user(
1006 &self,
1007 req: &ConfirmUserRequest,
1008 ) -> Result<ConfirmUserResponse, Error> {
1009 let resp = self
1010 .fc
1011 .client
1012 .post(format!(
1013 "{}/_fakecloud/cognito/confirm-user",
1014 self.fc.base_url
1015 ))
1016 .json(req)
1017 .send()
1018 .await?;
1019 let status = resp.status().as_u16();
1020 let body: ConfirmUserResponse = resp.json().await?;
1021 if status >= 400 {
1022 return Err(Error::Api {
1023 status,
1024 body: body.error.unwrap_or_default(),
1025 });
1026 }
1027 Ok(body)
1028 }
1029
1030 pub async fn get_tokens(&self) -> Result<TokensResponse, Error> {
1032 let resp = self
1033 .fc
1034 .client
1035 .get(format!("{}/_fakecloud/cognito/tokens", self.fc.base_url))
1036 .send()
1037 .await?;
1038 FakeCloud::parse(resp).await
1039 }
1040
1041 pub async fn expire_tokens(
1043 &self,
1044 req: &ExpireTokensRequest,
1045 ) -> Result<ExpireTokensResponse, Error> {
1046 let resp = self
1047 .fc
1048 .client
1049 .post(format!(
1050 "{}/_fakecloud/cognito/expire-tokens",
1051 self.fc.base_url
1052 ))
1053 .json(req)
1054 .send()
1055 .await?;
1056 FakeCloud::parse(resp).await
1057 }
1058
1059 pub async fn get_auth_events(&self) -> Result<AuthEventsResponse, Error> {
1061 let resp = self
1062 .fc
1063 .client
1064 .get(format!(
1065 "{}/_fakecloud/cognito/auth-events",
1066 self.fc.base_url
1067 ))
1068 .send()
1069 .await?;
1070 FakeCloud::parse(resp).await
1071 }
1072
1073 pub async fn get_pre_token_gen_invocations(
1079 &self,
1080 ) -> Result<PreTokenGenInvocationsResponse, Error> {
1081 let resp = self
1082 .fc
1083 .client
1084 .get(format!(
1085 "{}/_fakecloud/cognito/pretokengen/invocations",
1086 self.fc.base_url
1087 ))
1088 .send()
1089 .await?;
1090 FakeCloud::parse(resp).await
1091 }
1092
1093 pub async fn mint_authorization_code(
1097 &self,
1098 req: &MintAuthorizationCodeRequest,
1099 ) -> Result<MintAuthorizationCodeResponse, Error> {
1100 let resp = self
1101 .fc
1102 .client
1103 .post(format!(
1104 "{}/_fakecloud/cognito/authorization-codes",
1105 self.fc.base_url
1106 ))
1107 .json(req)
1108 .send()
1109 .await?;
1110 FakeCloud::parse(resp).await
1111 }
1112
1113 pub async fn set_compromised_passwords(
1118 &self,
1119 req: &CognitoCompromisedPasswordsRequest,
1120 ) -> Result<CompromisedPasswordsResponse, Error> {
1121 let resp = self
1122 .fc
1123 .client
1124 .post(format!(
1125 "{}/_fakecloud/cognito/compromised-passwords",
1126 self.fc.base_url
1127 ))
1128 .json(req)
1129 .send()
1130 .await?;
1131 FakeCloud::parse(resp).await
1132 }
1133
1134 pub async fn get_webauthn_credentials(&self) -> Result<WebAuthnCredentialsResponse, Error> {
1136 let resp = self
1137 .fc
1138 .client
1139 .get(format!(
1140 "{}/_fakecloud/cognito/webauthn-credentials",
1141 self.fc.base_url
1142 ))
1143 .send()
1144 .await?;
1145 FakeCloud::parse(resp).await
1146 }
1147}
1148
1149pub struct ApiGatewayV2Client<'a> {
1152 fc: &'a FakeCloud,
1153}
1154
1155impl ApiGatewayV2Client<'_> {
1156 pub async fn get_requests(&self) -> Result<ApiGatewayV2RequestsResponse, Error> {
1158 let resp = self
1159 .fc
1160 .client
1161 .get(format!(
1162 "{}/_fakecloud/apigatewayv2/requests",
1163 self.fc.base_url
1164 ))
1165 .send()
1166 .await?;
1167 FakeCloud::parse(resp).await
1168 }
1169
1170 pub async fn connections(&self) -> Result<ApiGatewayV2ConnectionsResponse, Error> {
1173 let resp = self
1174 .fc
1175 .client
1176 .get(format!(
1177 "{}/_fakecloud/apigatewayv2/connections",
1178 self.fc.base_url
1179 ))
1180 .send()
1181 .await?;
1182 FakeCloud::parse(resp).await
1183 }
1184
1185 pub async fn mtls_info(&self, name: &str) -> Result<serde_json::Value, Error> {
1189 let resp = self
1190 .fc
1191 .client
1192 .get(format!(
1193 "{}/_fakecloud/apigatewayv2/domain-names/{}/mtls-info",
1194 self.fc.base_url, name
1195 ))
1196 .send()
1197 .await?;
1198 FakeCloud::parse(resp).await
1199 }
1200
1201 pub fn ws_url(&self, api_id: &str, stage: Option<&str>) -> String {
1205 let base = self
1206 .fc
1207 .base_url
1208 .replacen("https://", "wss://", 1)
1209 .replacen("http://", "ws://", 1);
1210 let url = reqwest::Url::parse(&format!("{}/_fakecloud/apigatewayv2/ws/{}", base, api_id))
1214 .expect("base url + api id form a valid URL");
1215 match stage {
1216 Some(s) => {
1217 let mut u = url;
1218 u.query_pairs_mut().append_pair("stage", s);
1219 u.to_string()
1220 }
1221 None => url.to_string(),
1222 }
1223 }
1224}
1225
1226pub struct StepFunctionsClient<'a> {
1229 fc: &'a FakeCloud,
1230}
1231
1232impl StepFunctionsClient<'_> {
1233 pub async fn get_executions(&self) -> Result<StepFunctionsExecutionsResponse, Error> {
1235 let resp = self
1236 .fc
1237 .client
1238 .get(format!(
1239 "{}/_fakecloud/stepfunctions/executions",
1240 self.fc.base_url
1241 ))
1242 .send()
1243 .await?;
1244 FakeCloud::parse(resp).await
1245 }
1246
1247 pub async fn get_sync_executions(&self) -> Result<StepFunctionsSyncExecutionsResponse, Error> {
1251 let resp = self
1252 .fc
1253 .client
1254 .get(format!(
1255 "{}/_fakecloud/stepfunctions/sync-executions",
1256 self.fc.base_url
1257 ))
1258 .send()
1259 .await?;
1260 FakeCloud::parse(resp).await
1261 }
1262
1263 pub async fn enqueue_activity_task(
1271 &self,
1272 req: &SfnEnqueueActivityTaskRequest,
1273 ) -> Result<SfnEnqueueActivityTaskResponse, Error> {
1274 let resp = self
1275 .fc
1276 .client
1277 .post(format!(
1278 "{}/_fakecloud/stepfunctions/enqueue-activity-task",
1279 self.fc.base_url
1280 ))
1281 .json(req)
1282 .send()
1283 .await?;
1284 FakeCloud::parse(resp).await
1285 }
1286
1287 pub async fn get_execution_tree(
1288 &self,
1289 execution_arn: &str,
1290 ) -> Result<StepFunctionsExecutionTreeResponse, Error> {
1291 let mut encoded = String::with_capacity(execution_arn.len());
1292 for b in execution_arn.bytes() {
1293 match b {
1294 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1295 encoded.push(b as char);
1296 }
1297 _ => encoded.push_str(&format!("%{:02X}", b)),
1298 }
1299 }
1300 let resp = self
1301 .fc
1302 .client
1303 .get(format!(
1304 "{}/_fakecloud/stepfunctions/execution-tree/{}",
1305 self.fc.base_url, encoded
1306 ))
1307 .send()
1308 .await?;
1309 FakeCloud::parse(resp).await
1310 }
1311}
1312
1313pub struct BedrockClient<'a> {
1316 fc: &'a FakeCloud,
1317}
1318
1319impl BedrockClient<'_> {
1320 pub async fn get_invocations(&self) -> Result<BedrockInvocationsResponse, Error> {
1323 let resp = self
1324 .fc
1325 .client
1326 .get(format!(
1327 "{}/_fakecloud/bedrock/invocations",
1328 self.fc.base_url
1329 ))
1330 .send()
1331 .await?;
1332 FakeCloud::parse(resp).await
1333 }
1334
1335 pub async fn set_model_response(
1337 &self,
1338 model_id: &str,
1339 response: &str,
1340 ) -> Result<BedrockModelResponseConfig, Error> {
1341 let resp = self
1342 .fc
1343 .client
1344 .post(format!(
1345 "{}/_fakecloud/bedrock/models/{}/response",
1346 self.fc.base_url, model_id
1347 ))
1348 .header("content-type", "text/plain")
1349 .body(response.to_string())
1350 .send()
1351 .await?;
1352 FakeCloud::parse(resp).await
1353 }
1354
1355 pub async fn set_response_rules(
1357 &self,
1358 model_id: &str,
1359 rules: &[BedrockResponseRule],
1360 ) -> Result<BedrockModelResponseConfig, Error> {
1361 let body = serde_json::json!({ "rules": rules });
1362 let resp = self
1363 .fc
1364 .client
1365 .post(format!(
1366 "{}/_fakecloud/bedrock/models/{}/responses",
1367 self.fc.base_url, model_id
1368 ))
1369 .json(&body)
1370 .send()
1371 .await?;
1372 FakeCloud::parse(resp).await
1373 }
1374
1375 pub async fn clear_response_rules(
1377 &self,
1378 model_id: &str,
1379 ) -> Result<BedrockModelResponseConfig, Error> {
1380 let resp = self
1381 .fc
1382 .client
1383 .delete(format!(
1384 "{}/_fakecloud/bedrock/models/{}/responses",
1385 self.fc.base_url, model_id
1386 ))
1387 .send()
1388 .await?;
1389 FakeCloud::parse(resp).await
1390 }
1391
1392 pub async fn queue_fault(
1394 &self,
1395 rule: &BedrockFaultRule,
1396 ) -> Result<BedrockStatusResponse, Error> {
1397 let resp = self
1398 .fc
1399 .client
1400 .post(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1401 .json(rule)
1402 .send()
1403 .await?;
1404 FakeCloud::parse(resp).await
1405 }
1406
1407 pub async fn get_faults(&self) -> Result<BedrockFaultsResponse, Error> {
1409 let resp = self
1410 .fc
1411 .client
1412 .get(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1413 .send()
1414 .await?;
1415 FakeCloud::parse(resp).await
1416 }
1417
1418 pub async fn clear_faults(&self) -> Result<BedrockStatusResponse, Error> {
1420 let resp = self
1421 .fc
1422 .client
1423 .delete(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1424 .send()
1425 .await?;
1426 FakeCloud::parse(resp).await
1427 }
1428}
1429
1430pub struct BedrockAgentClient<'a> {
1433 fc: &'a FakeCloud,
1434}
1435
1436impl BedrockAgentClient<'_> {
1437 pub async fn get_agents(&self) -> Result<BedrockAgentAgentsResponse, Error> {
1441 let resp = self
1442 .fc
1443 .client
1444 .get(format!(
1445 "{}/_fakecloud/bedrock-agent/agents",
1446 self.fc.base_url
1447 ))
1448 .send()
1449 .await?;
1450 FakeCloud::parse(resp).await
1451 }
1452}
1453
1454pub struct BedrockAgentRuntimeClient<'a> {
1457 fc: &'a FakeCloud,
1458}
1459
1460impl BedrockAgentRuntimeClient<'_> {
1461 pub async fn get_invocations(&self) -> Result<BedrockAgentRuntimeInvocationsResponse, Error> {
1464 let resp = self
1465 .fc
1466 .client
1467 .get(format!(
1468 "{}/_fakecloud/bedrock-agent-runtime/invocations",
1469 self.fc.base_url
1470 ))
1471 .send()
1472 .await?;
1473 FakeCloud::parse(resp).await
1474 }
1475}
1476
1477pub struct EcsClient<'a> {
1480 fc: &'a FakeCloud,
1481}
1482
1483impl EcsClient<'_> {
1484 pub async fn get_clusters(&self) -> Result<EcsClustersResponse, Error> {
1488 let resp = self
1489 .fc
1490 .client
1491 .get(format!("{}/_fakecloud/ecs/clusters", self.fc.base_url))
1492 .send()
1493 .await?;
1494 FakeCloud::parse(resp).await
1495 }
1496
1497 pub async fn get_tasks(
1500 &self,
1501 cluster: Option<&str>,
1502 status: Option<&str>,
1503 ) -> Result<EcsTasksResponse, Error> {
1504 fn encode(s: &str) -> String {
1505 let mut out = String::with_capacity(s.len());
1506 for b in s.bytes() {
1507 match b {
1508 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1509 out.push(b as char);
1510 }
1511 _ => out.push_str(&format!("%{:02X}", b)),
1512 }
1513 }
1514 out
1515 }
1516 let mut url = format!("{}/_fakecloud/ecs/tasks", self.fc.base_url);
1517 let mut sep = '?';
1518 if let Some(c) = cluster {
1519 url.push(sep);
1520 url.push_str("cluster=");
1521 url.push_str(&encode(c));
1522 sep = '&';
1523 }
1524 if let Some(s) = status {
1525 url.push(sep);
1526 url.push_str("status=");
1527 url.push_str(&encode(s));
1528 }
1529 let resp = self.fc.client.get(url).send().await?;
1530 FakeCloud::parse(resp).await
1531 }
1532
1533 pub async fn get_task_logs(&self, task_id: &str) -> Result<EcsTaskLogsResponse, Error> {
1537 let resp = self
1538 .fc
1539 .client
1540 .get(format!(
1541 "{}/_fakecloud/ecs/tasks/{}/logs",
1542 self.fc.base_url, task_id
1543 ))
1544 .send()
1545 .await?;
1546 FakeCloud::parse(resp).await
1547 }
1548
1549 pub async fn force_stop_task(&self, task_id: &str) -> Result<EcsTask, Error> {
1551 let resp = self
1552 .fc
1553 .client
1554 .post(format!(
1555 "{}/_fakecloud/ecs/tasks/{}/force-stop",
1556 self.fc.base_url, task_id
1557 ))
1558 .send()
1559 .await?;
1560 FakeCloud::parse(resp).await
1561 }
1562
1563 pub async fn mark_task_failed(
1566 &self,
1567 task_id: &str,
1568 req: &EcsMarkFailedRequest,
1569 ) -> Result<EcsTask, Error> {
1570 let resp = self
1571 .fc
1572 .client
1573 .post(format!(
1574 "{}/_fakecloud/ecs/tasks/{}/mark-failed",
1575 self.fc.base_url, task_id
1576 ))
1577 .json(req)
1578 .send()
1579 .await?;
1580 FakeCloud::parse(resp).await
1581 }
1582
1583 pub async fn get_events(&self) -> Result<EcsEventsResponse, Error> {
1585 let resp = self
1586 .fc
1587 .client
1588 .get(format!("{}/_fakecloud/ecs/events", self.fc.base_url))
1589 .send()
1590 .await?;
1591 FakeCloud::parse(resp).await
1592 }
1593
1594 pub async fn get_metadata_by_arn(&self, task_arn: &str) -> Result<serde_json::Value, Error> {
1601 let mut encoded = String::with_capacity(task_arn.len());
1602 for b in task_arn.bytes() {
1603 match b {
1604 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1605 encoded.push(b as char);
1606 }
1607 _ => encoded.push_str(&format!("%{:02X}", b)),
1608 }
1609 }
1610 let resp = self
1611 .fc
1612 .client
1613 .get(format!(
1614 "{}/_fakecloud/ecs/metadata/{}",
1615 self.fc.base_url, encoded
1616 ))
1617 .send()
1618 .await?;
1619 FakeCloud::parse(resp).await
1620 }
1621
1622 pub async fn task_credentials(
1627 &self,
1628 task_id: &str,
1629 ) -> Result<EcsTaskCredentialsResponse, Error> {
1630 let resp = self
1631 .fc
1632 .client
1633 .get(format!(
1634 "{}/_fakecloud/ecs/creds/{}",
1635 self.fc.base_url, task_id
1636 ))
1637 .send()
1638 .await?;
1639 FakeCloud::parse(resp).await
1640 }
1641
1642 pub async fn task_metadata_v3(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1648 let resp = self
1649 .fc
1650 .client
1651 .get(format!(
1652 "{}/_fakecloud/ecs/v3/{}",
1653 self.fc.base_url, task_id
1654 ))
1655 .send()
1656 .await?;
1657 FakeCloud::parse(resp).await
1658 }
1659
1660 pub async fn task_metadata_v4(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1664 let resp = self
1665 .fc
1666 .client
1667 .get(format!(
1668 "{}/_fakecloud/ecs/v4/{}",
1669 self.fc.base_url, task_id
1670 ))
1671 .send()
1672 .await?;
1673 FakeCloud::parse(resp).await
1674 }
1675}
1676
1677pub struct Route53Client<'a> {
1680 fc: &'a FakeCloud,
1681}
1682
1683impl Route53Client<'_> {
1684 pub async fn dnssec_material(
1688 &self,
1689 zone_id: &str,
1690 ) -> Result<Route53DnssecMaterialResponse, Error> {
1691 let resp = self
1692 .fc
1693 .client
1694 .get(format!(
1695 "{}/_fakecloud/route53/zones/{}/dnssec",
1696 self.fc.base_url, zone_id
1697 ))
1698 .send()
1699 .await?;
1700 FakeCloud::parse(resp).await
1701 }
1702
1703 pub async fn dnssec_sign(
1707 &self,
1708 zone_id: &str,
1709 req: &Route53DnssecSignRequest,
1710 ) -> Result<Route53DnssecSignResponse, Error> {
1711 let resp = self
1712 .fc
1713 .client
1714 .post(format!(
1715 "{}/_fakecloud/route53/zones/{}/dnssec/sign",
1716 self.fc.base_url, zone_id
1717 ))
1718 .json(req)
1719 .send()
1720 .await?;
1721 FakeCloud::parse(resp).await
1722 }
1723}
1724
1725pub struct AthenaClient<'a> {
1728 fc: &'a FakeCloud,
1729}
1730
1731impl AthenaClient<'_> {
1732 pub async fn get_named_queries(&self) -> Result<AthenaNamedQueriesResponse, Error> {
1737 let resp = self
1738 .fc
1739 .client
1740 .get(format!(
1741 "{}/_fakecloud/athena/named-queries",
1742 self.fc.base_url
1743 ))
1744 .send()
1745 .await?;
1746 FakeCloud::parse(resp).await
1747 }
1748}
1749
1750pub struct OrganizationsClient<'a> {
1753 fc: &'a FakeCloud,
1754}
1755
1756impl OrganizationsClient<'_> {
1757 pub async fn get_accounts(&self) -> Result<OrganizationsAccountsResponse, Error> {
1762 let resp = self
1763 .fc
1764 .client
1765 .get(format!(
1766 "{}/_fakecloud/organizations/accounts",
1767 self.fc.base_url
1768 ))
1769 .send()
1770 .await?;
1771 FakeCloud::parse(resp).await
1772 }
1773
1774 pub async fn get_responsibility_transfers(
1778 &self,
1779 ) -> Result<OrganizationsResponsibilityTransfersResponse, Error> {
1780 let resp = self
1781 .fc
1782 .client
1783 .get(format!(
1784 "{}/_fakecloud/organizations/responsibility-transfers",
1785 self.fc.base_url
1786 ))
1787 .send()
1788 .await?;
1789 FakeCloud::parse(resp).await
1790 }
1791}
1792
1793pub struct AcmClient<'a> {
1796 fc: &'a FakeCloud,
1797}
1798
1799impl AcmClient<'_> {
1800 fn certificate_id(arn_or_id: &str) -> String {
1801 match arn_or_id.rfind("certificate/") {
1802 Some(idx) => arn_or_id[idx + "certificate/".len()..].to_string(),
1803 None => arn_or_id.to_string(),
1804 }
1805 }
1806
1807 pub async fn set_certificate_status(
1812 &self,
1813 arn_or_id: &str,
1814 req: &AcmCertificateStatusRequest,
1815 ) -> Result<(), Error> {
1816 let id = Self::certificate_id(arn_or_id);
1817 let resp = self
1818 .fc
1819 .client
1820 .post(format!(
1821 "{}/_fakecloud/acm/certificates/{}/status",
1822 self.fc.base_url, id
1823 ))
1824 .json(req)
1825 .send()
1826 .await?;
1827 if !resp.status().is_success() {
1828 let status = resp.status().as_u16();
1829 let body = resp.text().await.unwrap_or_default();
1830 return Err(Error::Api { status, body });
1831 }
1832 Ok(())
1833 }
1834
1835 pub async fn get_certificate_chain_info(
1839 &self,
1840 arn_or_id: &str,
1841 ) -> Result<AcmCertificateChainInfo, Error> {
1842 let id = Self::certificate_id(arn_or_id);
1843 let resp = self
1844 .fc
1845 .client
1846 .get(format!(
1847 "{}/_fakecloud/acm/certificates/{}/chain-info",
1848 self.fc.base_url, id
1849 ))
1850 .send()
1851 .await?;
1852 FakeCloud::parse(resp).await
1853 }
1854
1855 pub async fn approve_certificate(&self, arn_or_id: &str) -> Result<(), Error> {
1859 let id = Self::certificate_id(arn_or_id);
1860 let resp = self
1861 .fc
1862 .client
1863 .post(format!(
1864 "{}/_fakecloud/acm/certificates/{}/approve",
1865 self.fc.base_url, id
1866 ))
1867 .send()
1868 .await?;
1869 if !resp.status().is_success() {
1870 let status = resp.status().as_u16();
1871 let body = resp.text().await.unwrap_or_default();
1872 return Err(Error::Api { status, body });
1873 }
1874 Ok(())
1875 }
1876}
1877
1878pub struct EcrClient<'a> {
1881 fc: &'a FakeCloud,
1882}
1883
1884impl EcrClient<'_> {
1885 pub async fn get_images(&self) -> Result<EcrImagesResponse, Error> {
1887 let resp = self
1888 .fc
1889 .client
1890 .get(format!("{}/_fakecloud/ecr/images", self.fc.base_url))
1891 .send()
1892 .await?;
1893 FakeCloud::parse(resp).await
1894 }
1895
1896 pub async fn get_repositories(&self) -> Result<EcrRepositoriesResponse, Error> {
1898 let resp = self
1899 .fc
1900 .client
1901 .get(format!("{}/_fakecloud/ecr/repositories", self.fc.base_url))
1902 .send()
1903 .await?;
1904 FakeCloud::parse(resp).await
1905 }
1906
1907 pub async fn get_pull_through_rules(&self) -> Result<EcrPullThroughRulesResponse, Error> {
1909 let resp = self
1910 .fc
1911 .client
1912 .get(format!(
1913 "{}/_fakecloud/ecr/pull-through-rules",
1914 self.fc.base_url
1915 ))
1916 .send()
1917 .await?;
1918 FakeCloud::parse(resp).await
1919 }
1920}
1921
1922pub struct Elbv2Client<'a> {
1925 fc: &'a FakeCloud,
1926}
1927
1928impl Elbv2Client<'_> {
1929 pub async fn get_load_balancers(&self) -> Result<Elbv2LoadBalancersResponse, Error> {
1931 let resp = self
1932 .fc
1933 .client
1934 .get(format!(
1935 "{}/_fakecloud/elbv2/load-balancers",
1936 self.fc.base_url
1937 ))
1938 .send()
1939 .await?;
1940 FakeCloud::parse(resp).await
1941 }
1942
1943 pub async fn get_listeners(&self) -> Result<Elbv2ListenersResponse, Error> {
1945 let resp = self
1946 .fc
1947 .client
1948 .get(format!("{}/_fakecloud/elbv2/listeners", self.fc.base_url))
1949 .send()
1950 .await?;
1951 FakeCloud::parse(resp).await
1952 }
1953
1954 pub async fn get_rules(&self) -> Result<Elbv2RulesResponse, Error> {
1956 let resp = self
1957 .fc
1958 .client
1959 .get(format!("{}/_fakecloud/elbv2/rules", self.fc.base_url))
1960 .send()
1961 .await?;
1962 FakeCloud::parse(resp).await
1963 }
1964
1965 pub async fn get_target_groups(&self) -> Result<Elbv2TargetGroupsResponse, Error> {
1968 let resp = self
1969 .fc
1970 .client
1971 .get(format!(
1972 "{}/_fakecloud/elbv2/target-groups",
1973 self.fc.base_url
1974 ))
1975 .send()
1976 .await?;
1977 FakeCloud::parse(resp).await
1978 }
1979
1980 pub async fn flush_access_logs(&self) -> Result<Elbv2AccessLogsFlushResponse, Error> {
1983 let resp = self
1984 .fc
1985 .client
1986 .post(format!(
1987 "{}/_fakecloud/elbv2/access-logs/flush",
1988 self.fc.base_url
1989 ))
1990 .send()
1991 .await?;
1992 FakeCloud::parse(resp).await
1993 }
1994}
1995
1996pub struct GlueClient<'a> {
1999 fc: &'a FakeCloud,
2000}
2001
2002impl GlueClient<'_> {
2003 pub async fn get_jobs(&self) -> Result<GlueJobsResponse, Error> {
2005 let resp = self
2006 .fc
2007 .client
2008 .get(format!("{}/_fakecloud/glue/jobs", self.fc.base_url))
2009 .send()
2010 .await?;
2011 FakeCloud::parse(resp).await
2012 }
2013
2014 pub async fn get_job_runs(&self, job_name: Option<&str>) -> Result<GlueJobRunsResponse, Error> {
2017 fn encode(s: &str) -> String {
2018 let mut out = String::with_capacity(s.len());
2019 for b in s.bytes() {
2020 match b {
2021 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
2022 out.push(b as char);
2023 }
2024 _ => out.push_str(&format!("%{:02X}", b)),
2025 }
2026 }
2027 out
2028 }
2029 let mut url = format!("{}/_fakecloud/glue/job-runs", self.fc.base_url);
2030 if let Some(name) = job_name {
2031 url.push_str("?job_name=");
2032 url.push_str(&encode(name));
2033 }
2034 let resp = self.fc.client.get(url).send().await?;
2035 FakeCloud::parse(resp).await
2036 }
2037
2038 pub async fn get_crawlers(&self) -> Result<GlueCrawlersResponse, Error> {
2040 let resp = self
2041 .fc
2042 .client
2043 .get(format!("{}/_fakecloud/glue/crawlers", self.fc.base_url))
2044 .send()
2045 .await?;
2046 FakeCloud::parse(resp).await
2047 }
2048}
2049
2050pub struct CloudWatchClient<'a> {
2053 fc: &'a FakeCloud,
2054}
2055
2056impl CloudWatchClient<'_> {
2057 pub async fn get_alarms(&self) -> Result<CloudWatchAlarmsResponse, Error> {
2060 let resp = self
2061 .fc
2062 .client
2063 .get(format!("{}/_fakecloud/cloudwatch/alarms", self.fc.base_url))
2064 .send()
2065 .await?;
2066 FakeCloud::parse(resp).await
2067 }
2068
2069 pub async fn get_metrics(&self) -> Result<CloudWatchMetricsResponse, Error> {
2072 let resp = self
2073 .fc
2074 .client
2075 .get(format!(
2076 "{}/_fakecloud/cloudwatch/metrics",
2077 self.fc.base_url
2078 ))
2079 .send()
2080 .await?;
2081 FakeCloud::parse(resp).await
2082 }
2083}
2084
2085pub struct FirehoseClient<'a> {
2088 fc: &'a FakeCloud,
2089}
2090
2091impl FirehoseClient<'_> {
2092 pub async fn get_delivery_streams(&self) -> Result<FirehoseDeliveryStreamsResponse, Error> {
2096 let resp = self
2097 .fc
2098 .client
2099 .get(format!(
2100 "{}/_fakecloud/firehose/delivery-streams",
2101 self.fc.base_url
2102 ))
2103 .send()
2104 .await?;
2105 FakeCloud::parse(resp).await
2106 }
2107}
2108
2109pub struct LogsClient<'a> {
2112 fc: &'a FakeCloud,
2113}
2114
2115impl LogsClient<'_> {
2116 pub async fn inject_anomaly(
2120 &self,
2121 req: &LogsAnomalyInjectRequest,
2122 ) -> Result<LogsAnomalyInjectResponse, Error> {
2123 let resp = self
2124 .fc
2125 .client
2126 .post(format!(
2127 "{}/_fakecloud/logs/anomalies/inject",
2128 self.fc.base_url
2129 ))
2130 .json(req)
2131 .send()
2132 .await?;
2133 FakeCloud::parse(resp).await
2134 }
2135
2136 pub async fn get_delivery_config(&self) -> Result<LogsDeliveryConfigResponse, Error> {
2140 let resp = self
2141 .fc
2142 .client
2143 .get(format!(
2144 "{}/_fakecloud/logs/delivery-config",
2145 self.fc.base_url
2146 ))
2147 .send()
2148 .await?;
2149 FakeCloud::parse(resp).await
2150 }
2151
2152 pub async fn get_field_indexes(
2156 &self,
2157 log_group_name: &str,
2158 ) -> Result<LogsFieldIndexesResponse, Error> {
2159 let resp = self
2160 .fc
2161 .client
2162 .get(format!(
2163 "{}/_fakecloud/logs/field-indexes/{}",
2164 self.fc.base_url,
2165 utf8_percent_encode(log_group_name, NON_ALPHANUMERIC)
2166 ))
2167 .send()
2168 .await?;
2169 FakeCloud::parse(resp).await
2170 }
2171}
2172
2173impl Route53Client<'_> {
2174 pub async fn set_health_check_status(
2179 &self,
2180 id: &str,
2181 req: &Route53HealthCheckStatusRequest,
2182 ) -> Result<(), Error> {
2183 let resp = self
2184 .fc
2185 .client
2186 .post(format!(
2187 "{}/_fakecloud/route53/health-checks/{}/status",
2188 self.fc.base_url, id
2189 ))
2190 .json(req)
2191 .send()
2192 .await?;
2193 if !resp.status().is_success() {
2194 let status = resp.status().as_u16();
2195 let body = resp.text().await.unwrap_or_default();
2196 return Err(Error::Api { status, body });
2197 }
2198 Ok(())
2199 }
2200}
2201
2202pub struct SchedulerClient<'a> {
2205 fc: &'a FakeCloud,
2206}
2207
2208impl SchedulerClient<'_> {
2209 pub async fn get_schedules(&self) -> Result<SchedulerSchedulesResponse, Error> {
2212 let resp = self
2213 .fc
2214 .client
2215 .get(format!(
2216 "{}/_fakecloud/scheduler/schedules",
2217 self.fc.base_url
2218 ))
2219 .send()
2220 .await?;
2221 FakeCloud::parse(resp).await
2222 }
2223
2224 pub async fn fire_schedule(
2228 &self,
2229 group: &str,
2230 name: &str,
2231 ) -> Result<FireScheduleResponse, Error> {
2232 let resp = self
2233 .fc
2234 .client
2235 .post(format!(
2236 "{}/_fakecloud/scheduler/fire/{}/{}",
2237 self.fc.base_url, group, name
2238 ))
2239 .send()
2240 .await?;
2241 FakeCloud::parse(resp).await
2242 }
2243}
2244
2245pub struct SsmClient<'a> {
2248 fc: &'a FakeCloud,
2249}
2250
2251impl SsmClient<'_> {
2252 pub async fn set_command_status(
2255 &self,
2256 command_id: &str,
2257 req: &SetSsmCommandStatusRequest,
2258 ) -> Result<SetSsmCommandStatusResponse, Error> {
2259 let resp = self
2260 .fc
2261 .client
2262 .post(format!(
2263 "{}/_fakecloud/ssm/commands/{}/status",
2264 self.fc.base_url, command_id
2265 ))
2266 .json(req)
2267 .send()
2268 .await?;
2269 FakeCloud::parse(resp).await
2270 }
2271
2272 pub async fn fail_command(
2276 &self,
2277 command_id: &str,
2278 req: Option<&FailSsmCommandRequest>,
2279 ) -> Result<FailSsmCommandResponse, Error> {
2280 let mut builder = self.fc.client.post(format!(
2281 "{}/_fakecloud/ssm/commands/{}/fail",
2282 self.fc.base_url, command_id
2283 ));
2284 if let Some(body) = req {
2285 builder = builder.json(body);
2286 }
2287 let resp = builder.send().await?;
2288 FakeCloud::parse(resp).await
2289 }
2290
2291 pub async fn parameter_policy_events(
2294 &self,
2295 account_id: Option<&str>,
2296 ) -> Result<SsmParameterPolicyEventsResponse, Error> {
2297 let mut url = format!(
2298 "{}/_fakecloud/ssm/parameter-policy-events",
2299 self.fc.base_url
2300 );
2301 if let Some(id) = account_id {
2302 url.push_str("?accountId=");
2303 url.push_str(id);
2304 }
2305 let resp = self.fc.client.get(url).send().await?;
2306 FakeCloud::parse(resp).await
2307 }
2308
2309 pub async fn inject_session(
2313 &self,
2314 req: &InjectSsmSessionRequest,
2315 ) -> Result<InjectSsmSessionResponse, Error> {
2316 let resp = self
2317 .fc
2318 .client
2319 .post(format!(
2320 "{}/_fakecloud/ssm/sessions/inject",
2321 self.fc.base_url
2322 ))
2323 .json(req)
2324 .send()
2325 .await?;
2326 FakeCloud::parse(resp).await
2327 }
2328}
2329
2330pub struct KmsClient<'a> {
2333 fc: &'a FakeCloud,
2334}
2335
2336impl KmsClient<'_> {
2337 pub async fn usage(&self) -> Result<KmsUsageResponse, Error> {
2339 let resp = self
2340 .fc
2341 .client
2342 .get(format!("{}/_fakecloud/kms/usage", self.fc.base_url))
2343 .send()
2344 .await?;
2345 FakeCloud::parse(resp).await
2346 }
2347}
2348
2349pub struct WafV2Client<'a> {
2352 fc: &'a FakeCloud,
2353}
2354
2355impl WafV2Client<'_> {
2356 pub async fn evaluate(&self, body: &serde_json::Value) -> Result<serde_json::Value, Error> {
2361 let resp = self
2362 .fc
2363 .client
2364 .post(format!("{}/_fakecloud/wafv2/evaluate", self.fc.base_url))
2365 .json(body)
2366 .send()
2367 .await?;
2368 FakeCloud::parse(resp).await
2369 }
2370}
2371
2372pub struct CloudFrontClient<'a> {
2375 fc: &'a FakeCloud,
2376}
2377
2378impl CloudFrontClient<'_> {
2379 pub async fn set_distribution_status(
2383 &self,
2384 distribution_id: &str,
2385 req: &CloudFrontDistributionStatusRequest,
2386 ) -> Result<(), Error> {
2387 let resp = self
2388 .fc
2389 .client
2390 .post(format!(
2391 "{}/_fakecloud/cloudfront/distributions/{}/status",
2392 self.fc.base_url, distribution_id
2393 ))
2394 .json(req)
2395 .send()
2396 .await?;
2397 let status = resp.status().as_u16();
2398 if !resp.status().is_success() {
2399 let body = resp.text().await.unwrap_or_default();
2400 return Err(Error::Api { status, body });
2401 }
2402 Ok(())
2403 }
2404}
2405
2406impl Elbv2Client<'_> {
2407 pub async fn waf_counts(&self) -> Result<Elbv2WafCountsResponse, Error> {
2411 let resp = self
2412 .fc
2413 .client
2414 .get(format!("{}/_fakecloud/elbv2/waf-counts", self.fc.base_url))
2415 .send()
2416 .await?;
2417 FakeCloud::parse(resp).await
2418 }
2419}