1use std::collections::BTreeMap;
9use std::sync::Arc;
10
11use parking_lot::RwLock;
12use serde::{Deserialize, Serialize};
13
14pub type SharedEc2State = Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<Ec2State>>>;
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Ec2Snapshot {
23 pub schema_version: u32,
24 #[serde(default)]
25 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<Ec2State>>,
26}
27
28pub const EC2_SNAPSHOT_SCHEMA_VERSION: u32 = 1;
29
30impl fakecloud_core::multi_account::AccountState for Ec2State {
31 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
32 Self::new(account_id, region)
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
38pub struct Tag {
39 pub key: String,
40 pub value: String,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize)]
45pub struct VpcCidrAssoc {
46 pub association_id: String,
47 pub cidr_block: String,
48 pub state: String,
50}
51
52#[derive(Clone, Debug, Serialize, Deserialize)]
54pub struct Vpc {
55 pub vpc_id: String,
56 pub cidr_block: String,
57 pub state: String,
59 pub dhcp_options_id: String,
60 pub instance_tenancy: String,
62 pub is_default: bool,
63 pub enable_dns_support: bool,
64 pub enable_dns_hostnames: bool,
65 #[serde(default)]
66 pub cidr_associations: Vec<VpcCidrAssoc>,
67 #[serde(default)]
72 pub ipv6_cidr_block: Option<String>,
73}
74
75#[derive(Clone, Debug, Serialize, Deserialize)]
77pub struct DhcpConfig {
78 pub key: String,
79 pub values: Vec<String>,
80}
81
82#[derive(Clone, Debug, Serialize, Deserialize)]
84pub struct DhcpOptions {
85 pub dhcp_options_id: String,
86 pub configurations: Vec<DhcpConfig>,
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize)]
91pub struct Subnet {
92 pub subnet_id: String,
93 pub vpc_id: String,
94 pub cidr_block: String,
95 pub availability_zone: String,
96 pub availability_zone_id: String,
97 pub state: String,
99 pub available_ip_address_count: i32,
100 pub default_for_az: bool,
101 pub map_public_ip_on_launch: bool,
102 pub assign_ipv6_address_on_creation: bool,
103 pub map_customer_owned_ip_on_launch: bool,
104 pub enable_dns64: bool,
105 pub private_dns_hostname_type: String,
107 #[serde(default)]
111 pub ipv6_cidr_block: Option<String>,
112}
113
114#[derive(Clone, Debug, Serialize, Deserialize)]
116pub struct SubnetCidrReservation {
117 pub subnet_cidr_reservation_id: String,
118 pub subnet_id: String,
119 pub cidr: String,
120 pub reservation_type: String,
122 pub description: String,
123}
124
125#[derive(Clone, Debug, Serialize, Deserialize)]
127pub struct SecurityGroupRule {
128 pub rule_id: String,
129 pub group_id: String,
130 pub is_egress: bool,
131 pub ip_protocol: String,
132 pub from_port: i64,
133 pub to_port: i64,
134 pub cidr_ipv4: Option<String>,
135 pub cidr_ipv6: Option<String>,
136 pub prefix_list_id: Option<String>,
137 pub referenced_group_id: Option<String>,
138 pub description: String,
139}
140
141#[derive(Clone, Debug, Serialize, Deserialize)]
143pub struct SecurityGroup {
144 pub group_id: String,
145 pub group_name: String,
146 pub description: String,
147 pub vpc_id: String,
148 #[serde(default)]
149 pub rules: Vec<SecurityGroupRule>,
150}
151
152#[derive(Clone, Debug, Default, Serialize, Deserialize)]
154pub struct Route {
155 pub destination_cidr_block: Option<String>,
156 pub destination_ipv6_cidr_block: Option<String>,
157 pub destination_prefix_list_id: Option<String>,
158 pub gateway_id: Option<String>,
159 pub nat_gateway_id: Option<String>,
160 pub network_interface_id: Option<String>,
161 pub instance_id: Option<String>,
162 pub vpc_peering_connection_id: Option<String>,
163 pub transit_gateway_id: Option<String>,
164 pub egress_only_internet_gateway_id: Option<String>,
165 pub state: String,
167 pub origin: String,
169}
170
171#[derive(Clone, Debug, Serialize, Deserialize)]
173pub struct RouteTableAssociation {
174 pub association_id: String,
175 pub route_table_id: String,
176 pub subnet_id: Option<String>,
177 pub gateway_id: Option<String>,
178 pub main: bool,
179}
180
181#[derive(Clone, Debug, Serialize, Deserialize)]
183pub struct RouteTable {
184 pub route_table_id: String,
185 pub vpc_id: String,
186 #[serde(default)]
187 pub routes: Vec<Route>,
188 #[serde(default)]
189 pub associations: Vec<RouteTableAssociation>,
190}
191
192#[derive(Clone, Debug, Serialize, Deserialize)]
194pub struct InternetGateway {
195 pub internet_gateway_id: String,
196 #[serde(default)]
198 pub attachments: Vec<(String, String)>,
199}
200
201#[derive(Clone, Debug, Serialize, Deserialize)]
203pub struct NatGateway {
204 pub nat_gateway_id: String,
205 pub subnet_id: String,
206 pub vpc_id: String,
207 pub state: String,
209 pub connectivity_type: String,
211 pub allocation_id: Option<String>,
212}
213
214#[derive(Clone, Debug, Serialize, Deserialize)]
216pub struct ElasticIp {
217 pub allocation_id: String,
218 pub public_ip: String,
219 pub domain: String,
221 pub association_id: Option<String>,
222 pub instance_id: Option<String>,
223 pub network_interface_id: Option<String>,
224 pub private_ip_address: Option<String>,
225}
226
227#[derive(Clone, Debug, Serialize, Deserialize)]
229pub struct KeyPair {
230 pub key_pair_id: String,
231 pub key_name: String,
232 pub key_type: String,
234 pub key_fingerprint: String,
235}
236
237#[derive(Clone, Debug, Serialize, Deserialize)]
239pub struct PlacementGroup {
240 pub group_id: String,
241 pub group_name: String,
242 pub strategy: String,
244 pub state: String,
246 pub partition_count: Option<i64>,
247 pub spread_level: Option<String>,
248}
249
250#[derive(Clone, Debug, Serialize, Deserialize)]
252pub struct EniAttachment {
253 pub attachment_id: String,
254 pub instance_id: String,
255 pub device_index: i64,
256 pub status: String,
258}
259
260#[derive(Clone, Debug, Serialize, Deserialize)]
262pub struct NetworkInterface {
263 pub network_interface_id: String,
264 pub subnet_id: String,
265 pub vpc_id: String,
266 pub availability_zone: String,
267 pub description: String,
268 pub mac_address: String,
269 pub private_ip_address: String,
270 pub status: String,
272 pub interface_type: String,
273 pub source_dest_check: bool,
274 #[serde(default)]
275 pub group_ids: Vec<String>,
276 #[serde(default)]
277 pub private_ips: Vec<String>,
278 #[serde(default)]
279 pub ipv6_addresses: Vec<String>,
280 pub attachment: Option<EniAttachment>,
281}
282
283#[derive(Clone, Debug, Serialize, Deserialize)]
285pub struct NetworkInterfacePermission {
286 pub permission_id: String,
287 pub network_interface_id: String,
288 pub aws_account_id: String,
289 pub permission: String,
291}
292
293#[derive(Clone, Debug, Serialize, Deserialize)]
295pub struct Instance {
296 pub instance_id: String,
297 pub image_id: String,
298 pub instance_type: String,
299 pub state_code: i64,
302 pub state_name: String,
303 pub private_ip: String,
304 pub public_ip: Option<String>,
305 pub subnet_id: Option<String>,
306 pub vpc_id: Option<String>,
307 pub key_name: Option<String>,
308 #[serde(default)]
309 pub security_group_ids: Vec<String>,
310 pub reservation_id: String,
311 pub ami_launch_index: i64,
312 pub monitoring: bool,
313 pub az: String,
314 pub launch_time: String,
315 #[serde(default)]
318 pub container_id: Option<String>,
319 #[serde(default)]
322 pub disable_api_termination: bool,
323 #[serde(default)]
325 pub disable_api_stop: bool,
326 #[serde(default = "default_true")]
328 pub source_dest_check: bool,
329 #[serde(default)]
331 pub ebs_optimized: bool,
332 #[serde(default = "default_shutdown_behavior")]
334 pub instance_initiated_shutdown_behavior: String,
335 #[serde(default)]
337 pub user_data: Option<String>,
338 #[serde(default)]
341 pub metadata_options: MetadataOptions,
342 #[serde(default)]
344 pub cpu_options: Option<CpuOptions>,
345 #[serde(default)]
347 pub bandwidth_weighting: Option<String>,
348 #[serde(default)]
350 pub maintenance_options: MaintenanceOptions,
351 #[serde(default)]
353 pub placement_tenancy: Option<String>,
354 #[serde(default)]
355 pub placement_affinity: Option<String>,
356 #[serde(default)]
357 pub placement_group_name: Option<String>,
358}
359
360fn default_true() -> bool {
361 true
362}
363
364fn default_shutdown_behavior() -> String {
365 "stop".to_string()
366}
367
368#[derive(Clone, Debug, Serialize, Deserialize)]
371pub struct MetadataOptions {
372 pub http_tokens: String,
374 pub http_endpoint: String,
376 pub http_put_response_hop_limit: i64,
377 pub http_protocol_ipv6: String,
379 pub instance_metadata_tags: String,
381}
382
383impl Default for MetadataOptions {
384 fn default() -> Self {
385 Self {
386 http_tokens: "optional".to_string(),
387 http_endpoint: "enabled".to_string(),
388 http_put_response_hop_limit: 1,
389 http_protocol_ipv6: "disabled".to_string(),
390 instance_metadata_tags: "disabled".to_string(),
391 }
392 }
393}
394
395#[derive(Clone, Debug, Serialize, Deserialize)]
397pub struct CpuOptions {
398 pub core_count: i64,
399 pub threads_per_core: i64,
400}
401
402#[derive(Clone, Debug, Serialize, Deserialize)]
404pub struct MaintenanceOptions {
405 pub auto_recovery: String,
407 pub reboot_migration: String,
409}
410
411impl Default for MaintenanceOptions {
412 fn default() -> Self {
413 Self {
414 auto_recovery: "default".to_string(),
415 reboot_migration: "default".to_string(),
416 }
417 }
418}
419
420#[derive(Clone, Debug, Serialize, Deserialize)]
422pub struct VolumeAttachment {
423 pub volume_id: String,
424 pub instance_id: String,
425 pub device: String,
426 pub status: String,
428 pub delete_on_termination: bool,
429}
430
431#[derive(Clone, Debug, Serialize, Deserialize)]
433pub struct Volume {
434 pub volume_id: String,
435 pub size: i64,
436 pub snapshot_id: Option<String>,
437 pub availability_zone: String,
438 pub state: String,
440 pub volume_type: String,
441 pub iops: Option<i64>,
442 pub throughput: Option<i64>,
443 pub encrypted: bool,
444 pub kms_key_id: Option<String>,
445 pub multi_attach_enabled: bool,
446 pub auto_enable_io: bool,
447 #[serde(default)]
448 pub attachments: Vec<VolumeAttachment>,
449 #[serde(default)]
450 pub in_recycle_bin: bool,
451}
452
453#[derive(Clone, Debug, Serialize, Deserialize)]
455pub struct Snapshot {
456 pub snapshot_id: String,
457 pub volume_id: String,
458 pub state: String,
460 pub volume_size: i64,
461 pub description: String,
462 pub encrypted: bool,
463 pub storage_tier: String,
465 #[serde(default)]
466 pub in_recycle_bin: bool,
467 #[serde(default)]
468 pub locked: bool,
469 pub lock_mode: Option<String>,
470}
471
472#[derive(Clone, Debug, Serialize, Deserialize)]
474pub struct Image {
475 pub image_id: String,
476 pub name: String,
477 pub description: String,
478 pub state: String,
480 pub architecture: String,
481 pub public: bool,
482 pub source_instance_id: Option<String>,
483 #[serde(default)]
484 pub in_recycle_bin: bool,
485 pub deprecation_time: Option<String>,
486 #[serde(default)]
487 pub deregistration_protection: bool,
488 #[serde(default)]
491 pub launch_permission_users: Vec<String>,
492 #[serde(default)]
494 pub launch_permission_groups: Vec<String>,
495 #[serde(default)]
498 pub boot_mode: Option<String>,
499}
500
501#[derive(Clone, Debug, Serialize, Deserialize)]
503pub struct NetworkAclEntry {
504 pub rule_number: i64,
505 pub protocol: String,
506 pub rule_action: String,
508 pub egress: bool,
509 pub cidr_block: Option<String>,
510 pub ipv6_cidr_block: Option<String>,
511 pub port_range: Option<(i64, i64)>,
513 pub icmp_type_code: Option<(i64, i64)>,
515}
516
517#[derive(Clone, Debug, Serialize, Deserialize)]
519pub struct NetworkAclAssoc {
520 pub association_id: String,
521 pub subnet_id: String,
522}
523
524#[derive(Clone, Debug, Serialize, Deserialize)]
526pub struct NetworkAcl {
527 pub network_acl_id: String,
528 pub vpc_id: String,
529 pub is_default: bool,
530 #[serde(default)]
531 pub entries: Vec<NetworkAclEntry>,
532 #[serde(default)]
533 pub associations: Vec<NetworkAclAssoc>,
534}
535
536#[derive(Clone, Debug, Serialize, Deserialize)]
538pub struct VpcPeering {
539 pub id: String,
540 pub requester_vpc_id: String,
541 pub accepter_vpc_id: String,
542 pub status: String,
544 #[serde(default)]
546 pub requester_allow_dns: bool,
547 #[serde(default)]
549 pub accepter_allow_dns: bool,
550}
551
552#[derive(Clone, Debug, Serialize, Deserialize)]
554pub struct VpcEndpoint {
555 pub id: String,
556 pub endpoint_type: String,
558 pub vpc_id: String,
559 pub service_name: String,
560 pub state: String,
561 #[serde(default)]
562 pub subnet_ids: Vec<String>,
563 #[serde(default)]
564 pub route_table_ids: Vec<String>,
565 #[serde(default)]
566 pub private_dns_enabled: bool,
567}
568
569#[derive(Clone, Debug, Serialize, Deserialize)]
571pub struct EndpointService {
572 pub service_id: String,
573 pub service_name: String,
574 pub state: String,
575 pub acceptance_required: bool,
576 pub payer_responsibility: String,
577 #[serde(default)]
578 pub nlb_arns: Vec<String>,
579}
580
581#[derive(Clone, Debug, Serialize, Deserialize)]
583pub struct ConnectionNotification {
584 pub id: String,
585 pub arn: String,
586 pub service_id: Option<String>,
587 #[serde(default)]
588 pub events: Vec<String>,
589}
590
591#[derive(Clone, Debug, Serialize, Deserialize)]
593pub struct FlowLog {
594 pub id: String,
595 pub resource_id: String,
596 pub traffic_type: String,
597 pub log_destination_type: String,
598 pub log_group_name: Option<String>,
599 pub log_destination: Option<String>,
601 #[serde(default)]
604 pub deliver_logs_permission_arn: Option<String>,
605 #[serde(default = "default_max_aggregation_interval")]
608 pub max_aggregation_interval: i64,
609}
610
611fn default_max_aggregation_interval() -> i64 {
612 600
613}
614
615#[derive(Clone, Debug, Serialize, Deserialize)]
617pub struct LaunchTemplate {
618 pub id: String,
619 pub name: String,
620 pub default_version: i64,
621 pub latest_version: i64,
622}
623
624#[derive(Clone, Debug, Serialize, Deserialize)]
626pub struct SpotRequest {
627 pub id: String,
628 pub state: String,
630 pub request_type: String,
631 pub spot_price: String,
632}
633
634#[derive(Clone, Debug, Serialize, Deserialize)]
636pub struct SpotFleet {
637 pub id: String,
638 pub state: String,
639}
640
641#[derive(Clone, Debug, Serialize, Deserialize)]
643pub struct Fleet {
644 pub id: String,
645 pub state: String,
646 pub fleet_type: String,
647}
648
649#[derive(Clone, Debug, Serialize, Deserialize)]
651pub struct CapacityReservation {
652 pub id: String,
653 pub instance_type: String,
654 pub instance_platform: String,
655 pub availability_zone: String,
656 pub tenancy: String,
657 pub total_instance_count: i64,
658 pub available_instance_count: i64,
659 pub state: String,
661 pub end_date_type: String,
662 pub instance_match_criteria: String,
663}
664
665#[derive(Clone, Debug, Serialize, Deserialize)]
667pub struct ReservedInstances {
668 pub id: String,
669 pub instance_type: String,
670 pub availability_zone: String,
671 pub instance_count: i64,
672 pub product_description: String,
673 pub state: String,
674 pub duration: i64,
675 pub fixed_price: String,
676 pub usage_price: String,
677}
678
679#[derive(Clone, Debug, Serialize, Deserialize)]
681pub struct ReservedInstancesListing {
682 pub listing_id: String,
683 pub reserved_instances_id: String,
684 pub instance_count: i64,
685 pub client_token: String,
686 pub status: String,
688 pub status_message: String,
689}
690
691#[derive(Clone, Debug, Serialize, Deserialize)]
693pub struct ReservedInstancesModification {
694 pub modification_id: String,
695 pub reserved_instances_ids: Vec<String>,
696 pub status: String,
698 pub client_token: String,
699}
700
701#[derive(Clone, Debug, Serialize, Deserialize)]
703pub struct DedicatedHost {
704 pub id: String,
705 pub auto_placement: String,
706 pub availability_zone: String,
707 pub instance_type: String,
708 pub state: String,
709 pub host_recovery: String,
710 pub host_maintenance: String,
711}
712
713#[derive(Clone, Debug, Serialize, Deserialize)]
715pub struct TransitGateway {
716 pub id: String,
717 pub description: String,
718 #[serde(default = "tgw_default_state")]
720 pub state: String,
721}
722
723fn tgw_default_state() -> String {
724 "available".to_string()
725}
726
727#[derive(Clone, Debug, Serialize, Deserialize)]
729pub struct TgwAttachment {
730 pub id: String,
731 pub tgw_id: String,
732 pub resource_id: String,
733 pub resource_type: String,
734 #[serde(default)]
735 pub subnet_ids: Vec<String>,
736 pub state: String,
737}
738
739#[derive(Clone, Debug, Serialize, Deserialize)]
741pub struct TgwRouteTable {
742 pub id: String,
743 pub tgw_id: String,
744}
745
746#[derive(Clone, Debug, Serialize, Deserialize)]
748pub struct TgwRoute {
749 pub cidr: String,
750 pub attachment_id: String,
751 pub state: String,
752}
753
754#[derive(Clone, Debug, Serialize, Deserialize)]
756pub struct TgwMulticastDomain {
757 pub id: String,
758 pub tgw_id: String,
759}
760
761#[derive(Clone, Debug, Serialize, Deserialize)]
763pub struct TgwMeteringPolicy {
764 pub id: String,
765 pub tgw_id: String,
766}
767
768#[derive(Clone, Debug, Serialize, Deserialize)]
770pub struct CustomerGateway {
771 pub id: String,
772 pub state: String,
773 pub ip_address: String,
774 pub bgp_asn: String,
775}
776
777#[derive(Clone, Debug, Serialize, Deserialize)]
779pub struct VpnGateway {
780 pub id: String,
781 pub state: String,
782 #[serde(default)]
783 pub attachments: Vec<String>,
784}
785
786#[derive(Clone, Debug, Serialize, Deserialize)]
788pub struct VpnConnection {
789 pub id: String,
790 pub state: String,
791 pub customer_gateway_id: String,
792 pub vpn_gateway_id: Option<String>,
793 #[serde(default)]
794 pub routes: Vec<String>,
795}
796
797#[derive(Clone, Debug, Serialize, Deserialize)]
799pub struct VpnConcentrator {
800 pub id: String,
801 pub state: String,
802}
803
804#[derive(Clone, Debug, Serialize, Deserialize)]
806pub struct Ipam {
807 pub id: String,
808 pub public_scope_id: String,
809 pub private_scope_id: String,
810 pub tier: String,
811 #[serde(default)]
812 pub description: String,
813}
814
815#[derive(Clone, Debug, Serialize, Deserialize)]
817pub struct IpamScope {
818 pub id: String,
819 pub ipam_id: String,
820 #[serde(default)]
822 pub scope_type: String,
823 #[serde(default)]
824 pub description: String,
825}
826
827#[derive(Clone, Debug, Serialize, Deserialize)]
829pub struct IpamPool {
830 pub id: String,
831 pub scope_id: String,
832 pub address_family: String,
833 #[serde(default)]
834 pub description: String,
835}
836
837#[derive(Clone, Debug, Serialize, Deserialize)]
839pub struct IpamResourceDiscovery {
840 pub id: String,
841 #[serde(default)]
842 pub description: String,
843}
844
845#[derive(Clone, Debug, Serialize, Deserialize)]
847pub struct IpamPolicy {
848 pub id: String,
849 pub ipam_id: String,
850}
851
852#[derive(Clone, Debug, Serialize, Deserialize)]
854pub struct IpamPrefixListResolver {
855 pub id: String,
856 pub ipam_id: String,
857 pub address_family: String,
858 #[serde(default)]
859 pub description: String,
860}
861
862#[derive(Clone, Debug, Serialize, Deserialize)]
864pub struct IpamPrefixListResolverTarget {
865 pub id: String,
866 pub resolver_id: String,
867 pub prefix_list_id: String,
868 pub prefix_list_region: String,
869 #[serde(default)]
870 pub track_latest_version: bool,
871}
872
873#[derive(Clone, Debug, Serialize, Deserialize)]
875pub struct VerifiedAccessInstance {
876 pub id: String,
877 pub description: String,
878 #[serde(default)]
879 pub trust_providers: Vec<String>,
880}
881
882#[derive(Clone, Debug, Serialize, Deserialize)]
884pub struct VerifiedAccessTrustProvider {
885 pub id: String,
886 pub trust_provider_type: String,
887 pub policy_reference_name: String,
888 pub description: String,
889}
890
891#[derive(Clone, Debug, Serialize, Deserialize)]
893pub struct VerifiedAccessGroup {
894 pub id: String,
895 pub instance_id: String,
896 pub description: String,
897}
898
899#[derive(Clone, Debug, Serialize, Deserialize)]
901pub struct VerifiedAccessEndpoint {
902 pub id: String,
903 pub group_id: String,
904 pub instance_id: String,
905 pub endpoint_type: String,
906 pub attachment_type: String,
907}
908
909#[derive(Clone, Debug, Serialize, Deserialize)]
911pub struct NetworkInsightsPath {
912 pub id: String,
913 pub source: String,
914 pub destination: String,
915 pub protocol: String,
916}
917
918#[derive(Clone, Debug, Serialize, Deserialize)]
920pub struct NetworkInsightsAnalysis {
921 pub id: String,
922 pub path_id: String,
923}
924
925#[derive(Clone, Debug, Serialize, Deserialize)]
927pub struct NetworkInsightsAccessScope {
928 pub id: String,
929}
930
931#[derive(Clone, Debug, Serialize, Deserialize)]
933pub struct NetworkInsightsAccessScopeAnalysis {
934 pub id: String,
935 pub scope_id: String,
936}
937
938#[derive(Clone, Debug, Serialize, Deserialize)]
940pub struct CarrierGateway {
941 pub id: String,
942 pub vpc_id: String,
943}
944
945#[derive(Clone, Debug, Serialize, Deserialize)]
947pub struct InstanceConnectEndpoint {
948 pub id: String,
949 pub subnet_id: String,
950}
951
952#[derive(Clone, Debug, Serialize, Deserialize)]
954pub struct CoipPool {
955 pub id: String,
956 pub route_table_id: String,
957}
958
959#[derive(Clone, Debug, Serialize, Deserialize)]
961pub struct LocalGatewayRouteTable {
962 pub id: String,
963 pub local_gateway_id: String,
964 pub mode: String,
965}
966
967#[derive(Clone, Debug, Serialize, Deserialize)]
969pub struct LocalGatewayRouteTableVpcAssoc {
970 pub id: String,
971 pub route_table_id: String,
972 pub vpc_id: String,
973}
974
975#[derive(Clone, Debug, Serialize, Deserialize)]
977pub struct LocalGatewayVif {
978 pub id: String,
979 pub group_id: String,
980 pub vlan: String,
981 pub local_address: String,
982 pub peer_address: String,
983}
984
985#[derive(Clone, Debug, Serialize, Deserialize)]
987pub struct LocalGatewayVifGroup {
988 pub id: String,
989 pub local_gateway_id: String,
990}
991
992#[derive(Clone, Debug, Serialize, Deserialize)]
994pub struct LocalGatewayRouteTableVifgAssoc {
995 pub id: String,
996 pub route_table_id: String,
997 pub vif_group_id: String,
998}
999
1000#[derive(Clone, Debug, Serialize, Deserialize)]
1002pub struct ClientVpnEndpoint {
1003 pub id: String,
1004 pub description: String,
1005 pub status: String,
1006 pub server_cert_arn: String,
1007 pub transport_protocol: String,
1008 pub client_cidr: String,
1009 #[serde(default)]
1010 pub routes: Vec<String>,
1011 #[serde(default)]
1013 pub target_networks: Vec<(String, String)>,
1014 #[serde(default)]
1016 pub auth_rules: Vec<String>,
1017}
1018
1019#[derive(Clone, Debug, Serialize, Deserialize)]
1021pub struct TgwPeering {
1022 pub id: String,
1023 pub tgw_id: String,
1024 pub peer_tgw_id: String,
1025 pub peer_account: String,
1026 pub peer_region: String,
1027 pub state: String,
1028}
1029
1030#[derive(Clone, Debug, Default, Serialize, Deserialize)]
1033pub struct Ec2State {
1034 pub account_id: String,
1035 pub region: String,
1036 #[serde(default)]
1038 pub tags: BTreeMap<String, Vec<Tag>>,
1039 #[serde(default)]
1040 pub vpcs: BTreeMap<String, Vpc>,
1041 #[serde(default)]
1042 pub dhcp_options: BTreeMap<String, DhcpOptions>,
1043 #[serde(default)]
1044 pub subnets: BTreeMap<String, Subnet>,
1045 #[serde(default)]
1046 pub subnet_cidr_reservations: BTreeMap<String, SubnetCidrReservation>,
1047 #[serde(default)]
1048 pub security_groups: BTreeMap<String, SecurityGroup>,
1049 #[serde(default)]
1050 pub route_tables: BTreeMap<String, RouteTable>,
1051 #[serde(default)]
1052 pub internet_gateways: BTreeMap<String, InternetGateway>,
1053 #[serde(default)]
1054 pub egress_only_igws: BTreeMap<String, InternetGateway>,
1055 #[serde(default)]
1056 pub nat_gateways: BTreeMap<String, NatGateway>,
1057 #[serde(default)]
1059 pub elastic_ips: BTreeMap<String, ElasticIp>,
1060 #[serde(default)]
1062 pub key_pairs: BTreeMap<String, KeyPair>,
1063 #[serde(default)]
1065 pub placement_groups: BTreeMap<String, PlacementGroup>,
1066 #[serde(default)]
1067 pub network_interfaces: BTreeMap<String, NetworkInterface>,
1068 #[serde(default)]
1070 pub eni_permissions: BTreeMap<String, NetworkInterfacePermission>,
1071 #[serde(default)]
1072 pub instances: BTreeMap<String, Instance>,
1073 #[serde(default)]
1074 pub volumes: BTreeMap<String, Volume>,
1075 #[serde(default)]
1077 pub ebs_encryption_default: bool,
1078 #[serde(default)]
1080 pub ebs_default_kms_key_id: Option<String>,
1081 #[serde(default)]
1082 pub snapshots: BTreeMap<String, Snapshot>,
1083 #[serde(default)]
1085 pub snapshot_block_public_access: String,
1086 #[serde(default)]
1087 pub images: BTreeMap<String, Image>,
1088 #[serde(default)]
1090 pub image_watermarks: BTreeMap<String, BTreeMap<String, String>>,
1091 #[serde(default)]
1093 pub image_block_public_access: String,
1094 #[serde(default)]
1096 pub allowed_images_settings: String,
1097 #[serde(default)]
1098 pub network_acls: BTreeMap<String, NetworkAcl>,
1099 #[serde(default)]
1100 pub vpc_peerings: BTreeMap<String, VpcPeering>,
1101 #[serde(default)]
1102 pub vpc_endpoints: BTreeMap<String, VpcEndpoint>,
1103 #[serde(default)]
1104 pub endpoint_services: BTreeMap<String, EndpointService>,
1105 #[serde(default)]
1106 pub connection_notifications: BTreeMap<String, ConnectionNotification>,
1107 #[serde(default)]
1108 pub flow_logs: BTreeMap<String, FlowLog>,
1109 #[serde(default)]
1110 pub launch_templates: BTreeMap<String, LaunchTemplate>,
1111 #[serde(default)]
1112 pub spot_requests: BTreeMap<String, SpotRequest>,
1113 #[serde(default)]
1114 pub spot_fleets: BTreeMap<String, SpotFleet>,
1115 #[serde(default)]
1116 pub fleets: BTreeMap<String, Fleet>,
1117 #[serde(default)]
1119 pub spot_datafeed: Option<(String, String)>,
1120 #[serde(default)]
1121 pub capacity_reservations: BTreeMap<String, CapacityReservation>,
1122 #[serde(default)]
1124 pub capacity_reservation_fleets: BTreeMap<String, String>,
1125 #[serde(default)]
1126 pub reserved_instances: BTreeMap<String, ReservedInstances>,
1127 #[serde(default)]
1128 pub reserved_instances_listings: BTreeMap<String, ReservedInstancesListing>,
1129 #[serde(default)]
1130 pub reserved_instances_modifications: BTreeMap<String, ReservedInstancesModification>,
1131 #[serde(default)]
1132 pub dedicated_hosts: BTreeMap<String, DedicatedHost>,
1133 #[serde(default)]
1134 pub transit_gateways: BTreeMap<String, TransitGateway>,
1135 #[serde(default)]
1136 pub tgw_attachments: BTreeMap<String, TgwAttachment>,
1137 #[serde(default)]
1138 pub tgw_route_tables: BTreeMap<String, TgwRouteTable>,
1139 #[serde(default)]
1141 pub tgw_routes: BTreeMap<String, Vec<TgwRoute>>,
1142 #[serde(default)]
1144 pub tgw_rt_associations: BTreeMap<String, Vec<String>>,
1145 #[serde(default)]
1147 pub tgw_rt_propagations: BTreeMap<String, Vec<String>>,
1148 #[serde(default)]
1150 pub tgw_prefix_list_refs: BTreeMap<String, Vec<String>>,
1151 #[serde(default)]
1152 pub tgw_peerings: BTreeMap<String, TgwPeering>,
1153 #[serde(default)]
1155 pub tgw_connects: BTreeMap<String, (String, String)>,
1156 #[serde(default)]
1158 pub tgw_connect_peers: BTreeMap<String, String>,
1159 #[serde(default)]
1161 pub tgw_policy_tables: BTreeMap<String, String>,
1162 #[serde(default)]
1164 pub tgw_policy_table_associations: BTreeMap<String, Vec<String>>,
1165 #[serde(default)]
1167 pub tgw_announcements: BTreeMap<String, (String, String)>,
1168 #[serde(default)]
1169 pub tgw_multicast_domains: BTreeMap<String, TgwMulticastDomain>,
1170 #[serde(default)]
1171 pub tgw_metering_policies: BTreeMap<String, TgwMeteringPolicy>,
1172 #[serde(default)]
1173 pub customer_gateways: BTreeMap<String, CustomerGateway>,
1174 #[serde(default)]
1175 pub vpn_gateways: BTreeMap<String, VpnGateway>,
1176 #[serde(default)]
1177 pub vpn_connections: BTreeMap<String, VpnConnection>,
1178 #[serde(default)]
1179 pub vpn_concentrators: BTreeMap<String, VpnConcentrator>,
1180 #[serde(default)]
1181 pub client_vpn_endpoints: BTreeMap<String, ClientVpnEndpoint>,
1182 #[serde(default)]
1183 pub ipams: BTreeMap<String, Ipam>,
1184 #[serde(default)]
1185 pub ipam_scopes: BTreeMap<String, IpamScope>,
1186 #[serde(default)]
1187 pub ipam_pools: BTreeMap<String, IpamPool>,
1188 #[serde(default)]
1190 pub ipam_pool_cidrs: BTreeMap<String, Vec<(String, String)>>,
1191 #[serde(default)]
1193 pub ipam_pool_allocations: BTreeMap<String, Vec<(String, String)>>,
1194 #[serde(default)]
1195 pub ipam_resource_discoveries: BTreeMap<String, IpamResourceDiscovery>,
1196 #[serde(default)]
1198 pub ipam_rd_associations: BTreeMap<String, (String, String)>,
1199 #[serde(default)]
1201 pub ipam_byoasns: BTreeMap<String, String>,
1202 #[serde(default)]
1204 pub ipam_ext_tokens: BTreeMap<String, String>,
1205 #[serde(default)]
1206 pub ipam_policies: BTreeMap<String, IpamPolicy>,
1207 #[serde(default)]
1208 pub ipam_pl_resolvers: BTreeMap<String, IpamPrefixListResolver>,
1209 #[serde(default)]
1210 pub ipam_pl_resolver_targets: BTreeMap<String, IpamPrefixListResolverTarget>,
1211 #[serde(default)]
1213 pub ipam_policy_alloc_rules: BTreeMap<String, Vec<(String, String)>>,
1214 #[serde(default)]
1216 pub ipam_enabled_policy: Option<String>,
1217 #[serde(default)]
1218 pub va_instances: BTreeMap<String, VerifiedAccessInstance>,
1219 #[serde(default)]
1220 pub va_trust_providers: BTreeMap<String, VerifiedAccessTrustProvider>,
1221 #[serde(default)]
1222 pub va_groups: BTreeMap<String, VerifiedAccessGroup>,
1223 #[serde(default)]
1224 pub va_endpoints: BTreeMap<String, VerifiedAccessEndpoint>,
1225 #[serde(default)]
1227 pub va_group_policies: BTreeMap<String, String>,
1228 #[serde(default)]
1230 pub va_endpoint_policies: BTreeMap<String, String>,
1231 #[serde(default)]
1232 pub ni_paths: BTreeMap<String, NetworkInsightsPath>,
1233 #[serde(default)]
1234 pub ni_analyses: BTreeMap<String, NetworkInsightsAnalysis>,
1235 #[serde(default)]
1236 pub ni_access_scopes: BTreeMap<String, NetworkInsightsAccessScope>,
1237 #[serde(default)]
1238 pub ni_scope_analyses: BTreeMap<String, NetworkInsightsAccessScopeAnalysis>,
1239 #[serde(default)]
1240 pub carrier_gateways: BTreeMap<String, CarrierGateway>,
1241 #[serde(default)]
1242 pub coip_pools: BTreeMap<String, CoipPool>,
1243 #[serde(default)]
1245 pub coip_pool_cidrs: BTreeMap<String, Vec<String>>,
1246 #[serde(default)]
1247 pub lg_route_tables: BTreeMap<String, LocalGatewayRouteTable>,
1248 #[serde(default)]
1250 pub lg_routes: BTreeMap<String, Vec<String>>,
1251 #[serde(default)]
1252 pub lg_rt_vpc_assocs: BTreeMap<String, LocalGatewayRouteTableVpcAssoc>,
1253 #[serde(default)]
1254 pub lg_virtual_interfaces: BTreeMap<String, LocalGatewayVif>,
1255 #[serde(default)]
1256 pub lg_vif_groups: BTreeMap<String, LocalGatewayVifGroup>,
1257 #[serde(default)]
1258 pub lg_rt_vifg_assocs: BTreeMap<String, LocalGatewayRouteTableVifgAssoc>,
1259 #[serde(default)]
1260 pub instance_connect_endpoints: BTreeMap<String, InstanceConnectEndpoint>,
1261 #[serde(default)]
1263 pub fast_launch_images: std::collections::HashSet<String>,
1264 #[serde(default)]
1265 pub serial_console_access: bool,
1266}
1267
1268impl Ec2State {
1269 pub fn new(account_id: &str, region: &str) -> Self {
1270 let mut state = Self {
1271 account_id: account_id.to_string(),
1272 region: region.to_string(),
1273 ..Default::default()
1274 };
1275 crate::defaults::bootstrap_default_network(&mut state);
1281 state
1282 }
1283
1284 pub fn upsert_tags(&mut self, resource_id: &str, new_tags: &[Tag]) {
1287 let entry = self.tags.entry(resource_id.to_string()).or_default();
1288 for t in new_tags {
1289 if let Some(existing) = entry.iter_mut().find(|e| e.key == t.key) {
1290 existing.value = t.value.clone();
1291 } else {
1292 entry.push(t.clone());
1293 }
1294 }
1295 }
1296
1297 pub fn remove_tags(&mut self, resource_id: &str, to_remove: &[(String, Option<String>)]) {
1301 if let Some(entry) = self.tags.get_mut(resource_id) {
1302 for (key, value) in to_remove {
1303 entry.retain(|e| {
1304 if &e.key != key {
1305 return true;
1306 }
1307 match value {
1308 Some(v) => &e.value != v,
1309 None => false,
1310 }
1311 });
1312 }
1313 if entry.is_empty() {
1314 self.tags.remove(resource_id);
1315 }
1316 }
1317 }
1318
1319 pub fn tags_for(&self, resource_id: &str) -> &[Tag] {
1321 self.tags.get(resource_id).map(Vec::as_slice).unwrap_or(&[])
1322 }
1323}
1324
1325#[cfg(test)]
1326mod tests {
1327 use super::*;
1328
1329 fn tag(k: &str, v: &str) -> Tag {
1330 Tag {
1331 key: k.to_string(),
1332 value: v.to_string(),
1333 }
1334 }
1335
1336 #[test]
1337 fn upsert_tags_inserts_then_overwrites_by_key() {
1338 let mut s = Ec2State::new("123456789012", "us-east-1");
1339 s.upsert_tags("vpc-1", &[tag("Name", "a"), tag("env", "dev")]);
1340 s.upsert_tags("vpc-1", &[tag("Name", "b")]);
1341 let tags = s.tags_for("vpc-1");
1342 assert_eq!(tags.len(), 2);
1343 assert_eq!(tags.iter().find(|t| t.key == "Name").unwrap().value, "b");
1344 }
1345
1346 #[test]
1347 fn remove_tags_by_key_and_by_key_value() {
1348 let mut s = Ec2State::new("123456789012", "us-east-1");
1349 s.upsert_tags(
1350 "i-1",
1351 &[tag("Name", "x"), tag("env", "prod"), tag("team", "a")],
1352 );
1353 s.remove_tags("i-1", &[("Name".to_string(), None)]);
1355 s.remove_tags("i-1", &[("env".to_string(), Some("dev".to_string()))]);
1357 s.remove_tags("i-1", &[("team".to_string(), Some("a".to_string()))]);
1359 let tags = s.tags_for("i-1");
1360 assert_eq!(tags.len(), 1);
1361 assert_eq!(tags[0].key, "env");
1362 }
1363
1364 #[test]
1365 fn empty_tag_set_drops_resource_entry() {
1366 let mut s = Ec2State::new("123456789012", "us-east-1");
1367 s.upsert_tags("sg-1", &[tag("Name", "x")]);
1368 s.remove_tags("sg-1", &[("Name".to_string(), None)]);
1369 assert!(!s.tags.contains_key("sg-1"));
1370 }
1371
1372 fn sample_instance() -> Instance {
1373 Instance {
1374 instance_id: "i-1".to_string(),
1375 image_id: "ami-1".to_string(),
1376 instance_type: "t3.micro".to_string(),
1377 state_code: 16,
1378 state_name: "running".to_string(),
1379 private_ip: "10.0.0.1".to_string(),
1380 public_ip: Some("52.0.0.1".to_string()),
1381 subnet_id: Some("subnet-1".to_string()),
1382 vpc_id: Some("vpc-1".to_string()),
1383 key_name: None,
1384 security_group_ids: vec!["sg-1".to_string()],
1385 reservation_id: "r-1".to_string(),
1386 ami_launch_index: 0,
1387 monitoring: false,
1388 az: "us-east-1a".to_string(),
1389 launch_time: "2024-01-01T00:00:00.000Z".to_string(),
1390 container_id: Some("abc".to_string()),
1391 disable_api_termination: true,
1392 disable_api_stop: true,
1393 source_dest_check: false,
1394 ebs_optimized: true,
1395 instance_initiated_shutdown_behavior: "terminate".to_string(),
1396 user_data: Some("ZWNobyBoaQ==".to_string()),
1397 metadata_options: MetadataOptions {
1398 http_tokens: "required".to_string(),
1399 ..MetadataOptions::default()
1400 },
1401 cpu_options: Some(CpuOptions {
1402 core_count: 4,
1403 threads_per_core: 2,
1404 }),
1405 bandwidth_weighting: Some("vpc-1".to_string()),
1406 maintenance_options: MaintenanceOptions::default(),
1407 placement_tenancy: Some("dedicated".to_string()),
1408 placement_affinity: None,
1409 placement_group_name: Some("cluster-1".to_string()),
1410 }
1411 }
1412
1413 #[test]
1414 fn instance_attributes_round_trip_through_serde() {
1415 let inst = sample_instance();
1416 let json = serde_json::to_string(&inst).unwrap();
1417 let back: Instance = serde_json::from_str(&json).unwrap();
1418 assert!(back.disable_api_termination);
1419 assert!(back.disable_api_stop);
1420 assert!(!back.source_dest_check);
1421 assert!(back.ebs_optimized);
1422 assert_eq!(back.instance_initiated_shutdown_behavior, "terminate");
1423 assert_eq!(back.user_data.as_deref(), Some("ZWNobyBoaQ=="));
1424 assert_eq!(back.metadata_options.http_tokens, "required");
1425 assert_eq!(back.cpu_options.as_ref().unwrap().core_count, 4);
1426 assert_eq!(back.bandwidth_weighting.as_deref(), Some("vpc-1"));
1427 assert_eq!(back.placement_tenancy.as_deref(), Some("dedicated"));
1428 assert_eq!(back.placement_group_name.as_deref(), Some("cluster-1"));
1429 }
1430
1431 #[test]
1432 fn instance_attribute_defaults_load_from_legacy_snapshot() {
1433 let legacy = r#"{
1436 "instance_id":"i-1","image_id":"ami-1","instance_type":"t3.micro",
1437 "state_code":16,"state_name":"running","private_ip":"10.0.0.1",
1438 "public_ip":null,"subnet_id":null,"vpc_id":null,"key_name":null,
1439 "reservation_id":"r-1","ami_launch_index":0,"monitoring":false,
1440 "az":"us-east-1a","launch_time":"2024-01-01T00:00:00.000Z"
1441 }"#;
1442 let inst: Instance = serde_json::from_str(legacy).unwrap();
1443 assert!(!inst.disable_api_termination);
1444 assert!(inst.source_dest_check, "sourceDestCheck defaults to true");
1445 assert_eq!(inst.instance_initiated_shutdown_behavior, "stop");
1446 assert_eq!(inst.metadata_options.http_tokens, "optional");
1447 assert!(inst.cpu_options.is_none());
1448 }
1449}