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}
68
69#[derive(Clone, Debug, Serialize, Deserialize)]
71pub struct DhcpConfig {
72 pub key: String,
73 pub values: Vec<String>,
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize)]
78pub struct DhcpOptions {
79 pub dhcp_options_id: String,
80 pub configurations: Vec<DhcpConfig>,
81}
82
83#[derive(Clone, Debug, Serialize, Deserialize)]
85pub struct Subnet {
86 pub subnet_id: String,
87 pub vpc_id: String,
88 pub cidr_block: String,
89 pub availability_zone: String,
90 pub availability_zone_id: String,
91 pub state: String,
93 pub available_ip_address_count: i32,
94 pub default_for_az: bool,
95 pub map_public_ip_on_launch: bool,
96 pub assign_ipv6_address_on_creation: bool,
97 pub map_customer_owned_ip_on_launch: bool,
98 pub enable_dns64: bool,
99 pub private_dns_hostname_type: String,
101}
102
103#[derive(Clone, Debug, Serialize, Deserialize)]
105pub struct SubnetCidrReservation {
106 pub subnet_cidr_reservation_id: String,
107 pub subnet_id: String,
108 pub cidr: String,
109 pub reservation_type: String,
111 pub description: String,
112}
113
114#[derive(Clone, Debug, Serialize, Deserialize)]
116pub struct SecurityGroupRule {
117 pub rule_id: String,
118 pub group_id: String,
119 pub is_egress: bool,
120 pub ip_protocol: String,
121 pub from_port: i64,
122 pub to_port: i64,
123 pub cidr_ipv4: Option<String>,
124 pub cidr_ipv6: Option<String>,
125 pub prefix_list_id: Option<String>,
126 pub referenced_group_id: Option<String>,
127 pub description: String,
128}
129
130#[derive(Clone, Debug, Serialize, Deserialize)]
132pub struct SecurityGroup {
133 pub group_id: String,
134 pub group_name: String,
135 pub description: String,
136 pub vpc_id: String,
137 #[serde(default)]
138 pub rules: Vec<SecurityGroupRule>,
139}
140
141#[derive(Clone, Debug, Default, Serialize, Deserialize)]
143pub struct Route {
144 pub destination_cidr_block: Option<String>,
145 pub destination_ipv6_cidr_block: Option<String>,
146 pub destination_prefix_list_id: Option<String>,
147 pub gateway_id: Option<String>,
148 pub nat_gateway_id: Option<String>,
149 pub network_interface_id: Option<String>,
150 pub instance_id: Option<String>,
151 pub vpc_peering_connection_id: Option<String>,
152 pub transit_gateway_id: Option<String>,
153 pub egress_only_internet_gateway_id: Option<String>,
154 pub state: String,
156 pub origin: String,
158}
159
160#[derive(Clone, Debug, Serialize, Deserialize)]
162pub struct RouteTableAssociation {
163 pub association_id: String,
164 pub route_table_id: String,
165 pub subnet_id: Option<String>,
166 pub gateway_id: Option<String>,
167 pub main: bool,
168}
169
170#[derive(Clone, Debug, Serialize, Deserialize)]
172pub struct RouteTable {
173 pub route_table_id: String,
174 pub vpc_id: String,
175 #[serde(default)]
176 pub routes: Vec<Route>,
177 #[serde(default)]
178 pub associations: Vec<RouteTableAssociation>,
179}
180
181#[derive(Clone, Debug, Serialize, Deserialize)]
183pub struct InternetGateway {
184 pub internet_gateway_id: String,
185 #[serde(default)]
187 pub attachments: Vec<(String, String)>,
188}
189
190#[derive(Clone, Debug, Serialize, Deserialize)]
192pub struct NatGateway {
193 pub nat_gateway_id: String,
194 pub subnet_id: String,
195 pub vpc_id: String,
196 pub state: String,
198 pub connectivity_type: String,
200 pub allocation_id: Option<String>,
201}
202
203#[derive(Clone, Debug, Serialize, Deserialize)]
205pub struct ElasticIp {
206 pub allocation_id: String,
207 pub public_ip: String,
208 pub domain: String,
210 pub association_id: Option<String>,
211 pub instance_id: Option<String>,
212 pub network_interface_id: Option<String>,
213 pub private_ip_address: Option<String>,
214}
215
216#[derive(Clone, Debug, Serialize, Deserialize)]
218pub struct KeyPair {
219 pub key_pair_id: String,
220 pub key_name: String,
221 pub key_type: String,
223 pub key_fingerprint: String,
224}
225
226#[derive(Clone, Debug, Serialize, Deserialize)]
228pub struct PlacementGroup {
229 pub group_id: String,
230 pub group_name: String,
231 pub strategy: String,
233 pub state: String,
235 pub partition_count: Option<i64>,
236 pub spread_level: Option<String>,
237}
238
239#[derive(Clone, Debug, Serialize, Deserialize)]
241pub struct EniAttachment {
242 pub attachment_id: String,
243 pub instance_id: String,
244 pub device_index: i64,
245 pub status: String,
247}
248
249#[derive(Clone, Debug, Serialize, Deserialize)]
251pub struct NetworkInterface {
252 pub network_interface_id: String,
253 pub subnet_id: String,
254 pub vpc_id: String,
255 pub availability_zone: String,
256 pub description: String,
257 pub mac_address: String,
258 pub private_ip_address: String,
259 pub status: String,
261 pub interface_type: String,
262 pub source_dest_check: bool,
263 #[serde(default)]
264 pub group_ids: Vec<String>,
265 #[serde(default)]
266 pub private_ips: Vec<String>,
267 #[serde(default)]
268 pub ipv6_addresses: Vec<String>,
269 pub attachment: Option<EniAttachment>,
270}
271
272#[derive(Clone, Debug, Serialize, Deserialize)]
274pub struct NetworkInterfacePermission {
275 pub permission_id: String,
276 pub network_interface_id: String,
277 pub aws_account_id: String,
278 pub permission: String,
280}
281
282#[derive(Clone, Debug, Serialize, Deserialize)]
284pub struct Instance {
285 pub instance_id: String,
286 pub image_id: String,
287 pub instance_type: String,
288 pub state_code: i64,
291 pub state_name: String,
292 pub private_ip: String,
293 pub public_ip: Option<String>,
294 pub subnet_id: Option<String>,
295 pub vpc_id: Option<String>,
296 pub key_name: Option<String>,
297 #[serde(default)]
298 pub security_group_ids: Vec<String>,
299 pub reservation_id: String,
300 pub ami_launch_index: i64,
301 pub monitoring: bool,
302 pub az: String,
303 pub launch_time: String,
304 #[serde(default)]
307 pub container_id: Option<String>,
308 #[serde(default)]
311 pub disable_api_termination: bool,
312 #[serde(default)]
314 pub disable_api_stop: bool,
315 #[serde(default = "default_true")]
317 pub source_dest_check: bool,
318 #[serde(default)]
320 pub ebs_optimized: bool,
321 #[serde(default = "default_shutdown_behavior")]
323 pub instance_initiated_shutdown_behavior: String,
324 #[serde(default)]
326 pub user_data: Option<String>,
327 #[serde(default)]
330 pub metadata_options: MetadataOptions,
331 #[serde(default)]
333 pub cpu_options: Option<CpuOptions>,
334 #[serde(default)]
336 pub bandwidth_weighting: Option<String>,
337 #[serde(default)]
339 pub maintenance_options: MaintenanceOptions,
340 #[serde(default)]
342 pub placement_tenancy: Option<String>,
343 #[serde(default)]
344 pub placement_affinity: Option<String>,
345 #[serde(default)]
346 pub placement_group_name: Option<String>,
347}
348
349fn default_true() -> bool {
350 true
351}
352
353fn default_shutdown_behavior() -> String {
354 "stop".to_string()
355}
356
357#[derive(Clone, Debug, Serialize, Deserialize)]
360pub struct MetadataOptions {
361 pub http_tokens: String,
363 pub http_endpoint: String,
365 pub http_put_response_hop_limit: i64,
366 pub http_protocol_ipv6: String,
368 pub instance_metadata_tags: String,
370}
371
372impl Default for MetadataOptions {
373 fn default() -> Self {
374 Self {
375 http_tokens: "optional".to_string(),
376 http_endpoint: "enabled".to_string(),
377 http_put_response_hop_limit: 1,
378 http_protocol_ipv6: "disabled".to_string(),
379 instance_metadata_tags: "disabled".to_string(),
380 }
381 }
382}
383
384#[derive(Clone, Debug, Serialize, Deserialize)]
386pub struct CpuOptions {
387 pub core_count: i64,
388 pub threads_per_core: i64,
389}
390
391#[derive(Clone, Debug, Serialize, Deserialize)]
393pub struct MaintenanceOptions {
394 pub auto_recovery: String,
396 pub reboot_migration: String,
398}
399
400impl Default for MaintenanceOptions {
401 fn default() -> Self {
402 Self {
403 auto_recovery: "default".to_string(),
404 reboot_migration: "default".to_string(),
405 }
406 }
407}
408
409#[derive(Clone, Debug, Serialize, Deserialize)]
411pub struct VolumeAttachment {
412 pub volume_id: String,
413 pub instance_id: String,
414 pub device: String,
415 pub status: String,
417 pub delete_on_termination: bool,
418}
419
420#[derive(Clone, Debug, Serialize, Deserialize)]
422pub struct Volume {
423 pub volume_id: String,
424 pub size: i64,
425 pub snapshot_id: Option<String>,
426 pub availability_zone: String,
427 pub state: String,
429 pub volume_type: String,
430 pub iops: Option<i64>,
431 pub throughput: Option<i64>,
432 pub encrypted: bool,
433 pub kms_key_id: Option<String>,
434 pub multi_attach_enabled: bool,
435 pub auto_enable_io: bool,
436 #[serde(default)]
437 pub attachments: Vec<VolumeAttachment>,
438 #[serde(default)]
439 pub in_recycle_bin: bool,
440}
441
442#[derive(Clone, Debug, Serialize, Deserialize)]
444pub struct Snapshot {
445 pub snapshot_id: String,
446 pub volume_id: String,
447 pub state: String,
449 pub volume_size: i64,
450 pub description: String,
451 pub encrypted: bool,
452 pub storage_tier: String,
454 #[serde(default)]
455 pub in_recycle_bin: bool,
456 #[serde(default)]
457 pub locked: bool,
458 pub lock_mode: Option<String>,
459}
460
461#[derive(Clone, Debug, Serialize, Deserialize)]
463pub struct Image {
464 pub image_id: String,
465 pub name: String,
466 pub description: String,
467 pub state: String,
469 pub architecture: String,
470 pub public: bool,
471 pub source_instance_id: Option<String>,
472 #[serde(default)]
473 pub in_recycle_bin: bool,
474 pub deprecation_time: Option<String>,
475 #[serde(default)]
476 pub deregistration_protection: bool,
477 #[serde(default)]
480 pub launch_permission_users: Vec<String>,
481 #[serde(default)]
483 pub launch_permission_groups: Vec<String>,
484 #[serde(default)]
487 pub boot_mode: Option<String>,
488}
489
490#[derive(Clone, Debug, Serialize, Deserialize)]
492pub struct NetworkAclEntry {
493 pub rule_number: i64,
494 pub protocol: String,
495 pub rule_action: String,
497 pub egress: bool,
498 pub cidr_block: Option<String>,
499 pub ipv6_cidr_block: Option<String>,
500 pub port_range: Option<(i64, i64)>,
502 pub icmp_type_code: Option<(i64, i64)>,
504}
505
506#[derive(Clone, Debug, Serialize, Deserialize)]
508pub struct NetworkAclAssoc {
509 pub association_id: String,
510 pub subnet_id: String,
511}
512
513#[derive(Clone, Debug, Serialize, Deserialize)]
515pub struct NetworkAcl {
516 pub network_acl_id: String,
517 pub vpc_id: String,
518 pub is_default: bool,
519 #[serde(default)]
520 pub entries: Vec<NetworkAclEntry>,
521 #[serde(default)]
522 pub associations: Vec<NetworkAclAssoc>,
523}
524
525#[derive(Clone, Debug, Serialize, Deserialize)]
527pub struct VpcPeering {
528 pub id: String,
529 pub requester_vpc_id: String,
530 pub accepter_vpc_id: String,
531 pub status: String,
533 #[serde(default)]
535 pub requester_allow_dns: bool,
536 #[serde(default)]
538 pub accepter_allow_dns: bool,
539}
540
541#[derive(Clone, Debug, Serialize, Deserialize)]
543pub struct VpcEndpoint {
544 pub id: String,
545 pub endpoint_type: String,
547 pub vpc_id: String,
548 pub service_name: String,
549 pub state: String,
550 #[serde(default)]
551 pub subnet_ids: Vec<String>,
552 #[serde(default)]
553 pub route_table_ids: Vec<String>,
554 #[serde(default)]
555 pub private_dns_enabled: bool,
556}
557
558#[derive(Clone, Debug, Serialize, Deserialize)]
560pub struct EndpointService {
561 pub service_id: String,
562 pub service_name: String,
563 pub state: String,
564 pub acceptance_required: bool,
565 pub payer_responsibility: String,
566 #[serde(default)]
567 pub nlb_arns: Vec<String>,
568}
569
570#[derive(Clone, Debug, Serialize, Deserialize)]
572pub struct ConnectionNotification {
573 pub id: String,
574 pub arn: String,
575 pub service_id: Option<String>,
576 #[serde(default)]
577 pub events: Vec<String>,
578}
579
580#[derive(Clone, Debug, Serialize, Deserialize)]
582pub struct FlowLog {
583 pub id: String,
584 pub resource_id: String,
585 pub traffic_type: String,
586 pub log_destination_type: String,
587 pub log_group_name: Option<String>,
588 pub log_destination: Option<String>,
590}
591
592#[derive(Clone, Debug, Serialize, Deserialize)]
594pub struct LaunchTemplate {
595 pub id: String,
596 pub name: String,
597 pub default_version: i64,
598 pub latest_version: i64,
599}
600
601#[derive(Clone, Debug, Serialize, Deserialize)]
603pub struct SpotRequest {
604 pub id: String,
605 pub state: String,
607 pub request_type: String,
608 pub spot_price: String,
609}
610
611#[derive(Clone, Debug, Serialize, Deserialize)]
613pub struct SpotFleet {
614 pub id: String,
615 pub state: String,
616}
617
618#[derive(Clone, Debug, Serialize, Deserialize)]
620pub struct Fleet {
621 pub id: String,
622 pub state: String,
623 pub fleet_type: String,
624}
625
626#[derive(Clone, Debug, Serialize, Deserialize)]
628pub struct CapacityReservation {
629 pub id: String,
630 pub instance_type: String,
631 pub instance_platform: String,
632 pub availability_zone: String,
633 pub tenancy: String,
634 pub total_instance_count: i64,
635 pub available_instance_count: i64,
636 pub state: String,
638 pub end_date_type: String,
639 pub instance_match_criteria: String,
640}
641
642#[derive(Clone, Debug, Serialize, Deserialize)]
644pub struct ReservedInstances {
645 pub id: String,
646 pub instance_type: String,
647 pub availability_zone: String,
648 pub instance_count: i64,
649 pub product_description: String,
650 pub state: String,
651 pub duration: i64,
652 pub fixed_price: String,
653 pub usage_price: String,
654}
655
656#[derive(Clone, Debug, Serialize, Deserialize)]
658pub struct ReservedInstancesListing {
659 pub listing_id: String,
660 pub reserved_instances_id: String,
661 pub instance_count: i64,
662 pub client_token: String,
663 pub status: String,
665 pub status_message: String,
666}
667
668#[derive(Clone, Debug, Serialize, Deserialize)]
670pub struct ReservedInstancesModification {
671 pub modification_id: String,
672 pub reserved_instances_ids: Vec<String>,
673 pub status: String,
675 pub client_token: String,
676}
677
678#[derive(Clone, Debug, Serialize, Deserialize)]
680pub struct DedicatedHost {
681 pub id: String,
682 pub auto_placement: String,
683 pub availability_zone: String,
684 pub instance_type: String,
685 pub state: String,
686 pub host_recovery: String,
687 pub host_maintenance: String,
688}
689
690#[derive(Clone, Debug, Serialize, Deserialize)]
692pub struct TransitGateway {
693 pub id: String,
694 pub description: String,
695 #[serde(default = "tgw_default_state")]
697 pub state: String,
698}
699
700fn tgw_default_state() -> String {
701 "available".to_string()
702}
703
704#[derive(Clone, Debug, Serialize, Deserialize)]
706pub struct TgwAttachment {
707 pub id: String,
708 pub tgw_id: String,
709 pub resource_id: String,
710 pub resource_type: String,
711 #[serde(default)]
712 pub subnet_ids: Vec<String>,
713 pub state: String,
714}
715
716#[derive(Clone, Debug, Serialize, Deserialize)]
718pub struct TgwRouteTable {
719 pub id: String,
720 pub tgw_id: String,
721}
722
723#[derive(Clone, Debug, Serialize, Deserialize)]
725pub struct TgwRoute {
726 pub cidr: String,
727 pub attachment_id: String,
728 pub state: String,
729}
730
731#[derive(Clone, Debug, Serialize, Deserialize)]
733pub struct TgwMulticastDomain {
734 pub id: String,
735 pub tgw_id: String,
736}
737
738#[derive(Clone, Debug, Serialize, Deserialize)]
740pub struct TgwMeteringPolicy {
741 pub id: String,
742 pub tgw_id: String,
743}
744
745#[derive(Clone, Debug, Serialize, Deserialize)]
747pub struct CustomerGateway {
748 pub id: String,
749 pub state: String,
750 pub ip_address: String,
751 pub bgp_asn: String,
752}
753
754#[derive(Clone, Debug, Serialize, Deserialize)]
756pub struct VpnGateway {
757 pub id: String,
758 pub state: String,
759 #[serde(default)]
760 pub attachments: Vec<String>,
761}
762
763#[derive(Clone, Debug, Serialize, Deserialize)]
765pub struct VpnConnection {
766 pub id: String,
767 pub state: String,
768 pub customer_gateway_id: String,
769 pub vpn_gateway_id: Option<String>,
770 #[serde(default)]
771 pub routes: Vec<String>,
772}
773
774#[derive(Clone, Debug, Serialize, Deserialize)]
776pub struct VpnConcentrator {
777 pub id: String,
778 pub state: String,
779}
780
781#[derive(Clone, Debug, Serialize, Deserialize)]
783pub struct Ipam {
784 pub id: String,
785 pub public_scope_id: String,
786 pub private_scope_id: String,
787 pub tier: String,
788 #[serde(default)]
789 pub description: String,
790}
791
792#[derive(Clone, Debug, Serialize, Deserialize)]
794pub struct IpamScope {
795 pub id: String,
796 pub ipam_id: String,
797 #[serde(default)]
799 pub scope_type: String,
800 #[serde(default)]
801 pub description: String,
802}
803
804#[derive(Clone, Debug, Serialize, Deserialize)]
806pub struct IpamPool {
807 pub id: String,
808 pub scope_id: String,
809 pub address_family: String,
810 #[serde(default)]
811 pub description: String,
812}
813
814#[derive(Clone, Debug, Serialize, Deserialize)]
816pub struct IpamResourceDiscovery {
817 pub id: String,
818 #[serde(default)]
819 pub description: String,
820}
821
822#[derive(Clone, Debug, Serialize, Deserialize)]
824pub struct IpamPolicy {
825 pub id: String,
826 pub ipam_id: String,
827}
828
829#[derive(Clone, Debug, Serialize, Deserialize)]
831pub struct IpamPrefixListResolver {
832 pub id: String,
833 pub ipam_id: String,
834 pub address_family: String,
835 #[serde(default)]
836 pub description: String,
837}
838
839#[derive(Clone, Debug, Serialize, Deserialize)]
841pub struct IpamPrefixListResolverTarget {
842 pub id: String,
843 pub resolver_id: String,
844 pub prefix_list_id: String,
845 pub prefix_list_region: String,
846 #[serde(default)]
847 pub track_latest_version: bool,
848}
849
850#[derive(Clone, Debug, Serialize, Deserialize)]
852pub struct VerifiedAccessInstance {
853 pub id: String,
854 pub description: String,
855 #[serde(default)]
856 pub trust_providers: Vec<String>,
857}
858
859#[derive(Clone, Debug, Serialize, Deserialize)]
861pub struct VerifiedAccessTrustProvider {
862 pub id: String,
863 pub trust_provider_type: String,
864 pub policy_reference_name: String,
865 pub description: String,
866}
867
868#[derive(Clone, Debug, Serialize, Deserialize)]
870pub struct VerifiedAccessGroup {
871 pub id: String,
872 pub instance_id: String,
873 pub description: String,
874}
875
876#[derive(Clone, Debug, Serialize, Deserialize)]
878pub struct VerifiedAccessEndpoint {
879 pub id: String,
880 pub group_id: String,
881 pub instance_id: String,
882 pub endpoint_type: String,
883 pub attachment_type: String,
884}
885
886#[derive(Clone, Debug, Serialize, Deserialize)]
888pub struct NetworkInsightsPath {
889 pub id: String,
890 pub source: String,
891 pub destination: String,
892 pub protocol: String,
893}
894
895#[derive(Clone, Debug, Serialize, Deserialize)]
897pub struct NetworkInsightsAnalysis {
898 pub id: String,
899 pub path_id: String,
900}
901
902#[derive(Clone, Debug, Serialize, Deserialize)]
904pub struct NetworkInsightsAccessScope {
905 pub id: String,
906}
907
908#[derive(Clone, Debug, Serialize, Deserialize)]
910pub struct NetworkInsightsAccessScopeAnalysis {
911 pub id: String,
912 pub scope_id: String,
913}
914
915#[derive(Clone, Debug, Serialize, Deserialize)]
917pub struct CarrierGateway {
918 pub id: String,
919 pub vpc_id: String,
920}
921
922#[derive(Clone, Debug, Serialize, Deserialize)]
924pub struct InstanceConnectEndpoint {
925 pub id: String,
926 pub subnet_id: String,
927}
928
929#[derive(Clone, Debug, Serialize, Deserialize)]
931pub struct CoipPool {
932 pub id: String,
933 pub route_table_id: String,
934}
935
936#[derive(Clone, Debug, Serialize, Deserialize)]
938pub struct LocalGatewayRouteTable {
939 pub id: String,
940 pub local_gateway_id: String,
941 pub mode: String,
942}
943
944#[derive(Clone, Debug, Serialize, Deserialize)]
946pub struct LocalGatewayRouteTableVpcAssoc {
947 pub id: String,
948 pub route_table_id: String,
949 pub vpc_id: String,
950}
951
952#[derive(Clone, Debug, Serialize, Deserialize)]
954pub struct LocalGatewayVif {
955 pub id: String,
956 pub group_id: String,
957 pub vlan: String,
958 pub local_address: String,
959 pub peer_address: String,
960}
961
962#[derive(Clone, Debug, Serialize, Deserialize)]
964pub struct LocalGatewayVifGroup {
965 pub id: String,
966 pub local_gateway_id: String,
967}
968
969#[derive(Clone, Debug, Serialize, Deserialize)]
971pub struct LocalGatewayRouteTableVifgAssoc {
972 pub id: String,
973 pub route_table_id: String,
974 pub vif_group_id: String,
975}
976
977#[derive(Clone, Debug, Serialize, Deserialize)]
979pub struct ClientVpnEndpoint {
980 pub id: String,
981 pub description: String,
982 pub status: String,
983 pub server_cert_arn: String,
984 pub transport_protocol: String,
985 pub client_cidr: String,
986 #[serde(default)]
987 pub routes: Vec<String>,
988 #[serde(default)]
990 pub target_networks: Vec<(String, String)>,
991 #[serde(default)]
993 pub auth_rules: Vec<String>,
994}
995
996#[derive(Clone, Debug, Serialize, Deserialize)]
998pub struct TgwPeering {
999 pub id: String,
1000 pub tgw_id: String,
1001 pub peer_tgw_id: String,
1002 pub peer_account: String,
1003 pub peer_region: String,
1004 pub state: String,
1005}
1006
1007#[derive(Clone, Debug, Default, Serialize, Deserialize)]
1010pub struct Ec2State {
1011 pub account_id: String,
1012 pub region: String,
1013 #[serde(default)]
1015 pub tags: BTreeMap<String, Vec<Tag>>,
1016 #[serde(default)]
1017 pub vpcs: BTreeMap<String, Vpc>,
1018 #[serde(default)]
1019 pub dhcp_options: BTreeMap<String, DhcpOptions>,
1020 #[serde(default)]
1021 pub subnets: BTreeMap<String, Subnet>,
1022 #[serde(default)]
1023 pub subnet_cidr_reservations: BTreeMap<String, SubnetCidrReservation>,
1024 #[serde(default)]
1025 pub security_groups: BTreeMap<String, SecurityGroup>,
1026 #[serde(default)]
1027 pub route_tables: BTreeMap<String, RouteTable>,
1028 #[serde(default)]
1029 pub internet_gateways: BTreeMap<String, InternetGateway>,
1030 #[serde(default)]
1031 pub egress_only_igws: BTreeMap<String, InternetGateway>,
1032 #[serde(default)]
1033 pub nat_gateways: BTreeMap<String, NatGateway>,
1034 #[serde(default)]
1036 pub elastic_ips: BTreeMap<String, ElasticIp>,
1037 #[serde(default)]
1039 pub key_pairs: BTreeMap<String, KeyPair>,
1040 #[serde(default)]
1042 pub placement_groups: BTreeMap<String, PlacementGroup>,
1043 #[serde(default)]
1044 pub network_interfaces: BTreeMap<String, NetworkInterface>,
1045 #[serde(default)]
1047 pub eni_permissions: BTreeMap<String, NetworkInterfacePermission>,
1048 #[serde(default)]
1049 pub instances: BTreeMap<String, Instance>,
1050 #[serde(default)]
1051 pub volumes: BTreeMap<String, Volume>,
1052 #[serde(default)]
1054 pub ebs_encryption_default: bool,
1055 #[serde(default)]
1057 pub ebs_default_kms_key_id: Option<String>,
1058 #[serde(default)]
1059 pub snapshots: BTreeMap<String, Snapshot>,
1060 #[serde(default)]
1062 pub snapshot_block_public_access: String,
1063 #[serde(default)]
1064 pub images: BTreeMap<String, Image>,
1065 #[serde(default)]
1067 pub image_watermarks: BTreeMap<String, BTreeMap<String, String>>,
1068 #[serde(default)]
1070 pub image_block_public_access: String,
1071 #[serde(default)]
1073 pub allowed_images_settings: String,
1074 #[serde(default)]
1075 pub network_acls: BTreeMap<String, NetworkAcl>,
1076 #[serde(default)]
1077 pub vpc_peerings: BTreeMap<String, VpcPeering>,
1078 #[serde(default)]
1079 pub vpc_endpoints: BTreeMap<String, VpcEndpoint>,
1080 #[serde(default)]
1081 pub endpoint_services: BTreeMap<String, EndpointService>,
1082 #[serde(default)]
1083 pub connection_notifications: BTreeMap<String, ConnectionNotification>,
1084 #[serde(default)]
1085 pub flow_logs: BTreeMap<String, FlowLog>,
1086 #[serde(default)]
1087 pub launch_templates: BTreeMap<String, LaunchTemplate>,
1088 #[serde(default)]
1089 pub spot_requests: BTreeMap<String, SpotRequest>,
1090 #[serde(default)]
1091 pub spot_fleets: BTreeMap<String, SpotFleet>,
1092 #[serde(default)]
1093 pub fleets: BTreeMap<String, Fleet>,
1094 #[serde(default)]
1096 pub spot_datafeed: Option<(String, String)>,
1097 #[serde(default)]
1098 pub capacity_reservations: BTreeMap<String, CapacityReservation>,
1099 #[serde(default)]
1101 pub capacity_reservation_fleets: BTreeMap<String, String>,
1102 #[serde(default)]
1103 pub reserved_instances: BTreeMap<String, ReservedInstances>,
1104 #[serde(default)]
1105 pub reserved_instances_listings: BTreeMap<String, ReservedInstancesListing>,
1106 #[serde(default)]
1107 pub reserved_instances_modifications: BTreeMap<String, ReservedInstancesModification>,
1108 #[serde(default)]
1109 pub dedicated_hosts: BTreeMap<String, DedicatedHost>,
1110 #[serde(default)]
1111 pub transit_gateways: BTreeMap<String, TransitGateway>,
1112 #[serde(default)]
1113 pub tgw_attachments: BTreeMap<String, TgwAttachment>,
1114 #[serde(default)]
1115 pub tgw_route_tables: BTreeMap<String, TgwRouteTable>,
1116 #[serde(default)]
1118 pub tgw_routes: BTreeMap<String, Vec<TgwRoute>>,
1119 #[serde(default)]
1121 pub tgw_rt_associations: BTreeMap<String, Vec<String>>,
1122 #[serde(default)]
1124 pub tgw_rt_propagations: BTreeMap<String, Vec<String>>,
1125 #[serde(default)]
1127 pub tgw_prefix_list_refs: BTreeMap<String, Vec<String>>,
1128 #[serde(default)]
1129 pub tgw_peerings: BTreeMap<String, TgwPeering>,
1130 #[serde(default)]
1132 pub tgw_connects: BTreeMap<String, (String, String)>,
1133 #[serde(default)]
1135 pub tgw_connect_peers: BTreeMap<String, String>,
1136 #[serde(default)]
1138 pub tgw_policy_tables: BTreeMap<String, String>,
1139 #[serde(default)]
1141 pub tgw_policy_table_associations: BTreeMap<String, Vec<String>>,
1142 #[serde(default)]
1144 pub tgw_announcements: BTreeMap<String, (String, String)>,
1145 #[serde(default)]
1146 pub tgw_multicast_domains: BTreeMap<String, TgwMulticastDomain>,
1147 #[serde(default)]
1148 pub tgw_metering_policies: BTreeMap<String, TgwMeteringPolicy>,
1149 #[serde(default)]
1150 pub customer_gateways: BTreeMap<String, CustomerGateway>,
1151 #[serde(default)]
1152 pub vpn_gateways: BTreeMap<String, VpnGateway>,
1153 #[serde(default)]
1154 pub vpn_connections: BTreeMap<String, VpnConnection>,
1155 #[serde(default)]
1156 pub vpn_concentrators: BTreeMap<String, VpnConcentrator>,
1157 #[serde(default)]
1158 pub client_vpn_endpoints: BTreeMap<String, ClientVpnEndpoint>,
1159 #[serde(default)]
1160 pub ipams: BTreeMap<String, Ipam>,
1161 #[serde(default)]
1162 pub ipam_scopes: BTreeMap<String, IpamScope>,
1163 #[serde(default)]
1164 pub ipam_pools: BTreeMap<String, IpamPool>,
1165 #[serde(default)]
1167 pub ipam_pool_cidrs: BTreeMap<String, Vec<(String, String)>>,
1168 #[serde(default)]
1170 pub ipam_pool_allocations: BTreeMap<String, Vec<(String, String)>>,
1171 #[serde(default)]
1172 pub ipam_resource_discoveries: BTreeMap<String, IpamResourceDiscovery>,
1173 #[serde(default)]
1175 pub ipam_rd_associations: BTreeMap<String, (String, String)>,
1176 #[serde(default)]
1178 pub ipam_byoasns: BTreeMap<String, String>,
1179 #[serde(default)]
1181 pub ipam_ext_tokens: BTreeMap<String, String>,
1182 #[serde(default)]
1183 pub ipam_policies: BTreeMap<String, IpamPolicy>,
1184 #[serde(default)]
1185 pub ipam_pl_resolvers: BTreeMap<String, IpamPrefixListResolver>,
1186 #[serde(default)]
1187 pub ipam_pl_resolver_targets: BTreeMap<String, IpamPrefixListResolverTarget>,
1188 #[serde(default)]
1190 pub ipam_policy_alloc_rules: BTreeMap<String, Vec<(String, String)>>,
1191 #[serde(default)]
1193 pub ipam_enabled_policy: Option<String>,
1194 #[serde(default)]
1195 pub va_instances: BTreeMap<String, VerifiedAccessInstance>,
1196 #[serde(default)]
1197 pub va_trust_providers: BTreeMap<String, VerifiedAccessTrustProvider>,
1198 #[serde(default)]
1199 pub va_groups: BTreeMap<String, VerifiedAccessGroup>,
1200 #[serde(default)]
1201 pub va_endpoints: BTreeMap<String, VerifiedAccessEndpoint>,
1202 #[serde(default)]
1204 pub va_group_policies: BTreeMap<String, String>,
1205 #[serde(default)]
1207 pub va_endpoint_policies: BTreeMap<String, String>,
1208 #[serde(default)]
1209 pub ni_paths: BTreeMap<String, NetworkInsightsPath>,
1210 #[serde(default)]
1211 pub ni_analyses: BTreeMap<String, NetworkInsightsAnalysis>,
1212 #[serde(default)]
1213 pub ni_access_scopes: BTreeMap<String, NetworkInsightsAccessScope>,
1214 #[serde(default)]
1215 pub ni_scope_analyses: BTreeMap<String, NetworkInsightsAccessScopeAnalysis>,
1216 #[serde(default)]
1217 pub carrier_gateways: BTreeMap<String, CarrierGateway>,
1218 #[serde(default)]
1219 pub coip_pools: BTreeMap<String, CoipPool>,
1220 #[serde(default)]
1222 pub coip_pool_cidrs: BTreeMap<String, Vec<String>>,
1223 #[serde(default)]
1224 pub lg_route_tables: BTreeMap<String, LocalGatewayRouteTable>,
1225 #[serde(default)]
1227 pub lg_routes: BTreeMap<String, Vec<String>>,
1228 #[serde(default)]
1229 pub lg_rt_vpc_assocs: BTreeMap<String, LocalGatewayRouteTableVpcAssoc>,
1230 #[serde(default)]
1231 pub lg_virtual_interfaces: BTreeMap<String, LocalGatewayVif>,
1232 #[serde(default)]
1233 pub lg_vif_groups: BTreeMap<String, LocalGatewayVifGroup>,
1234 #[serde(default)]
1235 pub lg_rt_vifg_assocs: BTreeMap<String, LocalGatewayRouteTableVifgAssoc>,
1236 #[serde(default)]
1237 pub instance_connect_endpoints: BTreeMap<String, InstanceConnectEndpoint>,
1238 #[serde(default)]
1240 pub fast_launch_images: std::collections::HashSet<String>,
1241 #[serde(default)]
1242 pub serial_console_access: bool,
1243}
1244
1245impl Ec2State {
1246 pub fn new(account_id: &str, region: &str) -> Self {
1247 let mut state = Self {
1248 account_id: account_id.to_string(),
1249 region: region.to_string(),
1250 ..Default::default()
1251 };
1252 crate::defaults::bootstrap_default_network(&mut state);
1258 state
1259 }
1260
1261 pub fn upsert_tags(&mut self, resource_id: &str, new_tags: &[Tag]) {
1264 let entry = self.tags.entry(resource_id.to_string()).or_default();
1265 for t in new_tags {
1266 if let Some(existing) = entry.iter_mut().find(|e| e.key == t.key) {
1267 existing.value = t.value.clone();
1268 } else {
1269 entry.push(t.clone());
1270 }
1271 }
1272 }
1273
1274 pub fn remove_tags(&mut self, resource_id: &str, to_remove: &[(String, Option<String>)]) {
1278 if let Some(entry) = self.tags.get_mut(resource_id) {
1279 for (key, value) in to_remove {
1280 entry.retain(|e| {
1281 if &e.key != key {
1282 return true;
1283 }
1284 match value {
1285 Some(v) => &e.value != v,
1286 None => false,
1287 }
1288 });
1289 }
1290 if entry.is_empty() {
1291 self.tags.remove(resource_id);
1292 }
1293 }
1294 }
1295
1296 pub fn tags_for(&self, resource_id: &str) -> &[Tag] {
1298 self.tags.get(resource_id).map(Vec::as_slice).unwrap_or(&[])
1299 }
1300}
1301
1302#[cfg(test)]
1303mod tests {
1304 use super::*;
1305
1306 fn tag(k: &str, v: &str) -> Tag {
1307 Tag {
1308 key: k.to_string(),
1309 value: v.to_string(),
1310 }
1311 }
1312
1313 #[test]
1314 fn upsert_tags_inserts_then_overwrites_by_key() {
1315 let mut s = Ec2State::new("123456789012", "us-east-1");
1316 s.upsert_tags("vpc-1", &[tag("Name", "a"), tag("env", "dev")]);
1317 s.upsert_tags("vpc-1", &[tag("Name", "b")]);
1318 let tags = s.tags_for("vpc-1");
1319 assert_eq!(tags.len(), 2);
1320 assert_eq!(tags.iter().find(|t| t.key == "Name").unwrap().value, "b");
1321 }
1322
1323 #[test]
1324 fn remove_tags_by_key_and_by_key_value() {
1325 let mut s = Ec2State::new("123456789012", "us-east-1");
1326 s.upsert_tags(
1327 "i-1",
1328 &[tag("Name", "x"), tag("env", "prod"), tag("team", "a")],
1329 );
1330 s.remove_tags("i-1", &[("Name".to_string(), None)]);
1332 s.remove_tags("i-1", &[("env".to_string(), Some("dev".to_string()))]);
1334 s.remove_tags("i-1", &[("team".to_string(), Some("a".to_string()))]);
1336 let tags = s.tags_for("i-1");
1337 assert_eq!(tags.len(), 1);
1338 assert_eq!(tags[0].key, "env");
1339 }
1340
1341 #[test]
1342 fn empty_tag_set_drops_resource_entry() {
1343 let mut s = Ec2State::new("123456789012", "us-east-1");
1344 s.upsert_tags("sg-1", &[tag("Name", "x")]);
1345 s.remove_tags("sg-1", &[("Name".to_string(), None)]);
1346 assert!(!s.tags.contains_key("sg-1"));
1347 }
1348
1349 fn sample_instance() -> Instance {
1350 Instance {
1351 instance_id: "i-1".to_string(),
1352 image_id: "ami-1".to_string(),
1353 instance_type: "t3.micro".to_string(),
1354 state_code: 16,
1355 state_name: "running".to_string(),
1356 private_ip: "10.0.0.1".to_string(),
1357 public_ip: Some("52.0.0.1".to_string()),
1358 subnet_id: Some("subnet-1".to_string()),
1359 vpc_id: Some("vpc-1".to_string()),
1360 key_name: None,
1361 security_group_ids: vec!["sg-1".to_string()],
1362 reservation_id: "r-1".to_string(),
1363 ami_launch_index: 0,
1364 monitoring: false,
1365 az: "us-east-1a".to_string(),
1366 launch_time: "2024-01-01T00:00:00.000Z".to_string(),
1367 container_id: Some("abc".to_string()),
1368 disable_api_termination: true,
1369 disable_api_stop: true,
1370 source_dest_check: false,
1371 ebs_optimized: true,
1372 instance_initiated_shutdown_behavior: "terminate".to_string(),
1373 user_data: Some("ZWNobyBoaQ==".to_string()),
1374 metadata_options: MetadataOptions {
1375 http_tokens: "required".to_string(),
1376 ..MetadataOptions::default()
1377 },
1378 cpu_options: Some(CpuOptions {
1379 core_count: 4,
1380 threads_per_core: 2,
1381 }),
1382 bandwidth_weighting: Some("vpc-1".to_string()),
1383 maintenance_options: MaintenanceOptions::default(),
1384 placement_tenancy: Some("dedicated".to_string()),
1385 placement_affinity: None,
1386 placement_group_name: Some("cluster-1".to_string()),
1387 }
1388 }
1389
1390 #[test]
1391 fn instance_attributes_round_trip_through_serde() {
1392 let inst = sample_instance();
1393 let json = serde_json::to_string(&inst).unwrap();
1394 let back: Instance = serde_json::from_str(&json).unwrap();
1395 assert!(back.disable_api_termination);
1396 assert!(back.disable_api_stop);
1397 assert!(!back.source_dest_check);
1398 assert!(back.ebs_optimized);
1399 assert_eq!(back.instance_initiated_shutdown_behavior, "terminate");
1400 assert_eq!(back.user_data.as_deref(), Some("ZWNobyBoaQ=="));
1401 assert_eq!(back.metadata_options.http_tokens, "required");
1402 assert_eq!(back.cpu_options.as_ref().unwrap().core_count, 4);
1403 assert_eq!(back.bandwidth_weighting.as_deref(), Some("vpc-1"));
1404 assert_eq!(back.placement_tenancy.as_deref(), Some("dedicated"));
1405 assert_eq!(back.placement_group_name.as_deref(), Some("cluster-1"));
1406 }
1407
1408 #[test]
1409 fn instance_attribute_defaults_load_from_legacy_snapshot() {
1410 let legacy = r#"{
1413 "instance_id":"i-1","image_id":"ami-1","instance_type":"t3.micro",
1414 "state_code":16,"state_name":"running","private_ip":"10.0.0.1",
1415 "public_ip":null,"subnet_id":null,"vpc_id":null,"key_name":null,
1416 "reservation_id":"r-1","ami_launch_index":0,"monitoring":false,
1417 "az":"us-east-1a","launch_time":"2024-01-01T00:00:00.000Z"
1418 }"#;
1419 let inst: Instance = serde_json::from_str(legacy).unwrap();
1420 assert!(!inst.disable_api_termination);
1421 assert!(inst.source_dest_check, "sourceDestCheck defaults to true");
1422 assert_eq!(inst.instance_initiated_shutdown_behavior, "stop");
1423 assert_eq!(inst.metadata_options.http_tokens, "optional");
1424 assert!(inst.cpu_options.is_none());
1425 }
1426}