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 elasticache(&self) -> ElastiCacheClient<'_> {
133 ElastiCacheClient { fc: self }
134 }
135
136 pub fn apigatewayv2(&self) -> ApiGatewayV2Client<'_> {
137 ApiGatewayV2Client { fc: self }
138 }
139
140 pub fn stepfunctions(&self) -> StepFunctionsClient<'_> {
141 StepFunctionsClient { fc: self }
142 }
143
144 pub fn bedrock(&self) -> BedrockClient<'_> {
145 BedrockClient { fc: self }
146 }
147
148 pub fn bedrock_agent(&self) -> BedrockAgentClient<'_> {
149 BedrockAgentClient { fc: self }
150 }
151
152 pub fn bedrock_agent_runtime(&self) -> BedrockAgentRuntimeClient<'_> {
153 BedrockAgentRuntimeClient { fc: self }
154 }
155
156 pub fn ecs(&self) -> EcsClient<'_> {
157 EcsClient { fc: self }
158 }
159
160 pub fn application_autoscaling(&self) -> ApplicationAutoScalingClient<'_> {
161 ApplicationAutoScalingClient { fc: self }
162 }
163
164 pub fn athena(&self) -> AthenaClient<'_> {
165 AthenaClient { fc: self }
166 }
167
168 pub fn organizations(&self) -> OrganizationsClient<'_> {
169 OrganizationsClient { fc: self }
170 }
171
172 pub fn acm(&self) -> AcmClient<'_> {
173 AcmClient { fc: self }
174 }
175
176 pub fn ecr(&self) -> EcrClient<'_> {
177 EcrClient { fc: self }
178 }
179
180 pub fn elbv2(&self) -> Elbv2Client<'_> {
181 Elbv2Client { fc: self }
182 }
183
184 pub fn glue(&self) -> GlueClient<'_> {
185 GlueClient { fc: self }
186 }
187
188 pub fn cloudwatch(&self) -> CloudWatchClient<'_> {
189 CloudWatchClient { fc: self }
190 }
191
192 pub fn firehose(&self) -> FirehoseClient<'_> {
193 FirehoseClient { fc: self }
194 }
195
196 pub fn logs(&self) -> LogsClient<'_> {
197 LogsClient { fc: self }
198 }
199
200 pub fn route53(&self) -> Route53Client<'_> {
201 Route53Client { fc: self }
202 }
203
204 pub fn scheduler(&self) -> SchedulerClient<'_> {
205 SchedulerClient { fc: self }
206 }
207
208 pub fn ssm(&self) -> SsmClient<'_> {
209 SsmClient { fc: self }
210 }
211
212 pub fn kms(&self) -> KmsClient<'_> {
213 KmsClient { fc: self }
214 }
215
216 pub fn wafv2(&self) -> WafV2Client<'_> {
217 WafV2Client { fc: self }
218 }
219
220 pub fn cloudfront(&self) -> CloudFrontClient<'_> {
221 CloudFrontClient { fc: self }
222 }
223
224 async fn parse<T: serde::de::DeserializeOwned>(resp: reqwest::Response) -> Result<T, Error> {
227 let status = resp.status().as_u16();
228 if !resp.status().is_success() {
229 let body = resp.text().await.unwrap_or_default();
230 return Err(Error::Api { status, body });
231 }
232 Ok(resp.json::<T>().await?)
233 }
234}
235
236pub struct RdsClient<'a> {
239 fc: &'a FakeCloud,
240}
241
242impl RdsClient<'_> {
243 pub async fn get_instances(&self) -> Result<RdsInstancesResponse, Error> {
245 let resp = self
246 .fc
247 .client
248 .get(format!("{}/_fakecloud/rds/instances", self.fc.base_url))
249 .send()
250 .await?;
251 FakeCloud::parse(resp).await
252 }
253
254 pub async fn lambda_invoke(
259 &self,
260 req: &RdsLambdaInvokeRequest,
261 ) -> Result<RdsLambdaInvokeResponse, Error> {
262 let resp = self
263 .fc
264 .client
265 .post(format!("{}/_fakecloud/rds/lambda-invoke", self.fc.base_url))
266 .json(req)
267 .send()
268 .await?;
269 let status = resp.status().as_u16();
270 if status == 502 || resp.status().is_success() {
274 return Ok(resp.json::<RdsLambdaInvokeResponse>().await?);
275 }
276 let body = resp.text().await.unwrap_or_default();
277 Err(Error::Api { status, body })
278 }
279
280 pub async fn s3_import(&self, req: &RdsS3ImportRequest) -> Result<RdsS3ImportResponse, Error> {
283 let resp = self
284 .fc
285 .client
286 .post(format!("{}/_fakecloud/rds/s3-import", self.fc.base_url))
287 .json(req)
288 .send()
289 .await?;
290 FakeCloud::parse(resp).await
291 }
292
293 pub async fn s3_export(&self, req: &RdsS3ExportRequest) -> Result<RdsS3ExportResponse, Error> {
296 let resp = self
297 .fc
298 .client
299 .post(format!("{}/_fakecloud/rds/s3-export", self.fc.base_url))
300 .json(req)
301 .send()
302 .await?;
303 FakeCloud::parse(resp).await
304 }
305}
306
307pub struct ElastiCacheClient<'a> {
310 fc: &'a FakeCloud,
311}
312
313impl ElastiCacheClient<'_> {
314 pub async fn get_clusters(&self) -> Result<ElastiCacheClustersResponse, Error> {
316 let resp = self
317 .fc
318 .client
319 .get(format!(
320 "{}/_fakecloud/elasticache/clusters",
321 self.fc.base_url
322 ))
323 .send()
324 .await?;
325 FakeCloud::parse(resp).await
326 }
327
328 pub async fn get_replication_groups(
330 &self,
331 ) -> Result<ElastiCacheReplicationGroupsResponse, Error> {
332 let resp = self
333 .fc
334 .client
335 .get(format!(
336 "{}/_fakecloud/elasticache/replication-groups",
337 self.fc.base_url
338 ))
339 .send()
340 .await?;
341 FakeCloud::parse(resp).await
342 }
343
344 pub async fn get_serverless_caches(
346 &self,
347 ) -> Result<ElastiCacheServerlessCachesResponse, Error> {
348 let resp = self
349 .fc
350 .client
351 .get(format!(
352 "{}/_fakecloud/elasticache/serverless-caches",
353 self.fc.base_url
354 ))
355 .send()
356 .await?;
357 FakeCloud::parse(resp).await
358 }
359
360 pub async fn get_acls(&self) -> Result<ElastiCacheAclsResponse, Error> {
363 let resp = self
364 .fc
365 .client
366 .get(format!("{}/_fakecloud/elasticache/acls", self.fc.base_url))
367 .send()
368 .await?;
369 FakeCloud::parse(resp).await
370 }
371}
372
373pub struct LambdaClient<'a> {
376 fc: &'a FakeCloud,
377}
378
379impl LambdaClient<'_> {
380 pub async fn get_invocations(&self) -> Result<LambdaInvocationsResponse, Error> {
382 let resp = self
383 .fc
384 .client
385 .get(format!(
386 "{}/_fakecloud/lambda/invocations",
387 self.fc.base_url
388 ))
389 .send()
390 .await?;
391 FakeCloud::parse(resp).await
392 }
393
394 pub async fn get_warm_containers(&self) -> Result<WarmContainersResponse, Error> {
396 let resp = self
397 .fc
398 .client
399 .get(format!(
400 "{}/_fakecloud/lambda/warm-containers",
401 self.fc.base_url
402 ))
403 .send()
404 .await?;
405 FakeCloud::parse(resp).await
406 }
407
408 pub async fn evict_container(
410 &self,
411 function_name: &str,
412 ) -> Result<EvictContainerResponse, Error> {
413 let resp = self
414 .fc
415 .client
416 .post(format!(
417 "{}/_fakecloud/lambda/{}/evict-container",
418 self.fc.base_url, function_name
419 ))
420 .send()
421 .await?;
422 FakeCloud::parse(resp).await
423 }
424
425 pub async fn download_function_code(
429 &self,
430 account_id: &str,
431 function_name: &str,
432 qualifier_or_latest: &str,
433 ) -> Result<Vec<u8>, Error> {
434 let resp = self
435 .fc
436 .client
437 .get(format!(
438 "{}/_fakecloud/lambda/function-code/{}/{}/{}.zip",
439 self.fc.base_url, account_id, function_name, qualifier_or_latest
440 ))
441 .send()
442 .await?;
443 let status = resp.status().as_u16();
444 if !resp.status().is_success() {
445 let body = resp.text().await.unwrap_or_default();
446 return Err(Error::Api { status, body });
447 }
448 Ok(resp.bytes().await?.to_vec())
449 }
450
451 pub async fn download_layer_content(
453 &self,
454 account_id: &str,
455 layer_name: &str,
456 version: i64,
457 ) -> Result<Vec<u8>, Error> {
458 let resp = self
459 .fc
460 .client
461 .get(format!(
462 "{}/_fakecloud/lambda/layer-content/{}/{}/{}.zip",
463 self.fc.base_url, account_id, layer_name, version
464 ))
465 .send()
466 .await?;
467 let status = resp.status().as_u16();
468 if !resp.status().is_success() {
469 let body = resp.text().await.unwrap_or_default();
470 return Err(Error::Api { status, body });
471 }
472 Ok(resp.bytes().await?.to_vec())
473 }
474}
475
476pub struct SesClient<'a> {
479 fc: &'a FakeCloud,
480}
481
482impl SesClient<'_> {
483 pub async fn get_emails(&self) -> Result<SesEmailsResponse, Error> {
485 let resp = self
486 .fc
487 .client
488 .get(format!("{}/_fakecloud/ses/emails", self.fc.base_url))
489 .send()
490 .await?;
491 FakeCloud::parse(resp).await
492 }
493
494 pub async fn simulate_inbound(
496 &self,
497 req: &InboundEmailRequest,
498 ) -> Result<InboundEmailResponse, Error> {
499 let resp = self
500 .fc
501 .client
502 .post(format!("{}/_fakecloud/ses/inbound", self.fc.base_url))
503 .json(req)
504 .send()
505 .await?;
506 FakeCloud::parse(resp).await
507 }
508
509 pub async fn get_metrics(&self) -> Result<SesMetricsResponse, Error> {
512 let resp = self
513 .fc
514 .client
515 .get(format!("{}/_fakecloud/ses/metrics", self.fc.base_url))
516 .send()
517 .await?;
518 FakeCloud::parse(resp).await
519 }
520
521 pub async fn get_bounces(&self) -> Result<SesBouncesResponse, Error> {
523 let resp = self
524 .fc
525 .client
526 .get(format!("{}/_fakecloud/ses/bounces", self.fc.base_url))
527 .send()
528 .await?;
529 FakeCloud::parse(resp).await
530 }
531
532 pub async fn set_sandbox(&self, sandbox: bool) -> Result<SesSandboxResponse, Error> {
536 let resp = self
537 .fc
538 .client
539 .post(format!(
540 "{}/_fakecloud/ses/account/sandbox",
541 self.fc.base_url
542 ))
543 .json(&SesSandboxRequest { sandbox })
544 .send()
545 .await?;
546 FakeCloud::parse(resp).await
547 }
548
549 pub async fn get_event_destination_deliveries(
552 &self,
553 ) -> Result<SesEventDestinationDeliveriesResponse, Error> {
554 let resp = self
555 .fc
556 .client
557 .get(format!(
558 "{}/_fakecloud/ses/event-destinations/deliveries",
559 self.fc.base_url
560 ))
561 .send()
562 .await?;
563 FakeCloud::parse(resp).await
564 }
565
566 pub async fn get_dkim_public_key(
569 &self,
570 identity: &str,
571 ) -> Result<SesDkimPublicKeyResponse, Error> {
572 let resp = self
573 .fc
574 .client
575 .get(format!(
576 "{}/_fakecloud/ses/identities/{}/dkim-public-key",
577 self.fc.base_url, identity
578 ))
579 .send()
580 .await?;
581 FakeCloud::parse(resp).await
582 }
583
584 pub async fn set_mail_from_status(
587 &self,
588 identity: &str,
589 status: &str,
590 ) -> Result<SesMailFromStatusResponse, Error> {
591 let resp = self
592 .fc
593 .client
594 .post(format!(
595 "{}/_fakecloud/ses/identities/{}/mail-from-status",
596 self.fc.base_url, identity
597 ))
598 .json(&SesMailFromStatusRequest {
599 status: status.to_string(),
600 })
601 .send()
602 .await?;
603 FakeCloud::parse(resp).await
604 }
605
606 pub async fn get_message_insights(
609 &self,
610 message_id: &str,
611 ) -> Result<SesMessageInsightsResponse, Error> {
612 let resp = self
613 .fc
614 .client
615 .get(format!(
616 "{}/_fakecloud/ses/messages/{}/insights",
617 self.fc.base_url, message_id
618 ))
619 .send()
620 .await?;
621 FakeCloud::parse(resp).await
622 }
623
624 pub async fn get_smtp_submissions(&self) -> Result<SesSmtpSubmissionsResponse, Error> {
626 let resp = self
627 .fc
628 .client
629 .get(format!(
630 "{}/_fakecloud/ses/smtp/submissions",
631 self.fc.base_url
632 ))
633 .send()
634 .await?;
635 FakeCloud::parse(resp).await
636 }
637}
638
639pub struct SnsClient<'a> {
642 fc: &'a FakeCloud,
643}
644
645impl SnsClient<'_> {
646 pub async fn get_messages(&self) -> Result<SnsMessagesResponse, Error> {
648 let resp = self
649 .fc
650 .client
651 .get(format!("{}/_fakecloud/sns/messages", self.fc.base_url))
652 .send()
653 .await?;
654 FakeCloud::parse(resp).await
655 }
656
657 pub async fn get_pending_confirmations(&self) -> Result<PendingConfirmationsResponse, Error> {
659 let resp = self
660 .fc
661 .client
662 .get(format!(
663 "{}/_fakecloud/sns/pending-confirmations",
664 self.fc.base_url
665 ))
666 .send()
667 .await?;
668 FakeCloud::parse(resp).await
669 }
670
671 pub async fn confirm_subscription(
673 &self,
674 req: &ConfirmSubscriptionRequest,
675 ) -> Result<ConfirmSubscriptionResponse, Error> {
676 let resp = self
677 .fc
678 .client
679 .post(format!(
680 "{}/_fakecloud/sns/confirm-subscription",
681 self.fc.base_url
682 ))
683 .json(req)
684 .send()
685 .await?;
686 FakeCloud::parse(resp).await
687 }
688
689 pub async fn cert_pem(&self) -> Result<String, Error> {
694 let resp = self
695 .fc
696 .client
697 .get(format!("{}/_fakecloud/sns/cert.pem", self.fc.base_url))
698 .send()
699 .await?;
700 let status = resp.status().as_u16();
701 if !resp.status().is_success() {
702 let body = resp.text().await.unwrap_or_default();
703 return Err(Error::Api { status, body });
704 }
705 Ok(resp.text().await?)
706 }
707
708 pub async fn sms(&self) -> Result<SnsSmsResponse, Error> {
710 let resp = self
711 .fc
712 .client
713 .get(format!("{}/_fakecloud/sns/sms", self.fc.base_url))
714 .send()
715 .await?;
716 FakeCloud::parse(resp).await
717 }
718}
719
720pub struct SqsClient<'a> {
723 fc: &'a FakeCloud,
724}
725
726impl SqsClient<'_> {
727 pub async fn get_messages(&self) -> Result<SqsMessagesResponse, Error> {
729 let resp = self
730 .fc
731 .client
732 .get(format!("{}/_fakecloud/sqs/messages", self.fc.base_url))
733 .send()
734 .await?;
735 FakeCloud::parse(resp).await
736 }
737
738 pub async fn tick_expiration(&self) -> Result<ExpirationTickResponse, Error> {
740 let resp = self
741 .fc
742 .client
743 .post(format!(
744 "{}/_fakecloud/sqs/expiration-processor/tick",
745 self.fc.base_url
746 ))
747 .send()
748 .await?;
749 FakeCloud::parse(resp).await
750 }
751
752 pub async fn force_dlq(&self, queue_name: &str) -> Result<ForceDlqResponse, Error> {
754 let resp = self
755 .fc
756 .client
757 .post(format!(
758 "{}/_fakecloud/sqs/{}/force-dlq",
759 self.fc.base_url, queue_name
760 ))
761 .send()
762 .await?;
763 FakeCloud::parse(resp).await
764 }
765}
766
767pub struct ApplicationAutoScalingClient<'a> {
770 fc: &'a FakeCloud,
771}
772
773impl ApplicationAutoScalingClient<'_> {
774 pub async fn tick(&self) -> Result<AppAsTickResponse, Error> {
779 let resp = self
780 .fc
781 .client
782 .post(format!(
783 "{}/_fakecloud/application-autoscaling/tick",
784 self.fc.base_url
785 ))
786 .send()
787 .await?;
788 FakeCloud::parse(resp).await
789 }
790
791 pub async fn scheduled_tick(&self) -> Result<AppAsScheduledTickResponse, Error> {
796 let resp = self
797 .fc
798 .client
799 .post(format!(
800 "{}/_fakecloud/application-autoscaling/scheduled-tick",
801 self.fc.base_url
802 ))
803 .send()
804 .await?;
805 FakeCloud::parse(resp).await
806 }
807}
808
809pub struct EventsClient<'a> {
812 fc: &'a FakeCloud,
813}
814
815impl EventsClient<'_> {
816 pub async fn get_history(&self) -> Result<EventHistoryResponse, Error> {
818 let resp = self
819 .fc
820 .client
821 .get(format!("{}/_fakecloud/events/history", self.fc.base_url))
822 .send()
823 .await?;
824 FakeCloud::parse(resp).await
825 }
826
827 pub async fn fire_rule(&self, req: &FireRuleRequest) -> Result<FireRuleResponse, Error> {
829 let resp = self
830 .fc
831 .client
832 .post(format!("{}/_fakecloud/events/fire-rule", self.fc.base_url))
833 .json(req)
834 .send()
835 .await?;
836 FakeCloud::parse(resp).await
837 }
838}
839
840pub struct S3Client<'a> {
843 fc: &'a FakeCloud,
844}
845
846impl S3Client<'_> {
847 pub async fn get_notifications(&self) -> Result<S3NotificationsResponse, Error> {
849 let resp = self
850 .fc
851 .client
852 .get(format!("{}/_fakecloud/s3/notifications", self.fc.base_url))
853 .send()
854 .await?;
855 FakeCloud::parse(resp).await
856 }
857
858 pub async fn tick_lifecycle(&self) -> Result<LifecycleTickResponse, Error> {
860 let resp = self
861 .fc
862 .client
863 .post(format!(
864 "{}/_fakecloud/s3/lifecycle-processor/tick",
865 self.fc.base_url
866 ))
867 .send()
868 .await?;
869 FakeCloud::parse(resp).await
870 }
871
872 pub async fn get_access_points(&self) -> Result<S3AccessPointsResponse, Error> {
874 let resp = self
875 .fc
876 .client
877 .get(format!("{}/_fakecloud/s3/access-points", self.fc.base_url))
878 .send()
879 .await?;
880 FakeCloud::parse(resp).await
881 }
882
883 pub async fn get_object_lambda_responses(
885 &self,
886 ) -> Result<S3ObjectLambdaResponsesResponse, Error> {
887 let resp = self
888 .fc
889 .client
890 .get(format!(
891 "{}/_fakecloud/s3/object-lambda-responses",
892 self.fc.base_url
893 ))
894 .send()
895 .await?;
896 FakeCloud::parse(resp).await
897 }
898}
899
900pub struct DynamoDbClient<'a> {
903 fc: &'a FakeCloud,
904}
905
906impl DynamoDbClient<'_> {
907 pub async fn tick_ttl(&self) -> Result<TtlTickResponse, Error> {
909 let resp = self
910 .fc
911 .client
912 .post(format!(
913 "{}/_fakecloud/dynamodb/ttl-processor/tick",
914 self.fc.base_url
915 ))
916 .send()
917 .await?;
918 FakeCloud::parse(resp).await
919 }
920}
921
922pub struct SecretsManagerClient<'a> {
925 fc: &'a FakeCloud,
926}
927
928impl SecretsManagerClient<'_> {
929 pub async fn tick_rotation(&self) -> Result<RotationTickResponse, Error> {
931 let resp = self
932 .fc
933 .client
934 .post(format!(
935 "{}/_fakecloud/secretsmanager/rotation-scheduler/tick",
936 self.fc.base_url
937 ))
938 .send()
939 .await?;
940 FakeCloud::parse(resp).await
941 }
942}
943
944pub struct CognitoClient<'a> {
947 fc: &'a FakeCloud,
948}
949
950impl CognitoClient<'_> {
951 pub async fn get_user_codes(
953 &self,
954 pool_id: &str,
955 username: &str,
956 ) -> Result<UserConfirmationCodes, Error> {
957 let resp = self
958 .fc
959 .client
960 .get(format!(
961 "{}/_fakecloud/cognito/confirmation-codes/{}/{}",
962 self.fc.base_url, pool_id, username
963 ))
964 .send()
965 .await?;
966 FakeCloud::parse(resp).await
967 }
968
969 pub async fn get_confirmation_codes(&self) -> Result<ConfirmationCodesResponse, Error> {
971 let resp = self
972 .fc
973 .client
974 .get(format!(
975 "{}/_fakecloud/cognito/confirmation-codes",
976 self.fc.base_url
977 ))
978 .send()
979 .await?;
980 FakeCloud::parse(resp).await
981 }
982
983 pub async fn confirm_user(
985 &self,
986 req: &ConfirmUserRequest,
987 ) -> Result<ConfirmUserResponse, Error> {
988 let resp = self
989 .fc
990 .client
991 .post(format!(
992 "{}/_fakecloud/cognito/confirm-user",
993 self.fc.base_url
994 ))
995 .json(req)
996 .send()
997 .await?;
998 let status = resp.status().as_u16();
999 let body: ConfirmUserResponse = resp.json().await?;
1000 if status >= 400 {
1001 return Err(Error::Api {
1002 status,
1003 body: body.error.unwrap_or_default(),
1004 });
1005 }
1006 Ok(body)
1007 }
1008
1009 pub async fn get_tokens(&self) -> Result<TokensResponse, Error> {
1011 let resp = self
1012 .fc
1013 .client
1014 .get(format!("{}/_fakecloud/cognito/tokens", self.fc.base_url))
1015 .send()
1016 .await?;
1017 FakeCloud::parse(resp).await
1018 }
1019
1020 pub async fn expire_tokens(
1022 &self,
1023 req: &ExpireTokensRequest,
1024 ) -> Result<ExpireTokensResponse, Error> {
1025 let resp = self
1026 .fc
1027 .client
1028 .post(format!(
1029 "{}/_fakecloud/cognito/expire-tokens",
1030 self.fc.base_url
1031 ))
1032 .json(req)
1033 .send()
1034 .await?;
1035 FakeCloud::parse(resp).await
1036 }
1037
1038 pub async fn get_auth_events(&self) -> Result<AuthEventsResponse, Error> {
1040 let resp = self
1041 .fc
1042 .client
1043 .get(format!(
1044 "{}/_fakecloud/cognito/auth-events",
1045 self.fc.base_url
1046 ))
1047 .send()
1048 .await?;
1049 FakeCloud::parse(resp).await
1050 }
1051
1052 pub async fn get_pre_token_gen_invocations(
1058 &self,
1059 ) -> Result<PreTokenGenInvocationsResponse, Error> {
1060 let resp = self
1061 .fc
1062 .client
1063 .get(format!(
1064 "{}/_fakecloud/cognito/pretokengen/invocations",
1065 self.fc.base_url
1066 ))
1067 .send()
1068 .await?;
1069 FakeCloud::parse(resp).await
1070 }
1071
1072 pub async fn mint_authorization_code(
1076 &self,
1077 req: &MintAuthorizationCodeRequest,
1078 ) -> Result<MintAuthorizationCodeResponse, Error> {
1079 let resp = self
1080 .fc
1081 .client
1082 .post(format!(
1083 "{}/_fakecloud/cognito/authorization-codes",
1084 self.fc.base_url
1085 ))
1086 .json(req)
1087 .send()
1088 .await?;
1089 FakeCloud::parse(resp).await
1090 }
1091
1092 pub async fn set_compromised_passwords(
1097 &self,
1098 req: &CognitoCompromisedPasswordsRequest,
1099 ) -> Result<CompromisedPasswordsResponse, Error> {
1100 let resp = self
1101 .fc
1102 .client
1103 .post(format!(
1104 "{}/_fakecloud/cognito/compromised-passwords",
1105 self.fc.base_url
1106 ))
1107 .json(req)
1108 .send()
1109 .await?;
1110 FakeCloud::parse(resp).await
1111 }
1112
1113 pub async fn get_webauthn_credentials(&self) -> Result<WebAuthnCredentialsResponse, Error> {
1115 let resp = self
1116 .fc
1117 .client
1118 .get(format!(
1119 "{}/_fakecloud/cognito/webauthn-credentials",
1120 self.fc.base_url
1121 ))
1122 .send()
1123 .await?;
1124 FakeCloud::parse(resp).await
1125 }
1126}
1127
1128pub struct ApiGatewayV2Client<'a> {
1131 fc: &'a FakeCloud,
1132}
1133
1134impl ApiGatewayV2Client<'_> {
1135 pub async fn get_requests(&self) -> Result<ApiGatewayV2RequestsResponse, Error> {
1137 let resp = self
1138 .fc
1139 .client
1140 .get(format!(
1141 "{}/_fakecloud/apigatewayv2/requests",
1142 self.fc.base_url
1143 ))
1144 .send()
1145 .await?;
1146 FakeCloud::parse(resp).await
1147 }
1148
1149 pub async fn connections(&self) -> Result<ApiGatewayV2ConnectionsResponse, Error> {
1152 let resp = self
1153 .fc
1154 .client
1155 .get(format!(
1156 "{}/_fakecloud/apigatewayv2/connections",
1157 self.fc.base_url
1158 ))
1159 .send()
1160 .await?;
1161 FakeCloud::parse(resp).await
1162 }
1163
1164 pub async fn mtls_info(&self, name: &str) -> Result<serde_json::Value, Error> {
1168 let resp = self
1169 .fc
1170 .client
1171 .get(format!(
1172 "{}/_fakecloud/apigatewayv2/domain-names/{}/mtls-info",
1173 self.fc.base_url, name
1174 ))
1175 .send()
1176 .await?;
1177 FakeCloud::parse(resp).await
1178 }
1179
1180 pub fn ws_url(&self, api_id: &str, stage: Option<&str>) -> String {
1184 let base = self
1185 .fc
1186 .base_url
1187 .replacen("https://", "wss://", 1)
1188 .replacen("http://", "ws://", 1);
1189 let url = reqwest::Url::parse(&format!("{}/_fakecloud/apigatewayv2/ws/{}", base, api_id))
1193 .expect("base url + api id form a valid URL");
1194 match stage {
1195 Some(s) => {
1196 let mut u = url;
1197 u.query_pairs_mut().append_pair("stage", s);
1198 u.to_string()
1199 }
1200 None => url.to_string(),
1201 }
1202 }
1203}
1204
1205pub struct StepFunctionsClient<'a> {
1208 fc: &'a FakeCloud,
1209}
1210
1211impl StepFunctionsClient<'_> {
1212 pub async fn get_executions(&self) -> Result<StepFunctionsExecutionsResponse, Error> {
1214 let resp = self
1215 .fc
1216 .client
1217 .get(format!(
1218 "{}/_fakecloud/stepfunctions/executions",
1219 self.fc.base_url
1220 ))
1221 .send()
1222 .await?;
1223 FakeCloud::parse(resp).await
1224 }
1225
1226 pub async fn get_sync_executions(&self) -> Result<StepFunctionsSyncExecutionsResponse, Error> {
1230 let resp = self
1231 .fc
1232 .client
1233 .get(format!(
1234 "{}/_fakecloud/stepfunctions/sync-executions",
1235 self.fc.base_url
1236 ))
1237 .send()
1238 .await?;
1239 FakeCloud::parse(resp).await
1240 }
1241
1242 pub async fn enqueue_activity_task(
1250 &self,
1251 req: &SfnEnqueueActivityTaskRequest,
1252 ) -> Result<SfnEnqueueActivityTaskResponse, Error> {
1253 let resp = self
1254 .fc
1255 .client
1256 .post(format!(
1257 "{}/_fakecloud/stepfunctions/enqueue-activity-task",
1258 self.fc.base_url
1259 ))
1260 .json(req)
1261 .send()
1262 .await?;
1263 FakeCloud::parse(resp).await
1264 }
1265
1266 pub async fn get_execution_tree(
1267 &self,
1268 execution_arn: &str,
1269 ) -> Result<StepFunctionsExecutionTreeResponse, Error> {
1270 let mut encoded = String::with_capacity(execution_arn.len());
1271 for b in execution_arn.bytes() {
1272 match b {
1273 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1274 encoded.push(b as char);
1275 }
1276 _ => encoded.push_str(&format!("%{:02X}", b)),
1277 }
1278 }
1279 let resp = self
1280 .fc
1281 .client
1282 .get(format!(
1283 "{}/_fakecloud/stepfunctions/execution-tree/{}",
1284 self.fc.base_url, encoded
1285 ))
1286 .send()
1287 .await?;
1288 FakeCloud::parse(resp).await
1289 }
1290}
1291
1292pub struct BedrockClient<'a> {
1295 fc: &'a FakeCloud,
1296}
1297
1298impl BedrockClient<'_> {
1299 pub async fn get_invocations(&self) -> Result<BedrockInvocationsResponse, Error> {
1302 let resp = self
1303 .fc
1304 .client
1305 .get(format!(
1306 "{}/_fakecloud/bedrock/invocations",
1307 self.fc.base_url
1308 ))
1309 .send()
1310 .await?;
1311 FakeCloud::parse(resp).await
1312 }
1313
1314 pub async fn set_model_response(
1316 &self,
1317 model_id: &str,
1318 response: &str,
1319 ) -> Result<BedrockModelResponseConfig, Error> {
1320 let resp = self
1321 .fc
1322 .client
1323 .post(format!(
1324 "{}/_fakecloud/bedrock/models/{}/response",
1325 self.fc.base_url, model_id
1326 ))
1327 .header("content-type", "text/plain")
1328 .body(response.to_string())
1329 .send()
1330 .await?;
1331 FakeCloud::parse(resp).await
1332 }
1333
1334 pub async fn set_response_rules(
1336 &self,
1337 model_id: &str,
1338 rules: &[BedrockResponseRule],
1339 ) -> Result<BedrockModelResponseConfig, Error> {
1340 let body = serde_json::json!({ "rules": rules });
1341 let resp = self
1342 .fc
1343 .client
1344 .post(format!(
1345 "{}/_fakecloud/bedrock/models/{}/responses",
1346 self.fc.base_url, model_id
1347 ))
1348 .json(&body)
1349 .send()
1350 .await?;
1351 FakeCloud::parse(resp).await
1352 }
1353
1354 pub async fn clear_response_rules(
1356 &self,
1357 model_id: &str,
1358 ) -> Result<BedrockModelResponseConfig, Error> {
1359 let resp = self
1360 .fc
1361 .client
1362 .delete(format!(
1363 "{}/_fakecloud/bedrock/models/{}/responses",
1364 self.fc.base_url, model_id
1365 ))
1366 .send()
1367 .await?;
1368 FakeCloud::parse(resp).await
1369 }
1370
1371 pub async fn queue_fault(
1373 &self,
1374 rule: &BedrockFaultRule,
1375 ) -> Result<BedrockStatusResponse, Error> {
1376 let resp = self
1377 .fc
1378 .client
1379 .post(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1380 .json(rule)
1381 .send()
1382 .await?;
1383 FakeCloud::parse(resp).await
1384 }
1385
1386 pub async fn get_faults(&self) -> Result<BedrockFaultsResponse, Error> {
1388 let resp = self
1389 .fc
1390 .client
1391 .get(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1392 .send()
1393 .await?;
1394 FakeCloud::parse(resp).await
1395 }
1396
1397 pub async fn clear_faults(&self) -> Result<BedrockStatusResponse, Error> {
1399 let resp = self
1400 .fc
1401 .client
1402 .delete(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
1403 .send()
1404 .await?;
1405 FakeCloud::parse(resp).await
1406 }
1407}
1408
1409pub struct BedrockAgentClient<'a> {
1412 fc: &'a FakeCloud,
1413}
1414
1415impl BedrockAgentClient<'_> {
1416 pub async fn get_agents(&self) -> Result<BedrockAgentAgentsResponse, Error> {
1420 let resp = self
1421 .fc
1422 .client
1423 .get(format!(
1424 "{}/_fakecloud/bedrock-agent/agents",
1425 self.fc.base_url
1426 ))
1427 .send()
1428 .await?;
1429 FakeCloud::parse(resp).await
1430 }
1431}
1432
1433pub struct BedrockAgentRuntimeClient<'a> {
1436 fc: &'a FakeCloud,
1437}
1438
1439impl BedrockAgentRuntimeClient<'_> {
1440 pub async fn get_invocations(&self) -> Result<BedrockAgentRuntimeInvocationsResponse, Error> {
1443 let resp = self
1444 .fc
1445 .client
1446 .get(format!(
1447 "{}/_fakecloud/bedrock-agent-runtime/invocations",
1448 self.fc.base_url
1449 ))
1450 .send()
1451 .await?;
1452 FakeCloud::parse(resp).await
1453 }
1454}
1455
1456pub struct EcsClient<'a> {
1459 fc: &'a FakeCloud,
1460}
1461
1462impl EcsClient<'_> {
1463 pub async fn get_clusters(&self) -> Result<EcsClustersResponse, Error> {
1467 let resp = self
1468 .fc
1469 .client
1470 .get(format!("{}/_fakecloud/ecs/clusters", self.fc.base_url))
1471 .send()
1472 .await?;
1473 FakeCloud::parse(resp).await
1474 }
1475
1476 pub async fn get_tasks(
1479 &self,
1480 cluster: Option<&str>,
1481 status: Option<&str>,
1482 ) -> Result<EcsTasksResponse, Error> {
1483 fn encode(s: &str) -> String {
1484 let mut out = String::with_capacity(s.len());
1485 for b in s.bytes() {
1486 match b {
1487 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1488 out.push(b as char);
1489 }
1490 _ => out.push_str(&format!("%{:02X}", b)),
1491 }
1492 }
1493 out
1494 }
1495 let mut url = format!("{}/_fakecloud/ecs/tasks", self.fc.base_url);
1496 let mut sep = '?';
1497 if let Some(c) = cluster {
1498 url.push(sep);
1499 url.push_str("cluster=");
1500 url.push_str(&encode(c));
1501 sep = '&';
1502 }
1503 if let Some(s) = status {
1504 url.push(sep);
1505 url.push_str("status=");
1506 url.push_str(&encode(s));
1507 }
1508 let resp = self.fc.client.get(url).send().await?;
1509 FakeCloud::parse(resp).await
1510 }
1511
1512 pub async fn get_task_logs(&self, task_id: &str) -> Result<EcsTaskLogsResponse, Error> {
1516 let resp = self
1517 .fc
1518 .client
1519 .get(format!(
1520 "{}/_fakecloud/ecs/tasks/{}/logs",
1521 self.fc.base_url, task_id
1522 ))
1523 .send()
1524 .await?;
1525 FakeCloud::parse(resp).await
1526 }
1527
1528 pub async fn force_stop_task(&self, task_id: &str) -> Result<EcsTask, Error> {
1530 let resp = self
1531 .fc
1532 .client
1533 .post(format!(
1534 "{}/_fakecloud/ecs/tasks/{}/force-stop",
1535 self.fc.base_url, task_id
1536 ))
1537 .send()
1538 .await?;
1539 FakeCloud::parse(resp).await
1540 }
1541
1542 pub async fn mark_task_failed(
1545 &self,
1546 task_id: &str,
1547 req: &EcsMarkFailedRequest,
1548 ) -> Result<EcsTask, Error> {
1549 let resp = self
1550 .fc
1551 .client
1552 .post(format!(
1553 "{}/_fakecloud/ecs/tasks/{}/mark-failed",
1554 self.fc.base_url, task_id
1555 ))
1556 .json(req)
1557 .send()
1558 .await?;
1559 FakeCloud::parse(resp).await
1560 }
1561
1562 pub async fn get_events(&self) -> Result<EcsEventsResponse, Error> {
1564 let resp = self
1565 .fc
1566 .client
1567 .get(format!("{}/_fakecloud/ecs/events", self.fc.base_url))
1568 .send()
1569 .await?;
1570 FakeCloud::parse(resp).await
1571 }
1572
1573 pub async fn get_metadata_by_arn(&self, task_arn: &str) -> Result<serde_json::Value, Error> {
1580 let mut encoded = String::with_capacity(task_arn.len());
1581 for b in task_arn.bytes() {
1582 match b {
1583 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1584 encoded.push(b as char);
1585 }
1586 _ => encoded.push_str(&format!("%{:02X}", b)),
1587 }
1588 }
1589 let resp = self
1590 .fc
1591 .client
1592 .get(format!(
1593 "{}/_fakecloud/ecs/metadata/{}",
1594 self.fc.base_url, encoded
1595 ))
1596 .send()
1597 .await?;
1598 FakeCloud::parse(resp).await
1599 }
1600
1601 pub async fn task_credentials(
1606 &self,
1607 task_id: &str,
1608 ) -> Result<EcsTaskCredentialsResponse, Error> {
1609 let resp = self
1610 .fc
1611 .client
1612 .get(format!(
1613 "{}/_fakecloud/ecs/creds/{}",
1614 self.fc.base_url, task_id
1615 ))
1616 .send()
1617 .await?;
1618 FakeCloud::parse(resp).await
1619 }
1620
1621 pub async fn task_metadata_v3(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1627 let resp = self
1628 .fc
1629 .client
1630 .get(format!(
1631 "{}/_fakecloud/ecs/v3/{}",
1632 self.fc.base_url, task_id
1633 ))
1634 .send()
1635 .await?;
1636 FakeCloud::parse(resp).await
1637 }
1638
1639 pub async fn task_metadata_v4(&self, task_id: &str) -> Result<serde_json::Value, Error> {
1643 let resp = self
1644 .fc
1645 .client
1646 .get(format!(
1647 "{}/_fakecloud/ecs/v4/{}",
1648 self.fc.base_url, task_id
1649 ))
1650 .send()
1651 .await?;
1652 FakeCloud::parse(resp).await
1653 }
1654}
1655
1656pub struct Route53Client<'a> {
1659 fc: &'a FakeCloud,
1660}
1661
1662impl Route53Client<'_> {
1663 pub async fn dnssec_material(
1667 &self,
1668 zone_id: &str,
1669 ) -> Result<Route53DnssecMaterialResponse, Error> {
1670 let resp = self
1671 .fc
1672 .client
1673 .get(format!(
1674 "{}/_fakecloud/route53/zones/{}/dnssec",
1675 self.fc.base_url, zone_id
1676 ))
1677 .send()
1678 .await?;
1679 FakeCloud::parse(resp).await
1680 }
1681
1682 pub async fn dnssec_sign(
1686 &self,
1687 zone_id: &str,
1688 req: &Route53DnssecSignRequest,
1689 ) -> Result<Route53DnssecSignResponse, Error> {
1690 let resp = self
1691 .fc
1692 .client
1693 .post(format!(
1694 "{}/_fakecloud/route53/zones/{}/dnssec/sign",
1695 self.fc.base_url, zone_id
1696 ))
1697 .json(req)
1698 .send()
1699 .await?;
1700 FakeCloud::parse(resp).await
1701 }
1702}
1703
1704pub struct AthenaClient<'a> {
1707 fc: &'a FakeCloud,
1708}
1709
1710impl AthenaClient<'_> {
1711 pub async fn get_named_queries(&self) -> Result<AthenaNamedQueriesResponse, Error> {
1716 let resp = self
1717 .fc
1718 .client
1719 .get(format!(
1720 "{}/_fakecloud/athena/named-queries",
1721 self.fc.base_url
1722 ))
1723 .send()
1724 .await?;
1725 FakeCloud::parse(resp).await
1726 }
1727}
1728
1729pub struct OrganizationsClient<'a> {
1732 fc: &'a FakeCloud,
1733}
1734
1735impl OrganizationsClient<'_> {
1736 pub async fn get_accounts(&self) -> Result<OrganizationsAccountsResponse, Error> {
1741 let resp = self
1742 .fc
1743 .client
1744 .get(format!(
1745 "{}/_fakecloud/organizations/accounts",
1746 self.fc.base_url
1747 ))
1748 .send()
1749 .await?;
1750 FakeCloud::parse(resp).await
1751 }
1752
1753 pub async fn get_responsibility_transfers(
1757 &self,
1758 ) -> Result<OrganizationsResponsibilityTransfersResponse, Error> {
1759 let resp = self
1760 .fc
1761 .client
1762 .get(format!(
1763 "{}/_fakecloud/organizations/responsibility-transfers",
1764 self.fc.base_url
1765 ))
1766 .send()
1767 .await?;
1768 FakeCloud::parse(resp).await
1769 }
1770}
1771
1772pub struct AcmClient<'a> {
1775 fc: &'a FakeCloud,
1776}
1777
1778impl AcmClient<'_> {
1779 fn certificate_id(arn_or_id: &str) -> String {
1780 match arn_or_id.rfind("certificate/") {
1781 Some(idx) => arn_or_id[idx + "certificate/".len()..].to_string(),
1782 None => arn_or_id.to_string(),
1783 }
1784 }
1785
1786 pub async fn set_certificate_status(
1791 &self,
1792 arn_or_id: &str,
1793 req: &AcmCertificateStatusRequest,
1794 ) -> Result<(), Error> {
1795 let id = Self::certificate_id(arn_or_id);
1796 let resp = self
1797 .fc
1798 .client
1799 .post(format!(
1800 "{}/_fakecloud/acm/certificates/{}/status",
1801 self.fc.base_url, id
1802 ))
1803 .json(req)
1804 .send()
1805 .await?;
1806 if !resp.status().is_success() {
1807 let status = resp.status().as_u16();
1808 let body = resp.text().await.unwrap_or_default();
1809 return Err(Error::Api { status, body });
1810 }
1811 Ok(())
1812 }
1813
1814 pub async fn get_certificate_chain_info(
1818 &self,
1819 arn_or_id: &str,
1820 ) -> Result<AcmCertificateChainInfo, Error> {
1821 let id = Self::certificate_id(arn_or_id);
1822 let resp = self
1823 .fc
1824 .client
1825 .get(format!(
1826 "{}/_fakecloud/acm/certificates/{}/chain-info",
1827 self.fc.base_url, id
1828 ))
1829 .send()
1830 .await?;
1831 FakeCloud::parse(resp).await
1832 }
1833
1834 pub async fn approve_certificate(&self, arn_or_id: &str) -> Result<(), Error> {
1838 let id = Self::certificate_id(arn_or_id);
1839 let resp = self
1840 .fc
1841 .client
1842 .post(format!(
1843 "{}/_fakecloud/acm/certificates/{}/approve",
1844 self.fc.base_url, id
1845 ))
1846 .send()
1847 .await?;
1848 if !resp.status().is_success() {
1849 let status = resp.status().as_u16();
1850 let body = resp.text().await.unwrap_or_default();
1851 return Err(Error::Api { status, body });
1852 }
1853 Ok(())
1854 }
1855}
1856
1857pub struct EcrClient<'a> {
1860 fc: &'a FakeCloud,
1861}
1862
1863impl EcrClient<'_> {
1864 pub async fn get_images(&self) -> Result<EcrImagesResponse, Error> {
1866 let resp = self
1867 .fc
1868 .client
1869 .get(format!("{}/_fakecloud/ecr/images", self.fc.base_url))
1870 .send()
1871 .await?;
1872 FakeCloud::parse(resp).await
1873 }
1874
1875 pub async fn get_repositories(&self) -> Result<EcrRepositoriesResponse, Error> {
1877 let resp = self
1878 .fc
1879 .client
1880 .get(format!("{}/_fakecloud/ecr/repositories", self.fc.base_url))
1881 .send()
1882 .await?;
1883 FakeCloud::parse(resp).await
1884 }
1885
1886 pub async fn get_pull_through_rules(&self) -> Result<EcrPullThroughRulesResponse, Error> {
1888 let resp = self
1889 .fc
1890 .client
1891 .get(format!(
1892 "{}/_fakecloud/ecr/pull-through-rules",
1893 self.fc.base_url
1894 ))
1895 .send()
1896 .await?;
1897 FakeCloud::parse(resp).await
1898 }
1899}
1900
1901pub struct Elbv2Client<'a> {
1904 fc: &'a FakeCloud,
1905}
1906
1907impl Elbv2Client<'_> {
1908 pub async fn get_load_balancers(&self) -> Result<Elbv2LoadBalancersResponse, Error> {
1910 let resp = self
1911 .fc
1912 .client
1913 .get(format!(
1914 "{}/_fakecloud/elbv2/load-balancers",
1915 self.fc.base_url
1916 ))
1917 .send()
1918 .await?;
1919 FakeCloud::parse(resp).await
1920 }
1921
1922 pub async fn get_listeners(&self) -> Result<Elbv2ListenersResponse, Error> {
1924 let resp = self
1925 .fc
1926 .client
1927 .get(format!("{}/_fakecloud/elbv2/listeners", self.fc.base_url))
1928 .send()
1929 .await?;
1930 FakeCloud::parse(resp).await
1931 }
1932
1933 pub async fn get_rules(&self) -> Result<Elbv2RulesResponse, Error> {
1935 let resp = self
1936 .fc
1937 .client
1938 .get(format!("{}/_fakecloud/elbv2/rules", self.fc.base_url))
1939 .send()
1940 .await?;
1941 FakeCloud::parse(resp).await
1942 }
1943
1944 pub async fn get_target_groups(&self) -> Result<Elbv2TargetGroupsResponse, Error> {
1947 let resp = self
1948 .fc
1949 .client
1950 .get(format!(
1951 "{}/_fakecloud/elbv2/target-groups",
1952 self.fc.base_url
1953 ))
1954 .send()
1955 .await?;
1956 FakeCloud::parse(resp).await
1957 }
1958
1959 pub async fn flush_access_logs(&self) -> Result<Elbv2AccessLogsFlushResponse, Error> {
1962 let resp = self
1963 .fc
1964 .client
1965 .post(format!(
1966 "{}/_fakecloud/elbv2/access-logs/flush",
1967 self.fc.base_url
1968 ))
1969 .send()
1970 .await?;
1971 FakeCloud::parse(resp).await
1972 }
1973}
1974
1975pub struct GlueClient<'a> {
1978 fc: &'a FakeCloud,
1979}
1980
1981impl GlueClient<'_> {
1982 pub async fn get_jobs(&self) -> Result<GlueJobsResponse, Error> {
1984 let resp = self
1985 .fc
1986 .client
1987 .get(format!("{}/_fakecloud/glue/jobs", self.fc.base_url))
1988 .send()
1989 .await?;
1990 FakeCloud::parse(resp).await
1991 }
1992
1993 pub async fn get_job_runs(&self, job_name: Option<&str>) -> Result<GlueJobRunsResponse, Error> {
1996 fn encode(s: &str) -> String {
1997 let mut out = String::with_capacity(s.len());
1998 for b in s.bytes() {
1999 match b {
2000 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
2001 out.push(b as char);
2002 }
2003 _ => out.push_str(&format!("%{:02X}", b)),
2004 }
2005 }
2006 out
2007 }
2008 let mut url = format!("{}/_fakecloud/glue/job-runs", self.fc.base_url);
2009 if let Some(name) = job_name {
2010 url.push_str("?job_name=");
2011 url.push_str(&encode(name));
2012 }
2013 let resp = self.fc.client.get(url).send().await?;
2014 FakeCloud::parse(resp).await
2015 }
2016
2017 pub async fn get_crawlers(&self) -> Result<GlueCrawlersResponse, Error> {
2019 let resp = self
2020 .fc
2021 .client
2022 .get(format!("{}/_fakecloud/glue/crawlers", self.fc.base_url))
2023 .send()
2024 .await?;
2025 FakeCloud::parse(resp).await
2026 }
2027}
2028
2029pub struct CloudWatchClient<'a> {
2032 fc: &'a FakeCloud,
2033}
2034
2035impl CloudWatchClient<'_> {
2036 pub async fn get_alarms(&self) -> Result<CloudWatchAlarmsResponse, Error> {
2039 let resp = self
2040 .fc
2041 .client
2042 .get(format!("{}/_fakecloud/cloudwatch/alarms", self.fc.base_url))
2043 .send()
2044 .await?;
2045 FakeCloud::parse(resp).await
2046 }
2047
2048 pub async fn get_metrics(&self) -> Result<CloudWatchMetricsResponse, Error> {
2051 let resp = self
2052 .fc
2053 .client
2054 .get(format!(
2055 "{}/_fakecloud/cloudwatch/metrics",
2056 self.fc.base_url
2057 ))
2058 .send()
2059 .await?;
2060 FakeCloud::parse(resp).await
2061 }
2062}
2063
2064pub struct FirehoseClient<'a> {
2067 fc: &'a FakeCloud,
2068}
2069
2070impl FirehoseClient<'_> {
2071 pub async fn get_delivery_streams(&self) -> Result<FirehoseDeliveryStreamsResponse, Error> {
2075 let resp = self
2076 .fc
2077 .client
2078 .get(format!(
2079 "{}/_fakecloud/firehose/delivery-streams",
2080 self.fc.base_url
2081 ))
2082 .send()
2083 .await?;
2084 FakeCloud::parse(resp).await
2085 }
2086}
2087
2088pub struct LogsClient<'a> {
2091 fc: &'a FakeCloud,
2092}
2093
2094impl LogsClient<'_> {
2095 pub async fn inject_anomaly(
2099 &self,
2100 req: &LogsAnomalyInjectRequest,
2101 ) -> Result<LogsAnomalyInjectResponse, Error> {
2102 let resp = self
2103 .fc
2104 .client
2105 .post(format!(
2106 "{}/_fakecloud/logs/anomalies/inject",
2107 self.fc.base_url
2108 ))
2109 .json(req)
2110 .send()
2111 .await?;
2112 FakeCloud::parse(resp).await
2113 }
2114
2115 pub async fn get_delivery_config(&self) -> Result<LogsDeliveryConfigResponse, Error> {
2119 let resp = self
2120 .fc
2121 .client
2122 .get(format!(
2123 "{}/_fakecloud/logs/delivery-config",
2124 self.fc.base_url
2125 ))
2126 .send()
2127 .await?;
2128 FakeCloud::parse(resp).await
2129 }
2130
2131 pub async fn get_field_indexes(
2135 &self,
2136 log_group_name: &str,
2137 ) -> Result<LogsFieldIndexesResponse, Error> {
2138 let resp = self
2139 .fc
2140 .client
2141 .get(format!(
2142 "{}/_fakecloud/logs/field-indexes/{}",
2143 self.fc.base_url,
2144 utf8_percent_encode(log_group_name, NON_ALPHANUMERIC)
2145 ))
2146 .send()
2147 .await?;
2148 FakeCloud::parse(resp).await
2149 }
2150}
2151
2152impl Route53Client<'_> {
2153 pub async fn set_health_check_status(
2158 &self,
2159 id: &str,
2160 req: &Route53HealthCheckStatusRequest,
2161 ) -> Result<(), Error> {
2162 let resp = self
2163 .fc
2164 .client
2165 .post(format!(
2166 "{}/_fakecloud/route53/health-checks/{}/status",
2167 self.fc.base_url, id
2168 ))
2169 .json(req)
2170 .send()
2171 .await?;
2172 if !resp.status().is_success() {
2173 let status = resp.status().as_u16();
2174 let body = resp.text().await.unwrap_or_default();
2175 return Err(Error::Api { status, body });
2176 }
2177 Ok(())
2178 }
2179}
2180
2181pub struct SchedulerClient<'a> {
2184 fc: &'a FakeCloud,
2185}
2186
2187impl SchedulerClient<'_> {
2188 pub async fn get_schedules(&self) -> Result<SchedulerSchedulesResponse, Error> {
2191 let resp = self
2192 .fc
2193 .client
2194 .get(format!(
2195 "{}/_fakecloud/scheduler/schedules",
2196 self.fc.base_url
2197 ))
2198 .send()
2199 .await?;
2200 FakeCloud::parse(resp).await
2201 }
2202
2203 pub async fn fire_schedule(
2207 &self,
2208 group: &str,
2209 name: &str,
2210 ) -> Result<FireScheduleResponse, Error> {
2211 let resp = self
2212 .fc
2213 .client
2214 .post(format!(
2215 "{}/_fakecloud/scheduler/fire/{}/{}",
2216 self.fc.base_url, group, name
2217 ))
2218 .send()
2219 .await?;
2220 FakeCloud::parse(resp).await
2221 }
2222}
2223
2224pub struct SsmClient<'a> {
2227 fc: &'a FakeCloud,
2228}
2229
2230impl SsmClient<'_> {
2231 pub async fn set_command_status(
2234 &self,
2235 command_id: &str,
2236 req: &SetSsmCommandStatusRequest,
2237 ) -> Result<SetSsmCommandStatusResponse, Error> {
2238 let resp = self
2239 .fc
2240 .client
2241 .post(format!(
2242 "{}/_fakecloud/ssm/commands/{}/status",
2243 self.fc.base_url, command_id
2244 ))
2245 .json(req)
2246 .send()
2247 .await?;
2248 FakeCloud::parse(resp).await
2249 }
2250
2251 pub async fn fail_command(
2255 &self,
2256 command_id: &str,
2257 req: Option<&FailSsmCommandRequest>,
2258 ) -> Result<FailSsmCommandResponse, Error> {
2259 let mut builder = self.fc.client.post(format!(
2260 "{}/_fakecloud/ssm/commands/{}/fail",
2261 self.fc.base_url, command_id
2262 ));
2263 if let Some(body) = req {
2264 builder = builder.json(body);
2265 }
2266 let resp = builder.send().await?;
2267 FakeCloud::parse(resp).await
2268 }
2269
2270 pub async fn parameter_policy_events(
2273 &self,
2274 account_id: Option<&str>,
2275 ) -> Result<SsmParameterPolicyEventsResponse, Error> {
2276 let mut url = format!(
2277 "{}/_fakecloud/ssm/parameter-policy-events",
2278 self.fc.base_url
2279 );
2280 if let Some(id) = account_id {
2281 url.push_str("?accountId=");
2282 url.push_str(id);
2283 }
2284 let resp = self.fc.client.get(url).send().await?;
2285 FakeCloud::parse(resp).await
2286 }
2287
2288 pub async fn inject_session(
2292 &self,
2293 req: &InjectSsmSessionRequest,
2294 ) -> Result<InjectSsmSessionResponse, Error> {
2295 let resp = self
2296 .fc
2297 .client
2298 .post(format!(
2299 "{}/_fakecloud/ssm/sessions/inject",
2300 self.fc.base_url
2301 ))
2302 .json(req)
2303 .send()
2304 .await?;
2305 FakeCloud::parse(resp).await
2306 }
2307}
2308
2309pub struct KmsClient<'a> {
2312 fc: &'a FakeCloud,
2313}
2314
2315impl KmsClient<'_> {
2316 pub async fn usage(&self) -> Result<KmsUsageResponse, Error> {
2318 let resp = self
2319 .fc
2320 .client
2321 .get(format!("{}/_fakecloud/kms/usage", self.fc.base_url))
2322 .send()
2323 .await?;
2324 FakeCloud::parse(resp).await
2325 }
2326}
2327
2328pub struct WafV2Client<'a> {
2331 fc: &'a FakeCloud,
2332}
2333
2334impl WafV2Client<'_> {
2335 pub async fn evaluate(&self, body: &serde_json::Value) -> Result<serde_json::Value, Error> {
2340 let resp = self
2341 .fc
2342 .client
2343 .post(format!("{}/_fakecloud/wafv2/evaluate", self.fc.base_url))
2344 .json(body)
2345 .send()
2346 .await?;
2347 FakeCloud::parse(resp).await
2348 }
2349}
2350
2351pub struct CloudFrontClient<'a> {
2354 fc: &'a FakeCloud,
2355}
2356
2357impl CloudFrontClient<'_> {
2358 pub async fn set_distribution_status(
2362 &self,
2363 distribution_id: &str,
2364 req: &CloudFrontDistributionStatusRequest,
2365 ) -> Result<(), Error> {
2366 let resp = self
2367 .fc
2368 .client
2369 .post(format!(
2370 "{}/_fakecloud/cloudfront/distributions/{}/status",
2371 self.fc.base_url, distribution_id
2372 ))
2373 .json(req)
2374 .send()
2375 .await?;
2376 let status = resp.status().as_u16();
2377 if !resp.status().is_success() {
2378 let body = resp.text().await.unwrap_or_default();
2379 return Err(Error::Api { status, body });
2380 }
2381 Ok(())
2382 }
2383}
2384
2385impl Elbv2Client<'_> {
2386 pub async fn waf_counts(&self) -> Result<Elbv2WafCountsResponse, Error> {
2390 let resp = self
2391 .fc
2392 .client
2393 .get(format!("{}/_fakecloud/elbv2/waf-counts", self.fc.base_url))
2394 .send()
2395 .await?;
2396 FakeCloud::parse(resp).await
2397 }
2398}