1use crate::error::Error;
2use crate::types::*;
3
4pub struct FakeCloud {
6 base_url: String,
7 client: reqwest::Client,
8}
9
10impl FakeCloud {
11 pub fn new(base_url: &str) -> Self {
13 Self {
14 base_url: base_url.trim_end_matches('/').to_string(),
15 client: reqwest::Client::new(),
16 }
17 }
18
19 pub async fn health(&self) -> Result<HealthResponse, Error> {
23 let resp = self
24 .client
25 .get(format!("{}/_fakecloud/health", self.base_url))
26 .send()
27 .await?;
28 Self::parse(resp).await
29 }
30
31 pub async fn reset(&self) -> Result<ResetResponse, Error> {
33 let resp = self
34 .client
35 .post(format!("{}/_reset", self.base_url))
36 .send()
37 .await?;
38 Self::parse(resp).await
39 }
40
41 pub async fn create_admin(
46 &self,
47 account_id: &str,
48 user_name: &str,
49 ) -> Result<CreateAdminResponse, Error> {
50 let resp = self
51 .client
52 .post(format!("{}/_fakecloud/iam/create-admin", self.base_url))
53 .json(&CreateAdminRequest {
54 account_id: account_id.to_string(),
55 user_name: user_name.to_string(),
56 })
57 .send()
58 .await?;
59 Self::parse(resp).await
60 }
61
62 pub async fn reset_service(&self, service: &str) -> Result<ResetServiceResponse, Error> {
64 let resp = self
65 .client
66 .post(format!("{}/_fakecloud/reset/{}", self.base_url, service))
67 .send()
68 .await?;
69 Self::parse(resp).await
70 }
71
72 pub async fn reset_service_for_account(
74 &self,
75 service: &str,
76 account_id: &str,
77 ) -> Result<ResetServiceResponse, Error> {
78 let resp = self
79 .client
80 .post(format!(
81 "{}/_fakecloud/reset/{}/{}",
82 self.base_url, service, account_id
83 ))
84 .send()
85 .await?;
86 Self::parse(resp).await
87 }
88
89 pub fn lambda(&self) -> LambdaClient<'_> {
92 LambdaClient { fc: self }
93 }
94
95 pub fn ses(&self) -> SesClient<'_> {
96 SesClient { fc: self }
97 }
98
99 pub fn sns(&self) -> SnsClient<'_> {
100 SnsClient { fc: self }
101 }
102
103 pub fn sqs(&self) -> SqsClient<'_> {
104 SqsClient { fc: self }
105 }
106
107 pub fn events(&self) -> EventsClient<'_> {
108 EventsClient { fc: self }
109 }
110
111 pub fn s3(&self) -> S3Client<'_> {
112 S3Client { fc: self }
113 }
114
115 pub fn dynamodb(&self) -> DynamoDbClient<'_> {
116 DynamoDbClient { fc: self }
117 }
118
119 pub fn secretsmanager(&self) -> SecretsManagerClient<'_> {
120 SecretsManagerClient { fc: self }
121 }
122
123 pub fn cognito(&self) -> CognitoClient<'_> {
124 CognitoClient { fc: self }
125 }
126
127 pub fn rds(&self) -> RdsClient<'_> {
128 RdsClient { fc: self }
129 }
130
131 pub fn elasticache(&self) -> ElastiCacheClient<'_> {
132 ElastiCacheClient { fc: self }
133 }
134
135 pub fn apigatewayv2(&self) -> ApiGatewayV2Client<'_> {
136 ApiGatewayV2Client { fc: self }
137 }
138
139 pub fn stepfunctions(&self) -> StepFunctionsClient<'_> {
140 StepFunctionsClient { fc: self }
141 }
142
143 pub fn bedrock(&self) -> BedrockClient<'_> {
144 BedrockClient { fc: self }
145 }
146
147 pub fn bedrock_agent(&self) -> BedrockAgentClient<'_> {
148 BedrockAgentClient { fc: self }
149 }
150
151 pub fn bedrock_agent_runtime(&self) -> BedrockAgentRuntimeClient<'_> {
152 BedrockAgentRuntimeClient { fc: self }
153 }
154
155 pub fn ecs(&self) -> EcsClient<'_> {
156 EcsClient { fc: self }
157 }
158
159 pub fn application_autoscaling(&self) -> ApplicationAutoScalingClient<'_> {
160 ApplicationAutoScalingClient { fc: self }
161 }
162
163 pub fn athena(&self) -> AthenaClient<'_> {
164 AthenaClient { fc: self }
165 }
166
167 pub fn organizations(&self) -> OrganizationsClient<'_> {
168 OrganizationsClient { fc: self }
169 }
170
171 async fn parse<T: serde::de::DeserializeOwned>(resp: reqwest::Response) -> Result<T, Error> {
174 let status = resp.status().as_u16();
175 if !resp.status().is_success() {
176 let body = resp.text().await.unwrap_or_default();
177 return Err(Error::Api { status, body });
178 }
179 Ok(resp.json::<T>().await?)
180 }
181}
182
183pub struct RdsClient<'a> {
186 fc: &'a FakeCloud,
187}
188
189impl RdsClient<'_> {
190 pub async fn get_instances(&self) -> Result<RdsInstancesResponse, Error> {
192 let resp = self
193 .fc
194 .client
195 .get(format!("{}/_fakecloud/rds/instances", self.fc.base_url))
196 .send()
197 .await?;
198 FakeCloud::parse(resp).await
199 }
200}
201
202pub struct ElastiCacheClient<'a> {
205 fc: &'a FakeCloud,
206}
207
208impl ElastiCacheClient<'_> {
209 pub async fn get_clusters(&self) -> Result<ElastiCacheClustersResponse, Error> {
211 let resp = self
212 .fc
213 .client
214 .get(format!(
215 "{}/_fakecloud/elasticache/clusters",
216 self.fc.base_url
217 ))
218 .send()
219 .await?;
220 FakeCloud::parse(resp).await
221 }
222
223 pub async fn get_replication_groups(
225 &self,
226 ) -> Result<ElastiCacheReplicationGroupsResponse, Error> {
227 let resp = self
228 .fc
229 .client
230 .get(format!(
231 "{}/_fakecloud/elasticache/replication-groups",
232 self.fc.base_url
233 ))
234 .send()
235 .await?;
236 FakeCloud::parse(resp).await
237 }
238
239 pub async fn get_serverless_caches(
241 &self,
242 ) -> Result<ElastiCacheServerlessCachesResponse, Error> {
243 let resp = self
244 .fc
245 .client
246 .get(format!(
247 "{}/_fakecloud/elasticache/serverless-caches",
248 self.fc.base_url
249 ))
250 .send()
251 .await?;
252 FakeCloud::parse(resp).await
253 }
254
255 pub async fn get_acls(&self) -> Result<ElastiCacheAclsResponse, Error> {
258 let resp = self
259 .fc
260 .client
261 .get(format!("{}/_fakecloud/elasticache/acls", self.fc.base_url))
262 .send()
263 .await?;
264 FakeCloud::parse(resp).await
265 }
266}
267
268pub struct LambdaClient<'a> {
271 fc: &'a FakeCloud,
272}
273
274impl LambdaClient<'_> {
275 pub async fn get_invocations(&self) -> Result<LambdaInvocationsResponse, Error> {
277 let resp = self
278 .fc
279 .client
280 .get(format!(
281 "{}/_fakecloud/lambda/invocations",
282 self.fc.base_url
283 ))
284 .send()
285 .await?;
286 FakeCloud::parse(resp).await
287 }
288
289 pub async fn get_warm_containers(&self) -> Result<WarmContainersResponse, Error> {
291 let resp = self
292 .fc
293 .client
294 .get(format!(
295 "{}/_fakecloud/lambda/warm-containers",
296 self.fc.base_url
297 ))
298 .send()
299 .await?;
300 FakeCloud::parse(resp).await
301 }
302
303 pub async fn evict_container(
305 &self,
306 function_name: &str,
307 ) -> Result<EvictContainerResponse, Error> {
308 let resp = self
309 .fc
310 .client
311 .post(format!(
312 "{}/_fakecloud/lambda/{}/evict-container",
313 self.fc.base_url, function_name
314 ))
315 .send()
316 .await?;
317 FakeCloud::parse(resp).await
318 }
319}
320
321pub struct SesClient<'a> {
324 fc: &'a FakeCloud,
325}
326
327impl SesClient<'_> {
328 pub async fn get_emails(&self) -> Result<SesEmailsResponse, Error> {
330 let resp = self
331 .fc
332 .client
333 .get(format!("{}/_fakecloud/ses/emails", self.fc.base_url))
334 .send()
335 .await?;
336 FakeCloud::parse(resp).await
337 }
338
339 pub async fn simulate_inbound(
341 &self,
342 req: &InboundEmailRequest,
343 ) -> Result<InboundEmailResponse, Error> {
344 let resp = self
345 .fc
346 .client
347 .post(format!("{}/_fakecloud/ses/inbound", self.fc.base_url))
348 .json(req)
349 .send()
350 .await?;
351 FakeCloud::parse(resp).await
352 }
353}
354
355pub struct SnsClient<'a> {
358 fc: &'a FakeCloud,
359}
360
361impl SnsClient<'_> {
362 pub async fn get_messages(&self) -> Result<SnsMessagesResponse, Error> {
364 let resp = self
365 .fc
366 .client
367 .get(format!("{}/_fakecloud/sns/messages", self.fc.base_url))
368 .send()
369 .await?;
370 FakeCloud::parse(resp).await
371 }
372
373 pub async fn get_pending_confirmations(&self) -> Result<PendingConfirmationsResponse, Error> {
375 let resp = self
376 .fc
377 .client
378 .get(format!(
379 "{}/_fakecloud/sns/pending-confirmations",
380 self.fc.base_url
381 ))
382 .send()
383 .await?;
384 FakeCloud::parse(resp).await
385 }
386
387 pub async fn confirm_subscription(
389 &self,
390 req: &ConfirmSubscriptionRequest,
391 ) -> Result<ConfirmSubscriptionResponse, Error> {
392 let resp = self
393 .fc
394 .client
395 .post(format!(
396 "{}/_fakecloud/sns/confirm-subscription",
397 self.fc.base_url
398 ))
399 .json(req)
400 .send()
401 .await?;
402 FakeCloud::parse(resp).await
403 }
404}
405
406pub struct SqsClient<'a> {
409 fc: &'a FakeCloud,
410}
411
412impl SqsClient<'_> {
413 pub async fn get_messages(&self) -> Result<SqsMessagesResponse, Error> {
415 let resp = self
416 .fc
417 .client
418 .get(format!("{}/_fakecloud/sqs/messages", self.fc.base_url))
419 .send()
420 .await?;
421 FakeCloud::parse(resp).await
422 }
423
424 pub async fn tick_expiration(&self) -> Result<ExpirationTickResponse, Error> {
426 let resp = self
427 .fc
428 .client
429 .post(format!(
430 "{}/_fakecloud/sqs/expiration-processor/tick",
431 self.fc.base_url
432 ))
433 .send()
434 .await?;
435 FakeCloud::parse(resp).await
436 }
437
438 pub async fn force_dlq(&self, queue_name: &str) -> Result<ForceDlqResponse, Error> {
440 let resp = self
441 .fc
442 .client
443 .post(format!(
444 "{}/_fakecloud/sqs/{}/force-dlq",
445 self.fc.base_url, queue_name
446 ))
447 .send()
448 .await?;
449 FakeCloud::parse(resp).await
450 }
451}
452
453pub struct ApplicationAutoScalingClient<'a> {
456 fc: &'a FakeCloud,
457}
458
459impl ApplicationAutoScalingClient<'_> {
460 pub async fn tick(&self) -> Result<AppAsTickResponse, Error> {
465 let resp = self
466 .fc
467 .client
468 .post(format!(
469 "{}/_fakecloud/application-autoscaling/tick",
470 self.fc.base_url
471 ))
472 .send()
473 .await?;
474 FakeCloud::parse(resp).await
475 }
476
477 pub async fn scheduled_tick(&self) -> Result<AppAsScheduledTickResponse, Error> {
482 let resp = self
483 .fc
484 .client
485 .post(format!(
486 "{}/_fakecloud/application-autoscaling/scheduled-tick",
487 self.fc.base_url
488 ))
489 .send()
490 .await?;
491 FakeCloud::parse(resp).await
492 }
493}
494
495pub struct EventsClient<'a> {
498 fc: &'a FakeCloud,
499}
500
501impl EventsClient<'_> {
502 pub async fn get_history(&self) -> Result<EventHistoryResponse, Error> {
504 let resp = self
505 .fc
506 .client
507 .get(format!("{}/_fakecloud/events/history", self.fc.base_url))
508 .send()
509 .await?;
510 FakeCloud::parse(resp).await
511 }
512
513 pub async fn fire_rule(&self, req: &FireRuleRequest) -> Result<FireRuleResponse, Error> {
515 let resp = self
516 .fc
517 .client
518 .post(format!("{}/_fakecloud/events/fire-rule", self.fc.base_url))
519 .json(req)
520 .send()
521 .await?;
522 FakeCloud::parse(resp).await
523 }
524}
525
526pub struct S3Client<'a> {
529 fc: &'a FakeCloud,
530}
531
532impl S3Client<'_> {
533 pub async fn get_notifications(&self) -> Result<S3NotificationsResponse, Error> {
535 let resp = self
536 .fc
537 .client
538 .get(format!("{}/_fakecloud/s3/notifications", self.fc.base_url))
539 .send()
540 .await?;
541 FakeCloud::parse(resp).await
542 }
543
544 pub async fn tick_lifecycle(&self) -> Result<LifecycleTickResponse, Error> {
546 let resp = self
547 .fc
548 .client
549 .post(format!(
550 "{}/_fakecloud/s3/lifecycle-processor/tick",
551 self.fc.base_url
552 ))
553 .send()
554 .await?;
555 FakeCloud::parse(resp).await
556 }
557
558 pub async fn get_access_points(&self) -> Result<S3AccessPointsResponse, Error> {
560 let resp = self
561 .fc
562 .client
563 .get(format!("{}/_fakecloud/s3/access-points", self.fc.base_url))
564 .send()
565 .await?;
566 FakeCloud::parse(resp).await
567 }
568
569 pub async fn get_object_lambda_responses(
571 &self,
572 ) -> Result<S3ObjectLambdaResponsesResponse, Error> {
573 let resp = self
574 .fc
575 .client
576 .get(format!(
577 "{}/_fakecloud/s3/object-lambda-responses",
578 self.fc.base_url
579 ))
580 .send()
581 .await?;
582 FakeCloud::parse(resp).await
583 }
584}
585
586pub struct DynamoDbClient<'a> {
589 fc: &'a FakeCloud,
590}
591
592impl DynamoDbClient<'_> {
593 pub async fn tick_ttl(&self) -> Result<TtlTickResponse, Error> {
595 let resp = self
596 .fc
597 .client
598 .post(format!(
599 "{}/_fakecloud/dynamodb/ttl-processor/tick",
600 self.fc.base_url
601 ))
602 .send()
603 .await?;
604 FakeCloud::parse(resp).await
605 }
606}
607
608pub struct SecretsManagerClient<'a> {
611 fc: &'a FakeCloud,
612}
613
614impl SecretsManagerClient<'_> {
615 pub async fn tick_rotation(&self) -> Result<RotationTickResponse, Error> {
617 let resp = self
618 .fc
619 .client
620 .post(format!(
621 "{}/_fakecloud/secretsmanager/rotation-scheduler/tick",
622 self.fc.base_url
623 ))
624 .send()
625 .await?;
626 FakeCloud::parse(resp).await
627 }
628}
629
630pub struct CognitoClient<'a> {
633 fc: &'a FakeCloud,
634}
635
636impl CognitoClient<'_> {
637 pub async fn get_user_codes(
639 &self,
640 pool_id: &str,
641 username: &str,
642 ) -> Result<UserConfirmationCodes, Error> {
643 let resp = self
644 .fc
645 .client
646 .get(format!(
647 "{}/_fakecloud/cognito/confirmation-codes/{}/{}",
648 self.fc.base_url, pool_id, username
649 ))
650 .send()
651 .await?;
652 FakeCloud::parse(resp).await
653 }
654
655 pub async fn get_confirmation_codes(&self) -> Result<ConfirmationCodesResponse, Error> {
657 let resp = self
658 .fc
659 .client
660 .get(format!(
661 "{}/_fakecloud/cognito/confirmation-codes",
662 self.fc.base_url
663 ))
664 .send()
665 .await?;
666 FakeCloud::parse(resp).await
667 }
668
669 pub async fn confirm_user(
671 &self,
672 req: &ConfirmUserRequest,
673 ) -> Result<ConfirmUserResponse, Error> {
674 let resp = self
675 .fc
676 .client
677 .post(format!(
678 "{}/_fakecloud/cognito/confirm-user",
679 self.fc.base_url
680 ))
681 .json(req)
682 .send()
683 .await?;
684 let status = resp.status().as_u16();
685 let body: ConfirmUserResponse = resp.json().await?;
686 if status >= 400 {
687 return Err(Error::Api {
688 status,
689 body: body.error.unwrap_or_default(),
690 });
691 }
692 Ok(body)
693 }
694
695 pub async fn get_tokens(&self) -> Result<TokensResponse, Error> {
697 let resp = self
698 .fc
699 .client
700 .get(format!("{}/_fakecloud/cognito/tokens", self.fc.base_url))
701 .send()
702 .await?;
703 FakeCloud::parse(resp).await
704 }
705
706 pub async fn expire_tokens(
708 &self,
709 req: &ExpireTokensRequest,
710 ) -> Result<ExpireTokensResponse, Error> {
711 let resp = self
712 .fc
713 .client
714 .post(format!(
715 "{}/_fakecloud/cognito/expire-tokens",
716 self.fc.base_url
717 ))
718 .json(req)
719 .send()
720 .await?;
721 FakeCloud::parse(resp).await
722 }
723
724 pub async fn get_auth_events(&self) -> Result<AuthEventsResponse, Error> {
726 let resp = self
727 .fc
728 .client
729 .get(format!(
730 "{}/_fakecloud/cognito/auth-events",
731 self.fc.base_url
732 ))
733 .send()
734 .await?;
735 FakeCloud::parse(resp).await
736 }
737
738 pub async fn get_pre_token_gen_invocations(
744 &self,
745 ) -> Result<PreTokenGenInvocationsResponse, Error> {
746 let resp = self
747 .fc
748 .client
749 .get(format!(
750 "{}/_fakecloud/cognito/pretokengen/invocations",
751 self.fc.base_url
752 ))
753 .send()
754 .await?;
755 FakeCloud::parse(resp).await
756 }
757}
758
759pub struct ApiGatewayV2Client<'a> {
762 fc: &'a FakeCloud,
763}
764
765impl ApiGatewayV2Client<'_> {
766 pub async fn get_requests(&self) -> Result<ApiGatewayV2RequestsResponse, Error> {
768 let resp = self
769 .fc
770 .client
771 .get(format!(
772 "{}/_fakecloud/apigatewayv2/requests",
773 self.fc.base_url
774 ))
775 .send()
776 .await?;
777 FakeCloud::parse(resp).await
778 }
779}
780
781pub struct StepFunctionsClient<'a> {
784 fc: &'a FakeCloud,
785}
786
787impl StepFunctionsClient<'_> {
788 pub async fn get_executions(&self) -> Result<StepFunctionsExecutionsResponse, Error> {
790 let resp = self
791 .fc
792 .client
793 .get(format!(
794 "{}/_fakecloud/stepfunctions/executions",
795 self.fc.base_url
796 ))
797 .send()
798 .await?;
799 FakeCloud::parse(resp).await
800 }
801
802 pub async fn get_sync_executions(&self) -> Result<StepFunctionsSyncExecutionsResponse, Error> {
806 let resp = self
807 .fc
808 .client
809 .get(format!(
810 "{}/_fakecloud/stepfunctions/sync-executions",
811 self.fc.base_url
812 ))
813 .send()
814 .await?;
815 FakeCloud::parse(resp).await
816 }
817
818 pub async fn get_execution_tree(
822 &self,
823 execution_arn: &str,
824 ) -> Result<StepFunctionsExecutionTreeResponse, Error> {
825 let mut encoded = String::with_capacity(execution_arn.len());
826 for b in execution_arn.bytes() {
827 match b {
828 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
829 encoded.push(b as char);
830 }
831 _ => encoded.push_str(&format!("%{:02X}", b)),
832 }
833 }
834 let resp = self
835 .fc
836 .client
837 .get(format!(
838 "{}/_fakecloud/stepfunctions/execution-tree/{}",
839 self.fc.base_url, encoded
840 ))
841 .send()
842 .await?;
843 FakeCloud::parse(resp).await
844 }
845}
846
847pub struct BedrockClient<'a> {
850 fc: &'a FakeCloud,
851}
852
853impl BedrockClient<'_> {
854 pub async fn get_invocations(&self) -> Result<BedrockInvocationsResponse, Error> {
857 let resp = self
858 .fc
859 .client
860 .get(format!(
861 "{}/_fakecloud/bedrock/invocations",
862 self.fc.base_url
863 ))
864 .send()
865 .await?;
866 FakeCloud::parse(resp).await
867 }
868
869 pub async fn set_model_response(
871 &self,
872 model_id: &str,
873 response: &str,
874 ) -> Result<BedrockModelResponseConfig, Error> {
875 let resp = self
876 .fc
877 .client
878 .post(format!(
879 "{}/_fakecloud/bedrock/models/{}/response",
880 self.fc.base_url, model_id
881 ))
882 .header("content-type", "text/plain")
883 .body(response.to_string())
884 .send()
885 .await?;
886 FakeCloud::parse(resp).await
887 }
888
889 pub async fn set_response_rules(
891 &self,
892 model_id: &str,
893 rules: &[BedrockResponseRule],
894 ) -> Result<BedrockModelResponseConfig, Error> {
895 let body = serde_json::json!({ "rules": rules });
896 let resp = self
897 .fc
898 .client
899 .post(format!(
900 "{}/_fakecloud/bedrock/models/{}/responses",
901 self.fc.base_url, model_id
902 ))
903 .json(&body)
904 .send()
905 .await?;
906 FakeCloud::parse(resp).await
907 }
908
909 pub async fn clear_response_rules(
911 &self,
912 model_id: &str,
913 ) -> Result<BedrockModelResponseConfig, Error> {
914 let resp = self
915 .fc
916 .client
917 .delete(format!(
918 "{}/_fakecloud/bedrock/models/{}/responses",
919 self.fc.base_url, model_id
920 ))
921 .send()
922 .await?;
923 FakeCloud::parse(resp).await
924 }
925
926 pub async fn queue_fault(
928 &self,
929 rule: &BedrockFaultRule,
930 ) -> Result<BedrockStatusResponse, Error> {
931 let resp = self
932 .fc
933 .client
934 .post(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
935 .json(rule)
936 .send()
937 .await?;
938 FakeCloud::parse(resp).await
939 }
940
941 pub async fn get_faults(&self) -> Result<BedrockFaultsResponse, Error> {
943 let resp = self
944 .fc
945 .client
946 .get(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
947 .send()
948 .await?;
949 FakeCloud::parse(resp).await
950 }
951
952 pub async fn clear_faults(&self) -> Result<BedrockStatusResponse, Error> {
954 let resp = self
955 .fc
956 .client
957 .delete(format!("{}/_fakecloud/bedrock/faults", self.fc.base_url))
958 .send()
959 .await?;
960 FakeCloud::parse(resp).await
961 }
962}
963
964pub struct BedrockAgentClient<'a> {
967 fc: &'a FakeCloud,
968}
969
970impl BedrockAgentClient<'_> {
971 pub async fn get_agents(&self) -> Result<BedrockAgentAgentsResponse, Error> {
975 let resp = self
976 .fc
977 .client
978 .get(format!(
979 "{}/_fakecloud/bedrock-agent/agents",
980 self.fc.base_url
981 ))
982 .send()
983 .await?;
984 FakeCloud::parse(resp).await
985 }
986}
987
988pub struct BedrockAgentRuntimeClient<'a> {
991 fc: &'a FakeCloud,
992}
993
994impl BedrockAgentRuntimeClient<'_> {
995 pub async fn get_invocations(&self) -> Result<BedrockAgentRuntimeInvocationsResponse, Error> {
998 let resp = self
999 .fc
1000 .client
1001 .get(format!(
1002 "{}/_fakecloud/bedrock-agent-runtime/invocations",
1003 self.fc.base_url
1004 ))
1005 .send()
1006 .await?;
1007 FakeCloud::parse(resp).await
1008 }
1009}
1010
1011pub struct EcsClient<'a> {
1014 fc: &'a FakeCloud,
1015}
1016
1017impl EcsClient<'_> {
1018 pub async fn get_clusters(&self) -> Result<EcsClustersResponse, Error> {
1022 let resp = self
1023 .fc
1024 .client
1025 .get(format!("{}/_fakecloud/ecs/clusters", self.fc.base_url))
1026 .send()
1027 .await?;
1028 FakeCloud::parse(resp).await
1029 }
1030
1031 pub async fn get_tasks(
1034 &self,
1035 cluster: Option<&str>,
1036 status: Option<&str>,
1037 ) -> Result<EcsTasksResponse, Error> {
1038 fn encode(s: &str) -> String {
1039 let mut out = String::with_capacity(s.len());
1040 for b in s.bytes() {
1041 match b {
1042 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
1043 out.push(b as char);
1044 }
1045 _ => out.push_str(&format!("%{:02X}", b)),
1046 }
1047 }
1048 out
1049 }
1050 let mut url = format!("{}/_fakecloud/ecs/tasks", self.fc.base_url);
1051 let mut sep = '?';
1052 if let Some(c) = cluster {
1053 url.push(sep);
1054 url.push_str("cluster=");
1055 url.push_str(&encode(c));
1056 sep = '&';
1057 }
1058 if let Some(s) = status {
1059 url.push(sep);
1060 url.push_str("status=");
1061 url.push_str(&encode(s));
1062 }
1063 let resp = self.fc.client.get(url).send().await?;
1064 FakeCloud::parse(resp).await
1065 }
1066
1067 pub async fn get_task_logs(&self, task_id: &str) -> Result<EcsTaskLogsResponse, Error> {
1071 let resp = self
1072 .fc
1073 .client
1074 .get(format!(
1075 "{}/_fakecloud/ecs/tasks/{}/logs",
1076 self.fc.base_url, task_id
1077 ))
1078 .send()
1079 .await?;
1080 FakeCloud::parse(resp).await
1081 }
1082
1083 pub async fn force_stop_task(&self, task_id: &str) -> Result<EcsTask, Error> {
1085 let resp = self
1086 .fc
1087 .client
1088 .post(format!(
1089 "{}/_fakecloud/ecs/tasks/{}/force-stop",
1090 self.fc.base_url, task_id
1091 ))
1092 .send()
1093 .await?;
1094 FakeCloud::parse(resp).await
1095 }
1096
1097 pub async fn mark_task_failed(
1100 &self,
1101 task_id: &str,
1102 req: &EcsMarkFailedRequest,
1103 ) -> Result<EcsTask, Error> {
1104 let resp = self
1105 .fc
1106 .client
1107 .post(format!(
1108 "{}/_fakecloud/ecs/tasks/{}/mark-failed",
1109 self.fc.base_url, task_id
1110 ))
1111 .json(req)
1112 .send()
1113 .await?;
1114 FakeCloud::parse(resp).await
1115 }
1116
1117 pub async fn get_events(&self) -> Result<EcsEventsResponse, Error> {
1119 let resp = self
1120 .fc
1121 .client
1122 .get(format!("{}/_fakecloud/ecs/events", self.fc.base_url))
1123 .send()
1124 .await?;
1125 FakeCloud::parse(resp).await
1126 }
1127}
1128
1129pub struct AthenaClient<'a> {
1132 fc: &'a FakeCloud,
1133}
1134
1135impl AthenaClient<'_> {
1136 pub async fn get_named_queries(&self) -> Result<AthenaNamedQueriesResponse, Error> {
1141 let resp = self
1142 .fc
1143 .client
1144 .get(format!(
1145 "{}/_fakecloud/athena/named-queries",
1146 self.fc.base_url
1147 ))
1148 .send()
1149 .await?;
1150 FakeCloud::parse(resp).await
1151 }
1152}
1153
1154pub struct OrganizationsClient<'a> {
1157 fc: &'a FakeCloud,
1158}
1159
1160impl OrganizationsClient<'_> {
1161 pub async fn get_accounts(&self) -> Result<OrganizationsAccountsResponse, Error> {
1166 let resp = self
1167 .fc
1168 .client
1169 .get(format!(
1170 "{}/_fakecloud/organizations/accounts",
1171 self.fc.base_url
1172 ))
1173 .send()
1174 .await?;
1175 FakeCloud::parse(resp).await
1176 }
1177}