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 #[serde(default)]
286 pub public_ip_dns_hostname_type: Option<String>,
287}
288
289#[derive(Clone, Debug, Serialize, Deserialize)]
291pub struct NetworkInterfacePermission {
292 pub permission_id: String,
293 pub network_interface_id: String,
294 pub aws_account_id: String,
295 pub permission: String,
297}
298
299#[derive(Clone, Debug, Serialize, Deserialize)]
301pub struct Instance {
302 pub instance_id: String,
303 pub image_id: String,
304 pub instance_type: String,
305 pub state_code: i64,
308 pub state_name: String,
309 pub private_ip: String,
310 pub public_ip: Option<String>,
311 pub subnet_id: Option<String>,
312 pub vpc_id: Option<String>,
313 pub key_name: Option<String>,
314 #[serde(default)]
315 pub security_group_ids: Vec<String>,
316 pub reservation_id: String,
317 pub ami_launch_index: i64,
318 pub monitoring: bool,
319 pub az: String,
320 pub launch_time: String,
321 #[serde(default)]
324 pub container_id: Option<String>,
325 #[serde(default)]
328 pub disable_api_termination: bool,
329 #[serde(default)]
331 pub disable_api_stop: bool,
332 #[serde(default = "default_true")]
334 pub source_dest_check: bool,
335 #[serde(default)]
337 pub ebs_optimized: bool,
338 #[serde(default = "default_shutdown_behavior")]
340 pub instance_initiated_shutdown_behavior: String,
341 #[serde(default)]
343 pub user_data: Option<String>,
344 #[serde(default)]
347 pub metadata_options: MetadataOptions,
348 #[serde(default)]
350 pub cpu_options: Option<CpuOptions>,
351 #[serde(default)]
353 pub bandwidth_weighting: Option<String>,
354 #[serde(default)]
356 pub maintenance_options: MaintenanceOptions,
357 #[serde(default)]
359 pub placement_tenancy: Option<String>,
360 #[serde(default)]
361 pub placement_affinity: Option<String>,
362 #[serde(default)]
363 pub placement_group_name: Option<String>,
364 #[serde(default)]
368 pub private_dns_hostname_type: Option<String>,
369 #[serde(default)]
371 pub enable_resource_name_dns_a_record: bool,
372 #[serde(default)]
374 pub enable_resource_name_dns_aaaa_record: bool,
375}
376
377fn default_true() -> bool {
378 true
379}
380
381fn default_shutdown_behavior() -> String {
382 "stop".to_string()
383}
384
385#[derive(Clone, Debug, Serialize, Deserialize)]
388pub struct MetadataOptions {
389 pub http_tokens: String,
391 pub http_endpoint: String,
393 pub http_put_response_hop_limit: i64,
394 pub http_protocol_ipv6: String,
396 pub instance_metadata_tags: String,
398}
399
400impl Default for MetadataOptions {
401 fn default() -> Self {
402 Self {
403 http_tokens: "optional".to_string(),
404 http_endpoint: "enabled".to_string(),
405 http_put_response_hop_limit: 1,
406 http_protocol_ipv6: "disabled".to_string(),
407 instance_metadata_tags: "disabled".to_string(),
408 }
409 }
410}
411
412#[derive(Clone, Debug, Serialize, Deserialize)]
414pub struct CpuOptions {
415 pub core_count: i64,
416 pub threads_per_core: i64,
417}
418
419#[derive(Clone, Debug, Serialize, Deserialize)]
421pub struct MaintenanceOptions {
422 pub auto_recovery: String,
424 pub reboot_migration: String,
426}
427
428impl Default for MaintenanceOptions {
429 fn default() -> Self {
430 Self {
431 auto_recovery: "default".to_string(),
432 reboot_migration: "default".to_string(),
433 }
434 }
435}
436
437#[derive(Clone, Debug, Serialize, Deserialize)]
439pub struct VolumeAttachment {
440 pub volume_id: String,
441 pub instance_id: String,
442 pub device: String,
443 pub status: String,
445 pub delete_on_termination: bool,
446}
447
448#[derive(Clone, Debug, Serialize, Deserialize)]
450pub struct Volume {
451 pub volume_id: String,
452 pub size: i64,
453 pub snapshot_id: Option<String>,
454 pub availability_zone: String,
455 pub state: String,
457 pub volume_type: String,
458 pub iops: Option<i64>,
459 pub throughput: Option<i64>,
460 pub encrypted: bool,
461 pub kms_key_id: Option<String>,
462 pub multi_attach_enabled: bool,
463 pub auto_enable_io: bool,
464 #[serde(default)]
465 pub attachments: Vec<VolumeAttachment>,
466 #[serde(default)]
467 pub in_recycle_bin: bool,
468}
469
470#[derive(Clone, Debug, Serialize, Deserialize)]
472pub struct Snapshot {
473 pub snapshot_id: String,
474 pub volume_id: String,
475 pub state: String,
477 pub volume_size: i64,
478 pub description: String,
479 pub encrypted: bool,
480 pub storage_tier: String,
482 #[serde(default)]
483 pub in_recycle_bin: bool,
484 #[serde(default)]
485 pub locked: bool,
486 pub lock_mode: Option<String>,
487}
488
489#[derive(Clone, Debug, Serialize, Deserialize)]
491pub struct Image {
492 pub image_id: String,
493 pub name: String,
494 pub description: String,
495 pub state: String,
497 pub architecture: String,
498 pub public: bool,
499 pub source_instance_id: Option<String>,
500 #[serde(default)]
501 pub in_recycle_bin: bool,
502 pub deprecation_time: Option<String>,
503 #[serde(default)]
504 pub deregistration_protection: bool,
505 #[serde(default)]
508 pub launch_permission_users: Vec<String>,
509 #[serde(default)]
511 pub launch_permission_groups: Vec<String>,
512 #[serde(default)]
515 pub boot_mode: Option<String>,
516 #[serde(default)]
521 pub owner_id: Option<String>,
522 #[serde(default)]
526 pub owner_alias: Option<String>,
527 #[serde(default)]
531 pub creation_date: Option<String>,
532 #[serde(default)]
535 pub root_device_name: Option<String>,
536 #[serde(default)]
538 pub platform: Option<String>,
539}
540
541#[derive(Clone, Debug, Serialize, Deserialize)]
543pub struct NetworkAclEntry {
544 pub rule_number: i64,
545 pub protocol: String,
546 pub rule_action: String,
548 pub egress: bool,
549 pub cidr_block: Option<String>,
550 pub ipv6_cidr_block: Option<String>,
551 pub port_range: Option<(i64, i64)>,
553 pub icmp_type_code: Option<(i64, i64)>,
555}
556
557#[derive(Clone, Debug, Serialize, Deserialize)]
559pub struct NetworkAclAssoc {
560 pub association_id: String,
561 pub subnet_id: String,
562}
563
564#[derive(Clone, Debug, Serialize, Deserialize)]
566pub struct NetworkAcl {
567 pub network_acl_id: String,
568 pub vpc_id: String,
569 pub is_default: bool,
570 #[serde(default)]
571 pub entries: Vec<NetworkAclEntry>,
572 #[serde(default)]
573 pub associations: Vec<NetworkAclAssoc>,
574}
575
576#[derive(Clone, Debug, Serialize, Deserialize)]
578pub struct VpcPeering {
579 pub id: String,
580 pub requester_vpc_id: String,
581 pub accepter_vpc_id: String,
582 pub status: String,
584 #[serde(default)]
586 pub requester_allow_dns: bool,
587 #[serde(default)]
589 pub accepter_allow_dns: bool,
590}
591
592#[derive(Clone, Debug, Serialize, Deserialize)]
594pub struct VpcEndpoint {
595 pub id: String,
596 pub endpoint_type: String,
598 pub vpc_id: String,
599 pub service_name: String,
600 pub state: String,
601 #[serde(default)]
602 pub subnet_ids: Vec<String>,
603 #[serde(default)]
604 pub route_table_ids: Vec<String>,
605 #[serde(default)]
606 pub private_dns_enabled: bool,
607}
608
609#[derive(Clone, Debug, Serialize, Deserialize)]
611pub struct EndpointService {
612 pub service_id: String,
613 pub service_name: String,
614 pub state: String,
615 pub acceptance_required: bool,
616 pub payer_responsibility: String,
617 #[serde(default)]
618 pub nlb_arns: Vec<String>,
619}
620
621#[derive(Clone, Debug, Serialize, Deserialize)]
623pub struct ConnectionNotification {
624 pub id: String,
625 pub arn: String,
626 pub service_id: Option<String>,
627 #[serde(default)]
628 pub events: Vec<String>,
629}
630
631#[derive(Clone, Debug, Serialize, Deserialize)]
633pub struct FlowLog {
634 pub id: String,
635 pub resource_id: String,
636 pub traffic_type: String,
637 pub log_destination_type: String,
638 pub log_group_name: Option<String>,
639 pub log_destination: Option<String>,
641 #[serde(default)]
644 pub deliver_logs_permission_arn: Option<String>,
645 #[serde(default = "default_max_aggregation_interval")]
648 pub max_aggregation_interval: i64,
649}
650
651fn default_max_aggregation_interval() -> i64 {
652 600
653}
654
655#[derive(Clone, Debug, Serialize, Deserialize)]
657pub struct LaunchTemplate {
658 pub id: String,
659 pub name: String,
660 pub default_version: i64,
661 pub latest_version: i64,
662}
663
664#[derive(Clone, Debug, Serialize, Deserialize)]
666pub struct SpotRequest {
667 pub id: String,
668 pub state: String,
670 pub request_type: String,
671 pub spot_price: String,
672}
673
674#[derive(Clone, Debug, Serialize, Deserialize)]
676pub struct SpotFleet {
677 pub id: String,
678 pub state: String,
679}
680
681#[derive(Clone, Debug, Serialize, Deserialize)]
683pub struct Fleet {
684 pub id: String,
685 pub state: String,
686 pub fleet_type: String,
687}
688
689#[derive(Clone, Debug, Serialize, Deserialize)]
691pub struct CapacityReservation {
692 pub id: String,
693 pub instance_type: String,
694 pub instance_platform: String,
695 pub availability_zone: String,
696 pub tenancy: String,
697 pub total_instance_count: i64,
698 pub available_instance_count: i64,
699 pub state: String,
701 pub end_date_type: String,
702 pub instance_match_criteria: String,
703}
704
705#[derive(Clone, Debug, Serialize, Deserialize)]
707pub struct ReservedInstances {
708 pub id: String,
709 pub instance_type: String,
710 pub availability_zone: String,
711 pub instance_count: i64,
712 pub product_description: String,
713 pub state: String,
714 pub duration: i64,
715 pub fixed_price: String,
716 pub usage_price: String,
717}
718
719#[derive(Clone, Debug, Serialize, Deserialize)]
721pub struct ReservedInstancesListing {
722 pub listing_id: String,
723 pub reserved_instances_id: String,
724 pub instance_count: i64,
725 pub client_token: String,
726 pub status: String,
728 pub status_message: String,
729}
730
731#[derive(Clone, Debug, Serialize, Deserialize)]
733pub struct ReservedInstancesModification {
734 pub modification_id: String,
735 pub reserved_instances_ids: Vec<String>,
736 pub status: String,
738 pub client_token: String,
739}
740
741#[derive(Clone, Debug, Serialize, Deserialize)]
743pub struct DedicatedHost {
744 pub id: String,
745 pub auto_placement: String,
746 pub availability_zone: String,
747 pub instance_type: String,
748 pub state: String,
749 pub host_recovery: String,
750 pub host_maintenance: String,
751}
752
753#[derive(Clone, Debug, Serialize, Deserialize)]
755pub struct TransitGateway {
756 pub id: String,
757 pub description: String,
758 #[serde(default = "tgw_default_state")]
760 pub state: String,
761}
762
763fn tgw_default_state() -> String {
764 "available".to_string()
765}
766
767#[derive(Clone, Debug, Serialize, Deserialize)]
769pub struct TgwAttachment {
770 pub id: String,
771 pub tgw_id: String,
772 pub resource_id: String,
773 pub resource_type: String,
774 #[serde(default)]
775 pub subnet_ids: Vec<String>,
776 pub state: String,
777}
778
779#[derive(Clone, Debug, Serialize, Deserialize)]
781pub struct TgwRouteTable {
782 pub id: String,
783 pub tgw_id: String,
784}
785
786#[derive(Clone, Debug, Serialize, Deserialize)]
788pub struct TgwRoute {
789 pub cidr: String,
790 pub attachment_id: String,
791 pub state: String,
792}
793
794#[derive(Clone, Debug, Serialize, Deserialize)]
796pub struct TgwMulticastDomain {
797 pub id: String,
798 pub tgw_id: String,
799}
800
801#[derive(Clone, Debug, Serialize, Deserialize)]
803pub struct TgwMeteringPolicy {
804 pub id: String,
805 pub tgw_id: String,
806}
807
808#[derive(Clone, Debug, Serialize, Deserialize)]
810pub struct CustomerGateway {
811 pub id: String,
812 pub state: String,
813 pub ip_address: String,
814 pub bgp_asn: String,
815}
816
817#[derive(Clone, Debug, Serialize, Deserialize)]
819pub struct VpnGateway {
820 pub id: String,
821 pub state: String,
822 #[serde(default)]
823 pub attachments: Vec<String>,
824}
825
826#[derive(Clone, Debug, Serialize, Deserialize)]
828pub struct VpnConnection {
829 pub id: String,
830 pub state: String,
831 pub customer_gateway_id: String,
832 pub vpn_gateway_id: Option<String>,
833 #[serde(default)]
834 pub routes: Vec<String>,
835}
836
837#[derive(Clone, Debug, Serialize, Deserialize)]
839pub struct VpnConcentrator {
840 pub id: String,
841 pub state: String,
842}
843
844#[derive(Clone, Debug, Serialize, Deserialize)]
846pub struct Ipam {
847 pub id: String,
848 pub public_scope_id: String,
849 pub private_scope_id: String,
850 pub tier: String,
851 #[serde(default)]
852 pub description: String,
853}
854
855#[derive(Clone, Debug, Serialize, Deserialize)]
857pub struct IpamScope {
858 pub id: String,
859 pub ipam_id: String,
860 #[serde(default)]
862 pub scope_type: String,
863 #[serde(default)]
864 pub description: String,
865}
866
867#[derive(Clone, Debug, Serialize, Deserialize)]
869pub struct IpamPool {
870 pub id: String,
871 pub scope_id: String,
872 pub address_family: String,
873 #[serde(default)]
874 pub description: String,
875}
876
877#[derive(Clone, Debug, Serialize, Deserialize)]
879pub struct IpamResourceDiscovery {
880 pub id: String,
881 #[serde(default)]
882 pub description: String,
883}
884
885#[derive(Clone, Debug, Serialize, Deserialize)]
887pub struct IpamPolicy {
888 pub id: String,
889 pub ipam_id: String,
890}
891
892#[derive(Clone, Debug, Serialize, Deserialize)]
894pub struct IpamPrefixListResolver {
895 pub id: String,
896 pub ipam_id: String,
897 pub address_family: String,
898 #[serde(default)]
899 pub description: String,
900}
901
902#[derive(Clone, Debug, Serialize, Deserialize)]
904pub struct IpamPrefixListResolverTarget {
905 pub id: String,
906 pub resolver_id: String,
907 pub prefix_list_id: String,
908 pub prefix_list_region: String,
909 #[serde(default)]
910 pub track_latest_version: bool,
911}
912
913#[derive(Clone, Debug, Serialize, Deserialize)]
915pub struct VerifiedAccessInstance {
916 pub id: String,
917 pub description: String,
918 #[serde(default)]
919 pub trust_providers: Vec<String>,
920}
921
922#[derive(Clone, Debug, Serialize, Deserialize)]
924pub struct VerifiedAccessTrustProvider {
925 pub id: String,
926 pub trust_provider_type: String,
927 pub policy_reference_name: String,
928 pub description: String,
929}
930
931#[derive(Clone, Debug, Serialize, Deserialize)]
933pub struct VerifiedAccessGroup {
934 pub id: String,
935 pub instance_id: String,
936 pub description: String,
937}
938
939#[derive(Clone, Debug, Serialize, Deserialize)]
941pub struct VerifiedAccessEndpoint {
942 pub id: String,
943 pub group_id: String,
944 pub instance_id: String,
945 pub endpoint_type: String,
946 pub attachment_type: String,
947}
948
949#[derive(Clone, Debug, Serialize, Deserialize)]
951pub struct NetworkInsightsPath {
952 pub id: String,
953 pub source: String,
954 pub destination: String,
955 pub protocol: String,
956}
957
958#[derive(Clone, Debug, Serialize, Deserialize)]
960pub struct NetworkInsightsAnalysis {
961 pub id: String,
962 pub path_id: String,
963}
964
965#[derive(Clone, Debug, Serialize, Deserialize)]
967pub struct NetworkInsightsAccessScope {
968 pub id: String,
969}
970
971#[derive(Clone, Debug, Serialize, Deserialize)]
973pub struct NetworkInsightsAccessScopeAnalysis {
974 pub id: String,
975 pub scope_id: String,
976}
977
978#[derive(Clone, Debug, Serialize, Deserialize)]
980pub struct CarrierGateway {
981 pub id: String,
982 pub vpc_id: String,
983}
984
985#[derive(Clone, Debug, Serialize, Deserialize)]
987pub struct InstanceConnectEndpoint {
988 pub id: String,
989 pub subnet_id: String,
990}
991
992#[derive(Clone, Debug, Serialize, Deserialize)]
994pub struct CoipPool {
995 pub id: String,
996 pub route_table_id: String,
997}
998
999#[derive(Clone, Debug, Serialize, Deserialize)]
1001pub struct LocalGatewayRouteTable {
1002 pub id: String,
1003 pub local_gateway_id: String,
1004 pub mode: String,
1005}
1006
1007#[derive(Clone, Debug, Serialize, Deserialize)]
1009pub struct LocalGatewayRouteTableVpcAssoc {
1010 pub id: String,
1011 pub route_table_id: String,
1012 pub vpc_id: String,
1013}
1014
1015#[derive(Clone, Debug, Serialize, Deserialize)]
1017pub struct LocalGatewayVif {
1018 pub id: String,
1019 pub group_id: String,
1020 pub vlan: String,
1021 pub local_address: String,
1022 pub peer_address: String,
1023}
1024
1025#[derive(Clone, Debug, Serialize, Deserialize)]
1027pub struct LocalGatewayVifGroup {
1028 pub id: String,
1029 pub local_gateway_id: String,
1030}
1031
1032#[derive(Clone, Debug, Serialize, Deserialize)]
1034pub struct LocalGatewayRouteTableVifgAssoc {
1035 pub id: String,
1036 pub route_table_id: String,
1037 pub vif_group_id: String,
1038}
1039
1040#[derive(Clone, Debug, Serialize, Deserialize)]
1042pub struct ClientVpnEndpoint {
1043 pub id: String,
1044 pub description: String,
1045 pub status: String,
1046 pub server_cert_arn: String,
1047 pub transport_protocol: String,
1048 pub client_cidr: String,
1049 #[serde(default)]
1050 pub routes: Vec<String>,
1051 #[serde(default)]
1053 pub target_networks: Vec<(String, String)>,
1054 #[serde(default)]
1056 pub auth_rules: Vec<String>,
1057}
1058
1059#[derive(Clone, Debug, Serialize, Deserialize)]
1061pub struct TgwPeering {
1062 pub id: String,
1063 pub tgw_id: String,
1064 pub peer_tgw_id: String,
1065 pub peer_account: String,
1066 pub peer_region: String,
1067 pub state: String,
1068}
1069
1070#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1072pub struct PrefixListEntry {
1073 pub cidr: String,
1074 #[serde(default)]
1075 pub description: Option<String>,
1076}
1077
1078#[derive(Clone, Debug, Serialize, Deserialize)]
1083pub struct ManagedPrefixList {
1084 pub prefix_list_id: String,
1085 pub prefix_list_name: String,
1086 pub address_family: String,
1087 pub max_entries: i64,
1088 pub version: i64,
1089 pub state: String,
1091 #[serde(default)]
1092 pub entries: Vec<PrefixListEntry>,
1093 #[serde(default)]
1095 pub version_history: BTreeMap<i64, Vec<PrefixListEntry>>,
1096}
1097
1098#[derive(Clone, Debug, Serialize, Deserialize)]
1100pub struct EventWindowTimeRange {
1101 pub start_week_day: String,
1102 pub start_hour: i64,
1103 pub end_week_day: String,
1104 pub end_hour: i64,
1105}
1106
1107#[derive(Clone, Debug, Serialize, Deserialize)]
1109pub struct InstanceEventWindow {
1110 pub id: String,
1111 #[serde(default)]
1112 pub name: Option<String>,
1113 #[serde(default)]
1114 pub cron_expression: Option<String>,
1115 #[serde(default)]
1116 pub time_ranges: Vec<EventWindowTimeRange>,
1117 pub state: String,
1119 #[serde(default)]
1122 pub assoc_instance_ids: Vec<String>,
1123 #[serde(default)]
1124 pub assoc_dedicated_host_ids: Vec<String>,
1125 #[serde(default)]
1126 pub assoc_tags: Vec<Tag>,
1127}
1128
1129#[derive(Clone, Debug, Serialize, Deserialize)]
1131pub struct TrafficMirrorTarget {
1132 pub id: String,
1133 pub network_interface_id: Option<String>,
1134 pub network_load_balancer_arn: Option<String>,
1135 pub gateway_lb_endpoint_id: Option<String>,
1136 pub target_type: String,
1138 pub description: Option<String>,
1139}
1140
1141#[derive(Clone, Debug, Serialize, Deserialize)]
1143pub struct TrafficMirrorFilter {
1144 pub id: String,
1145 pub description: Option<String>,
1146 #[serde(default)]
1147 pub network_services: Vec<String>,
1148}
1149
1150#[derive(Clone, Debug, Serialize, Deserialize)]
1152pub struct TrafficMirrorFilterRule {
1153 pub id: String,
1154 pub filter_id: String,
1155 pub traffic_direction: String,
1156 pub rule_number: i64,
1157 pub rule_action: String,
1158 pub protocol: Option<i64>,
1159 pub destination_cidr_block: Option<String>,
1160 pub source_cidr_block: Option<String>,
1161 pub destination_port_range: Option<(i64, i64)>,
1163 pub source_port_range: Option<(i64, i64)>,
1164 pub description: Option<String>,
1165}
1166
1167#[derive(Clone, Debug, Serialize, Deserialize)]
1169pub struct TrafficMirrorSession {
1170 pub id: String,
1171 pub target_id: String,
1172 pub filter_id: String,
1173 pub network_interface_id: String,
1174 pub packet_length: Option<i64>,
1175 pub session_number: i64,
1176 pub virtual_network_id: Option<i64>,
1177 pub description: Option<String>,
1178}
1179
1180#[derive(Clone, Debug, Serialize, Deserialize)]
1182pub struct RouteServer {
1183 pub id: String,
1184 pub amazon_side_asn: i64,
1185 pub state: String,
1188 pub persist_routes_state: String,
1190 pub persist_routes_duration: Option<i64>,
1191 pub sns_notifications_enabled: bool,
1192}
1193
1194#[derive(Clone, Debug, Serialize, Deserialize)]
1196pub struct VpcEncryptionControl {
1197 pub id: String,
1198 pub vpc_id: String,
1199 pub mode: String,
1201 pub state: String,
1203 #[serde(default)]
1205 pub exclusions: BTreeMap<String, String>,
1206}
1207
1208#[derive(Clone, Debug, Serialize, Deserialize)]
1210pub struct VpcBpaExclusion {
1211 pub id: String,
1212 pub internet_gateway_exclusion_mode: String,
1214 pub resource_arn: Option<String>,
1215 pub state: String,
1217}
1218
1219#[derive(Clone, Debug, Serialize, Deserialize)]
1221pub struct FpgaImage {
1222 pub id: String,
1223 #[serde(default)]
1224 pub name: String,
1225 #[serde(default)]
1226 pub description: String,
1227 #[serde(default)]
1229 pub load_permission_users: Vec<String>,
1230 #[serde(default)]
1232 pub load_permission_groups: Vec<String>,
1233}
1234
1235#[derive(Clone, Debug, Default, Serialize, Deserialize)]
1238pub struct Ec2State {
1239 pub account_id: String,
1240 pub region: String,
1241 #[serde(default)]
1243 pub tags: BTreeMap<String, Vec<Tag>>,
1244 #[serde(default)]
1245 pub vpcs: BTreeMap<String, Vpc>,
1246 #[serde(default)]
1247 pub dhcp_options: BTreeMap<String, DhcpOptions>,
1248 #[serde(default)]
1249 pub subnets: BTreeMap<String, Subnet>,
1250 #[serde(default)]
1251 pub subnet_cidr_reservations: BTreeMap<String, SubnetCidrReservation>,
1252 #[serde(default)]
1253 pub security_groups: BTreeMap<String, SecurityGroup>,
1254 #[serde(default)]
1255 pub route_tables: BTreeMap<String, RouteTable>,
1256 #[serde(default)]
1257 pub internet_gateways: BTreeMap<String, InternetGateway>,
1258 #[serde(default)]
1259 pub egress_only_igws: BTreeMap<String, InternetGateway>,
1260 #[serde(default)]
1261 pub nat_gateways: BTreeMap<String, NatGateway>,
1262 #[serde(default)]
1264 pub elastic_ips: BTreeMap<String, ElasticIp>,
1265 #[serde(default)]
1267 pub key_pairs: BTreeMap<String, KeyPair>,
1268 #[serde(default)]
1270 pub placement_groups: BTreeMap<String, PlacementGroup>,
1271 #[serde(default)]
1272 pub network_interfaces: BTreeMap<String, NetworkInterface>,
1273 #[serde(default)]
1275 pub eni_permissions: BTreeMap<String, NetworkInterfacePermission>,
1276 #[serde(default)]
1277 pub instances: BTreeMap<String, Instance>,
1278 #[serde(default)]
1279 pub volumes: BTreeMap<String, Volume>,
1280 #[serde(default)]
1282 pub ebs_encryption_default: bool,
1283 #[serde(default)]
1285 pub ebs_default_kms_key_id: Option<String>,
1286 #[serde(default)]
1287 pub snapshots: BTreeMap<String, Snapshot>,
1288 #[serde(default)]
1290 pub snapshot_block_public_access: String,
1291 #[serde(default)]
1292 pub images: BTreeMap<String, Image>,
1293 #[serde(default)]
1295 pub image_watermarks: BTreeMap<String, BTreeMap<String, String>>,
1296 #[serde(default)]
1298 pub image_block_public_access: String,
1299 #[serde(default)]
1301 pub allowed_images_settings: String,
1302 #[serde(default)]
1306 pub allowed_image_criteria: Vec<Vec<String>>,
1307 #[serde(default)]
1308 pub network_acls: BTreeMap<String, NetworkAcl>,
1309 #[serde(default)]
1310 pub vpc_peerings: BTreeMap<String, VpcPeering>,
1311 #[serde(default)]
1312 pub vpc_endpoints: BTreeMap<String, VpcEndpoint>,
1313 #[serde(default)]
1314 pub endpoint_services: BTreeMap<String, EndpointService>,
1315 #[serde(default)]
1316 pub connection_notifications: BTreeMap<String, ConnectionNotification>,
1317 #[serde(default)]
1318 pub flow_logs: BTreeMap<String, FlowLog>,
1319 #[serde(default)]
1320 pub launch_templates: BTreeMap<String, LaunchTemplate>,
1321 #[serde(default)]
1322 pub spot_requests: BTreeMap<String, SpotRequest>,
1323 #[serde(default)]
1324 pub spot_fleets: BTreeMap<String, SpotFleet>,
1325 #[serde(default)]
1326 pub fleets: BTreeMap<String, Fleet>,
1327 #[serde(default)]
1329 pub spot_datafeed: Option<(String, String)>,
1330 #[serde(default)]
1331 pub capacity_reservations: BTreeMap<String, CapacityReservation>,
1332 #[serde(default)]
1334 pub capacity_reservation_fleets: BTreeMap<String, String>,
1335 #[serde(default)]
1336 pub reserved_instances: BTreeMap<String, ReservedInstances>,
1337 #[serde(default)]
1338 pub reserved_instances_listings: BTreeMap<String, ReservedInstancesListing>,
1339 #[serde(default)]
1340 pub reserved_instances_modifications: BTreeMap<String, ReservedInstancesModification>,
1341 #[serde(default)]
1342 pub dedicated_hosts: BTreeMap<String, DedicatedHost>,
1343 #[serde(default)]
1344 pub transit_gateways: BTreeMap<String, TransitGateway>,
1345 #[serde(default)]
1346 pub tgw_attachments: BTreeMap<String, TgwAttachment>,
1347 #[serde(default)]
1348 pub tgw_route_tables: BTreeMap<String, TgwRouteTable>,
1349 #[serde(default)]
1351 pub tgw_routes: BTreeMap<String, Vec<TgwRoute>>,
1352 #[serde(default)]
1354 pub tgw_rt_associations: BTreeMap<String, Vec<String>>,
1355 #[serde(default)]
1357 pub tgw_rt_propagations: BTreeMap<String, Vec<String>>,
1358 #[serde(default)]
1360 pub tgw_prefix_list_refs: BTreeMap<String, Vec<String>>,
1361 #[serde(default)]
1362 pub tgw_peerings: BTreeMap<String, TgwPeering>,
1363 #[serde(default)]
1365 pub tgw_connects: BTreeMap<String, (String, String)>,
1366 #[serde(default)]
1368 pub tgw_connect_peers: BTreeMap<String, String>,
1369 #[serde(default)]
1371 pub tgw_policy_tables: BTreeMap<String, String>,
1372 #[serde(default)]
1374 pub tgw_policy_table_associations: BTreeMap<String, Vec<String>>,
1375 #[serde(default)]
1377 pub tgw_announcements: BTreeMap<String, (String, String)>,
1378 #[serde(default)]
1379 pub tgw_multicast_domains: BTreeMap<String, TgwMulticastDomain>,
1380 #[serde(default)]
1381 pub tgw_metering_policies: BTreeMap<String, TgwMeteringPolicy>,
1382 #[serde(default)]
1383 pub customer_gateways: BTreeMap<String, CustomerGateway>,
1384 #[serde(default)]
1385 pub vpn_gateways: BTreeMap<String, VpnGateway>,
1386 #[serde(default)]
1387 pub vpn_connections: BTreeMap<String, VpnConnection>,
1388 #[serde(default)]
1389 pub vpn_concentrators: BTreeMap<String, VpnConcentrator>,
1390 #[serde(default)]
1391 pub client_vpn_endpoints: BTreeMap<String, ClientVpnEndpoint>,
1392 #[serde(default)]
1393 pub ipams: BTreeMap<String, Ipam>,
1394 #[serde(default)]
1395 pub ipam_scopes: BTreeMap<String, IpamScope>,
1396 #[serde(default)]
1397 pub ipam_pools: BTreeMap<String, IpamPool>,
1398 #[serde(default)]
1400 pub ipam_pool_cidrs: BTreeMap<String, Vec<(String, String)>>,
1401 #[serde(default)]
1403 pub ipam_pool_allocations: BTreeMap<String, Vec<(String, String)>>,
1404 #[serde(default)]
1405 pub ipam_resource_discoveries: BTreeMap<String, IpamResourceDiscovery>,
1406 #[serde(default)]
1408 pub ipam_rd_associations: BTreeMap<String, (String, String)>,
1409 #[serde(default)]
1411 pub ipam_byoasns: BTreeMap<String, String>,
1412 #[serde(default)]
1414 pub ipam_ext_tokens: BTreeMap<String, String>,
1415 #[serde(default)]
1416 pub ipam_policies: BTreeMap<String, IpamPolicy>,
1417 #[serde(default)]
1418 pub ipam_pl_resolvers: BTreeMap<String, IpamPrefixListResolver>,
1419 #[serde(default)]
1420 pub ipam_pl_resolver_targets: BTreeMap<String, IpamPrefixListResolverTarget>,
1421 #[serde(default)]
1423 pub ipam_policy_alloc_rules: BTreeMap<String, Vec<(String, String)>>,
1424 #[serde(default)]
1426 pub ipam_enabled_policy: Option<String>,
1427 #[serde(default)]
1428 pub va_instances: BTreeMap<String, VerifiedAccessInstance>,
1429 #[serde(default)]
1430 pub va_trust_providers: BTreeMap<String, VerifiedAccessTrustProvider>,
1431 #[serde(default)]
1432 pub va_groups: BTreeMap<String, VerifiedAccessGroup>,
1433 #[serde(default)]
1434 pub va_endpoints: BTreeMap<String, VerifiedAccessEndpoint>,
1435 #[serde(default)]
1437 pub va_group_policies: BTreeMap<String, String>,
1438 #[serde(default)]
1440 pub va_endpoint_policies: BTreeMap<String, String>,
1441 #[serde(default)]
1442 pub ni_paths: BTreeMap<String, NetworkInsightsPath>,
1443 #[serde(default)]
1444 pub ni_analyses: BTreeMap<String, NetworkInsightsAnalysis>,
1445 #[serde(default)]
1446 pub ni_access_scopes: BTreeMap<String, NetworkInsightsAccessScope>,
1447 #[serde(default)]
1448 pub ni_scope_analyses: BTreeMap<String, NetworkInsightsAccessScopeAnalysis>,
1449 #[serde(default)]
1450 pub carrier_gateways: BTreeMap<String, CarrierGateway>,
1451 #[serde(default)]
1452 pub coip_pools: BTreeMap<String, CoipPool>,
1453 #[serde(default)]
1455 pub coip_pool_cidrs: BTreeMap<String, Vec<String>>,
1456 #[serde(default)]
1457 pub lg_route_tables: BTreeMap<String, LocalGatewayRouteTable>,
1458 #[serde(default)]
1460 pub lg_routes: BTreeMap<String, Vec<String>>,
1461 #[serde(default)]
1462 pub lg_rt_vpc_assocs: BTreeMap<String, LocalGatewayRouteTableVpcAssoc>,
1463 #[serde(default)]
1464 pub lg_virtual_interfaces: BTreeMap<String, LocalGatewayVif>,
1465 #[serde(default)]
1466 pub lg_vif_groups: BTreeMap<String, LocalGatewayVifGroup>,
1467 #[serde(default)]
1468 pub lg_rt_vifg_assocs: BTreeMap<String, LocalGatewayRouteTableVifgAssoc>,
1469 #[serde(default)]
1470 pub instance_connect_endpoints: BTreeMap<String, InstanceConnectEndpoint>,
1471 #[serde(default)]
1473 pub fast_launch_images: std::collections::HashSet<String>,
1474 #[serde(default)]
1475 pub serial_console_access: bool,
1476 #[serde(default)]
1479 pub id_format: BTreeMap<String, bool>,
1480 #[serde(default)]
1482 pub identity_id_format: BTreeMap<String, BTreeMap<String, bool>>,
1483 #[serde(default)]
1486 pub default_credit_specs: BTreeMap<String, String>,
1487 #[serde(default)]
1490 pub vpc_bpa_internet_gateway_block_mode: Option<String>,
1491 #[serde(default)]
1494 pub managed_resource_default_visibility: Option<String>,
1495 #[serde(default)]
1498 pub az_group_optin: BTreeMap<String, String>,
1499 #[serde(default)]
1500 pub managed_prefix_lists: BTreeMap<String, ManagedPrefixList>,
1501 #[serde(default)]
1502 pub instance_event_windows: BTreeMap<String, InstanceEventWindow>,
1503 #[serde(default)]
1504 pub traffic_mirror_targets: BTreeMap<String, TrafficMirrorTarget>,
1505 #[serde(default)]
1506 pub traffic_mirror_filters: BTreeMap<String, TrafficMirrorFilter>,
1507 #[serde(default)]
1508 pub traffic_mirror_filter_rules: BTreeMap<String, TrafficMirrorFilterRule>,
1509 #[serde(default)]
1510 pub traffic_mirror_sessions: BTreeMap<String, TrafficMirrorSession>,
1511 #[serde(default)]
1512 pub route_servers: BTreeMap<String, RouteServer>,
1513 #[serde(default)]
1514 pub vpc_encryption_controls: BTreeMap<String, VpcEncryptionControl>,
1515 #[serde(default)]
1516 pub vpc_bpa_exclusions: BTreeMap<String, VpcBpaExclusion>,
1517 #[serde(default)]
1518 pub fpga_images: BTreeMap<String, FpgaImage>,
1519 #[serde(default)]
1522 pub ipam_allocation_descriptions: BTreeMap<String, String>,
1523}
1524
1525impl Ec2State {
1526 pub fn new(account_id: &str, region: &str) -> Self {
1527 let mut state = Self {
1528 account_id: account_id.to_string(),
1529 region: region.to_string(),
1530 ..Default::default()
1531 };
1532 crate::defaults::bootstrap_default_network(&mut state);
1538 crate::defaults::seed_public_images(&mut state);
1542 state
1543 }
1544
1545 pub fn ensure_public_images_seeded(&mut self) {
1551 crate::defaults::seed_public_images(self);
1552 }
1553
1554 pub fn upsert_tags(&mut self, resource_id: &str, new_tags: &[Tag]) {
1557 let entry = self.tags.entry(resource_id.to_string()).or_default();
1558 for t in new_tags {
1559 if let Some(existing) = entry.iter_mut().find(|e| e.key == t.key) {
1560 existing.value = t.value.clone();
1561 } else {
1562 entry.push(t.clone());
1563 }
1564 }
1565 }
1566
1567 pub fn remove_tags(&mut self, resource_id: &str, to_remove: &[(String, Option<String>)]) {
1571 if let Some(entry) = self.tags.get_mut(resource_id) {
1572 for (key, value) in to_remove {
1573 entry.retain(|e| {
1574 if &e.key != key {
1575 return true;
1576 }
1577 match value {
1578 Some(v) => &e.value != v,
1579 None => false,
1580 }
1581 });
1582 }
1583 if entry.is_empty() {
1584 self.tags.remove(resource_id);
1585 }
1586 }
1587 }
1588
1589 pub fn tags_for(&self, resource_id: &str) -> &[Tag] {
1591 self.tags.get(resource_id).map(Vec::as_slice).unwrap_or(&[])
1592 }
1593}
1594
1595#[cfg(test)]
1596mod tests {
1597 use super::*;
1598
1599 fn tag(k: &str, v: &str) -> Tag {
1600 Tag {
1601 key: k.to_string(),
1602 value: v.to_string(),
1603 }
1604 }
1605
1606 #[test]
1607 fn upsert_tags_inserts_then_overwrites_by_key() {
1608 let mut s = Ec2State::new("123456789012", "us-east-1");
1609 s.upsert_tags("vpc-1", &[tag("Name", "a"), tag("env", "dev")]);
1610 s.upsert_tags("vpc-1", &[tag("Name", "b")]);
1611 let tags = s.tags_for("vpc-1");
1612 assert_eq!(tags.len(), 2);
1613 assert_eq!(tags.iter().find(|t| t.key == "Name").unwrap().value, "b");
1614 }
1615
1616 #[test]
1617 fn remove_tags_by_key_and_by_key_value() {
1618 let mut s = Ec2State::new("123456789012", "us-east-1");
1619 s.upsert_tags(
1620 "i-1",
1621 &[tag("Name", "x"), tag("env", "prod"), tag("team", "a")],
1622 );
1623 s.remove_tags("i-1", &[("Name".to_string(), None)]);
1625 s.remove_tags("i-1", &[("env".to_string(), Some("dev".to_string()))]);
1627 s.remove_tags("i-1", &[("team".to_string(), Some("a".to_string()))]);
1629 let tags = s.tags_for("i-1");
1630 assert_eq!(tags.len(), 1);
1631 assert_eq!(tags[0].key, "env");
1632 }
1633
1634 #[test]
1635 fn empty_tag_set_drops_resource_entry() {
1636 let mut s = Ec2State::new("123456789012", "us-east-1");
1637 s.upsert_tags("sg-1", &[tag("Name", "x")]);
1638 s.remove_tags("sg-1", &[("Name".to_string(), None)]);
1639 assert!(!s.tags.contains_key("sg-1"));
1640 }
1641
1642 fn sample_instance() -> Instance {
1643 Instance {
1644 instance_id: "i-1".to_string(),
1645 image_id: "ami-1".to_string(),
1646 instance_type: "t3.micro".to_string(),
1647 state_code: 16,
1648 state_name: "running".to_string(),
1649 private_ip: "10.0.0.1".to_string(),
1650 public_ip: Some("52.0.0.1".to_string()),
1651 subnet_id: Some("subnet-1".to_string()),
1652 vpc_id: Some("vpc-1".to_string()),
1653 key_name: None,
1654 security_group_ids: vec!["sg-1".to_string()],
1655 reservation_id: "r-1".to_string(),
1656 ami_launch_index: 0,
1657 monitoring: false,
1658 az: "us-east-1a".to_string(),
1659 launch_time: "2024-01-01T00:00:00.000Z".to_string(),
1660 container_id: Some("abc".to_string()),
1661 disable_api_termination: true,
1662 disable_api_stop: true,
1663 source_dest_check: false,
1664 ebs_optimized: true,
1665 instance_initiated_shutdown_behavior: "terminate".to_string(),
1666 user_data: Some("ZWNobyBoaQ==".to_string()),
1667 metadata_options: MetadataOptions {
1668 http_tokens: "required".to_string(),
1669 ..MetadataOptions::default()
1670 },
1671 cpu_options: Some(CpuOptions {
1672 core_count: 4,
1673 threads_per_core: 2,
1674 }),
1675 bandwidth_weighting: Some("vpc-1".to_string()),
1676 maintenance_options: MaintenanceOptions::default(),
1677 placement_tenancy: Some("dedicated".to_string()),
1678 placement_affinity: None,
1679 placement_group_name: Some("cluster-1".to_string()),
1680 private_dns_hostname_type: Some("resource-name".to_string()),
1681 enable_resource_name_dns_a_record: true,
1682 enable_resource_name_dns_aaaa_record: false,
1683 }
1684 }
1685
1686 #[test]
1687 fn instance_attributes_round_trip_through_serde() {
1688 let inst = sample_instance();
1689 let json = serde_json::to_string(&inst).unwrap();
1690 let back: Instance = serde_json::from_str(&json).unwrap();
1691 assert!(back.disable_api_termination);
1692 assert!(back.disable_api_stop);
1693 assert!(!back.source_dest_check);
1694 assert!(back.ebs_optimized);
1695 assert_eq!(back.instance_initiated_shutdown_behavior, "terminate");
1696 assert_eq!(back.user_data.as_deref(), Some("ZWNobyBoaQ=="));
1697 assert_eq!(back.metadata_options.http_tokens, "required");
1698 assert_eq!(back.cpu_options.as_ref().unwrap().core_count, 4);
1699 assert_eq!(back.bandwidth_weighting.as_deref(), Some("vpc-1"));
1700 assert_eq!(back.placement_tenancy.as_deref(), Some("dedicated"));
1701 assert_eq!(back.placement_group_name.as_deref(), Some("cluster-1"));
1702 }
1703
1704 #[test]
1705 fn instance_attribute_defaults_load_from_legacy_snapshot() {
1706 let legacy = r#"{
1709 "instance_id":"i-1","image_id":"ami-1","instance_type":"t3.micro",
1710 "state_code":16,"state_name":"running","private_ip":"10.0.0.1",
1711 "public_ip":null,"subnet_id":null,"vpc_id":null,"key_name":null,
1712 "reservation_id":"r-1","ami_launch_index":0,"monitoring":false,
1713 "az":"us-east-1a","launch_time":"2024-01-01T00:00:00.000Z"
1714 }"#;
1715 let inst: Instance = serde_json::from_str(legacy).unwrap();
1716 assert!(!inst.disable_api_termination);
1717 assert!(inst.source_dest_check, "sourceDestCheck defaults to true");
1718 assert_eq!(inst.instance_initiated_shutdown_behavior, "stop");
1719 assert_eq!(inst.metadata_options.http_tokens, "optional");
1720 assert!(inst.cpu_options.is_none());
1721 }
1722}