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
400#[derive(Clone, Debug, Default, Serialize, Deserialize)]
404pub struct InstanceMetadataDefaults {
405 #[serde(default)]
406 pub http_tokens: Option<String>,
407 #[serde(default)]
408 pub http_endpoint: Option<String>,
409 #[serde(default)]
410 pub http_put_response_hop_limit: Option<i64>,
411 #[serde(default)]
412 pub instance_metadata_tags: Option<String>,
413 #[serde(default)]
414 pub http_tokens_enforced: Option<String>,
415}
416
417impl Default for MetadataOptions {
418 fn default() -> Self {
419 Self {
420 http_tokens: "optional".to_string(),
421 http_endpoint: "enabled".to_string(),
422 http_put_response_hop_limit: 1,
423 http_protocol_ipv6: "disabled".to_string(),
424 instance_metadata_tags: "disabled".to_string(),
425 }
426 }
427}
428
429#[derive(Clone, Debug, Serialize, Deserialize)]
431pub struct CpuOptions {
432 pub core_count: i64,
433 pub threads_per_core: i64,
434}
435
436#[derive(Clone, Debug, Serialize, Deserialize)]
438pub struct MaintenanceOptions {
439 pub auto_recovery: String,
441 pub reboot_migration: String,
443}
444
445impl Default for MaintenanceOptions {
446 fn default() -> Self {
447 Self {
448 auto_recovery: "default".to_string(),
449 reboot_migration: "default".to_string(),
450 }
451 }
452}
453
454#[derive(Clone, Debug, Serialize, Deserialize)]
456pub struct VolumeAttachment {
457 pub volume_id: String,
458 pub instance_id: String,
459 pub device: String,
460 pub status: String,
462 pub delete_on_termination: bool,
463}
464
465#[derive(Clone, Debug, Serialize, Deserialize)]
467pub struct Volume {
468 pub volume_id: String,
469 pub size: i64,
470 pub snapshot_id: Option<String>,
471 pub availability_zone: String,
472 pub state: String,
474 pub volume_type: String,
475 pub iops: Option<i64>,
476 pub throughput: Option<i64>,
477 pub encrypted: bool,
478 pub kms_key_id: Option<String>,
479 pub multi_attach_enabled: bool,
480 pub auto_enable_io: bool,
481 #[serde(default)]
482 pub attachments: Vec<VolumeAttachment>,
483 #[serde(default)]
484 pub in_recycle_bin: bool,
485}
486
487#[derive(Clone, Debug, Serialize, Deserialize)]
489pub struct Snapshot {
490 pub snapshot_id: String,
491 pub volume_id: String,
492 pub state: String,
494 pub volume_size: i64,
495 pub description: String,
496 pub encrypted: bool,
497 pub storage_tier: String,
499 #[serde(default)]
500 pub in_recycle_bin: bool,
501 #[serde(default)]
502 pub locked: bool,
503 pub lock_mode: Option<String>,
504 #[serde(default)]
507 pub create_volume_permissions: Vec<String>,
508}
509
510#[derive(Clone, Debug, Serialize, Deserialize)]
512pub struct Image {
513 pub image_id: String,
514 pub name: String,
515 pub description: String,
516 pub state: String,
518 pub architecture: String,
519 pub public: bool,
520 pub source_instance_id: Option<String>,
521 #[serde(default)]
522 pub in_recycle_bin: bool,
523 pub deprecation_time: Option<String>,
524 #[serde(default)]
525 pub deregistration_protection: bool,
526 #[serde(default)]
529 pub launch_permission_users: Vec<String>,
530 #[serde(default)]
532 pub launch_permission_groups: Vec<String>,
533 #[serde(default)]
536 pub boot_mode: Option<String>,
537 #[serde(default)]
542 pub owner_id: Option<String>,
543 #[serde(default)]
547 pub owner_alias: Option<String>,
548 #[serde(default)]
552 pub creation_date: Option<String>,
553 #[serde(default)]
556 pub root_device_name: Option<String>,
557 #[serde(default)]
559 pub platform: Option<String>,
560}
561
562#[derive(Clone, Debug, Serialize, Deserialize)]
564pub struct NetworkAclEntry {
565 pub rule_number: i64,
566 pub protocol: String,
567 pub rule_action: String,
569 pub egress: bool,
570 pub cidr_block: Option<String>,
571 pub ipv6_cidr_block: Option<String>,
572 pub port_range: Option<(i64, i64)>,
574 pub icmp_type_code: Option<(i64, i64)>,
576}
577
578#[derive(Clone, Debug, Serialize, Deserialize)]
580pub struct NetworkAclAssoc {
581 pub association_id: String,
582 pub subnet_id: String,
583}
584
585#[derive(Clone, Debug, Serialize, Deserialize)]
587pub struct NetworkAcl {
588 pub network_acl_id: String,
589 pub vpc_id: String,
590 pub is_default: bool,
591 #[serde(default)]
592 pub entries: Vec<NetworkAclEntry>,
593 #[serde(default)]
594 pub associations: Vec<NetworkAclAssoc>,
595}
596
597#[derive(Clone, Debug, Serialize, Deserialize)]
599pub struct VpcPeering {
600 pub id: String,
601 pub requester_vpc_id: String,
602 pub accepter_vpc_id: String,
603 pub status: String,
605 #[serde(default)]
607 pub requester_allow_dns: bool,
608 #[serde(default)]
610 pub accepter_allow_dns: bool,
611}
612
613#[derive(Clone, Debug, Serialize, Deserialize)]
615pub struct VpcEndpoint {
616 pub id: String,
617 pub endpoint_type: String,
619 pub vpc_id: String,
620 pub service_name: String,
621 pub state: String,
622 #[serde(default)]
623 pub subnet_ids: Vec<String>,
624 #[serde(default)]
625 pub route_table_ids: Vec<String>,
626 #[serde(default)]
627 pub private_dns_enabled: bool,
628 #[serde(default)]
630 pub security_group_ids: Vec<String>,
631}
632
633#[derive(Clone, Debug, Serialize, Deserialize)]
635pub struct EndpointService {
636 pub service_id: String,
637 pub service_name: String,
638 pub state: String,
639 pub acceptance_required: bool,
640 pub payer_responsibility: String,
641 #[serde(default)]
642 pub nlb_arns: Vec<String>,
643}
644
645#[derive(Clone, Debug, Serialize, Deserialize)]
647pub struct ConnectionNotification {
648 pub id: String,
649 pub arn: String,
650 pub service_id: Option<String>,
651 #[serde(default)]
652 pub events: Vec<String>,
653}
654
655#[derive(Clone, Debug, Serialize, Deserialize)]
657pub struct FlowLog {
658 pub id: String,
659 pub resource_id: String,
660 pub traffic_type: String,
661 pub log_destination_type: String,
662 pub log_group_name: Option<String>,
663 pub log_destination: Option<String>,
665 #[serde(default)]
668 pub deliver_logs_permission_arn: Option<String>,
669 #[serde(default = "default_max_aggregation_interval")]
672 pub max_aggregation_interval: i64,
673}
674
675fn default_max_aggregation_interval() -> i64 {
676 600
677}
678
679#[derive(Clone, Debug, Serialize, Deserialize)]
681pub struct LaunchTemplate {
682 pub id: String,
683 pub name: String,
684 pub default_version: i64,
685 pub latest_version: i64,
686}
687
688#[derive(Clone, Debug, Serialize, Deserialize)]
690pub struct SpotRequest {
691 pub id: String,
692 pub state: String,
694 pub request_type: String,
695 pub spot_price: String,
696}
697
698#[derive(Clone, Debug, Serialize, Deserialize)]
700pub struct SpotFleet {
701 pub id: String,
702 pub state: String,
703}
704
705#[derive(Clone, Debug, Serialize, Deserialize)]
707pub struct Fleet {
708 pub id: String,
709 pub state: String,
710 pub fleet_type: String,
711}
712
713#[derive(Clone, Debug, Serialize, Deserialize)]
715pub struct CapacityReservation {
716 pub id: String,
717 pub instance_type: String,
718 pub instance_platform: String,
719 pub availability_zone: String,
720 pub tenancy: String,
721 pub total_instance_count: i64,
722 pub available_instance_count: i64,
723 pub state: String,
725 pub end_date_type: String,
726 pub instance_match_criteria: String,
727}
728
729#[derive(Clone, Debug, Serialize, Deserialize)]
731pub struct ReservedInstances {
732 pub id: String,
733 pub instance_type: String,
734 pub availability_zone: String,
735 pub instance_count: i64,
736 pub product_description: String,
737 pub state: String,
738 pub duration: i64,
739 pub fixed_price: String,
740 pub usage_price: String,
741}
742
743#[derive(Clone, Debug, Serialize, Deserialize)]
745pub struct ReservedInstancesListing {
746 pub listing_id: String,
747 pub reserved_instances_id: String,
748 pub instance_count: i64,
749 pub client_token: String,
750 pub status: String,
752 pub status_message: String,
753}
754
755#[derive(Clone, Debug, Serialize, Deserialize)]
757pub struct ReservedInstancesModification {
758 pub modification_id: String,
759 pub reserved_instances_ids: Vec<String>,
760 pub status: String,
762 pub client_token: String,
763}
764
765#[derive(Clone, Debug, Serialize, Deserialize)]
767pub struct DedicatedHost {
768 pub id: String,
769 pub auto_placement: String,
770 pub availability_zone: String,
771 pub instance_type: String,
772 pub state: String,
773 pub host_recovery: String,
774 pub host_maintenance: String,
775}
776
777#[derive(Clone, Debug, Serialize, Deserialize)]
779pub struct TransitGateway {
780 pub id: String,
781 pub description: String,
782 #[serde(default = "tgw_default_state")]
784 pub state: String,
785}
786
787fn tgw_default_state() -> String {
788 "available".to_string()
789}
790
791#[derive(Clone, Debug, Serialize, Deserialize)]
793pub struct TgwAttachment {
794 pub id: String,
795 pub tgw_id: String,
796 pub resource_id: String,
797 pub resource_type: String,
798 #[serde(default)]
799 pub subnet_ids: Vec<String>,
800 pub state: String,
801}
802
803#[derive(Clone, Debug, Serialize, Deserialize)]
805pub struct TgwRouteTable {
806 pub id: String,
807 pub tgw_id: String,
808}
809
810#[derive(Clone, Debug, Serialize, Deserialize)]
812pub struct TgwRoute {
813 pub cidr: String,
814 pub attachment_id: String,
815 pub state: String,
816}
817
818#[derive(Clone, Debug, Serialize, Deserialize)]
820pub struct TgwMulticastDomain {
821 pub id: String,
822 pub tgw_id: String,
823}
824
825#[derive(Clone, Debug, Serialize, Deserialize)]
827pub struct TgwMeteringPolicy {
828 pub id: String,
829 pub tgw_id: String,
830}
831
832#[derive(Clone, Debug, Serialize, Deserialize)]
834pub struct CustomerGateway {
835 pub id: String,
836 pub state: String,
837 pub ip_address: String,
838 pub bgp_asn: String,
839}
840
841#[derive(Clone, Debug, Serialize, Deserialize)]
843pub struct VpnGateway {
844 pub id: String,
845 pub state: String,
846 #[serde(default)]
847 pub attachments: Vec<String>,
848}
849
850#[derive(Clone, Debug, Serialize, Deserialize)]
852pub struct VpnConnection {
853 pub id: String,
854 pub state: String,
855 pub customer_gateway_id: String,
856 pub vpn_gateway_id: Option<String>,
857 #[serde(default)]
858 pub routes: Vec<String>,
859}
860
861#[derive(Clone, Debug, Serialize, Deserialize)]
863pub struct VpnConcentrator {
864 pub id: String,
865 pub state: String,
866}
867
868#[derive(Clone, Debug, Serialize, Deserialize)]
870pub struct Ipam {
871 pub id: String,
872 pub public_scope_id: String,
873 pub private_scope_id: String,
874 pub tier: String,
875 #[serde(default)]
876 pub description: String,
877}
878
879#[derive(Clone, Debug, Serialize, Deserialize)]
881pub struct IpamScope {
882 pub id: String,
883 pub ipam_id: String,
884 #[serde(default)]
886 pub scope_type: String,
887 #[serde(default)]
888 pub description: String,
889}
890
891#[derive(Clone, Debug, Serialize, Deserialize)]
893pub struct IpamPool {
894 pub id: String,
895 pub scope_id: String,
896 pub address_family: String,
897 #[serde(default)]
898 pub description: String,
899}
900
901#[derive(Clone, Debug, Serialize, Deserialize)]
903pub struct IpamResourceDiscovery {
904 pub id: String,
905 #[serde(default)]
906 pub description: String,
907}
908
909#[derive(Clone, Debug, Serialize, Deserialize)]
911pub struct IpamPolicy {
912 pub id: String,
913 pub ipam_id: String,
914}
915
916#[derive(Clone, Debug, Serialize, Deserialize)]
918pub struct IpamPrefixListResolver {
919 pub id: String,
920 pub ipam_id: String,
921 pub address_family: String,
922 #[serde(default)]
923 pub description: String,
924}
925
926#[derive(Clone, Debug, Serialize, Deserialize)]
928pub struct IpamPrefixListResolverTarget {
929 pub id: String,
930 pub resolver_id: String,
931 pub prefix_list_id: String,
932 pub prefix_list_region: String,
933 #[serde(default)]
934 pub track_latest_version: bool,
935}
936
937#[derive(Clone, Debug, Serialize, Deserialize)]
939pub struct VerifiedAccessInstance {
940 pub id: String,
941 pub description: String,
942 #[serde(default)]
943 pub trust_providers: Vec<String>,
944}
945
946#[derive(Clone, Debug, Serialize, Deserialize)]
948pub struct VerifiedAccessTrustProvider {
949 pub id: String,
950 pub trust_provider_type: String,
951 pub policy_reference_name: String,
952 pub description: String,
953}
954
955#[derive(Clone, Debug, Serialize, Deserialize)]
957pub struct VerifiedAccessGroup {
958 pub id: String,
959 pub instance_id: String,
960 pub description: String,
961}
962
963#[derive(Clone, Debug, Serialize, Deserialize)]
965pub struct VerifiedAccessEndpoint {
966 pub id: String,
967 pub group_id: String,
968 pub instance_id: String,
969 pub endpoint_type: String,
970 pub attachment_type: String,
971}
972
973#[derive(Clone, Debug, Serialize, Deserialize)]
975pub struct NetworkInsightsPath {
976 pub id: String,
977 pub source: String,
978 pub destination: String,
979 pub protocol: String,
980}
981
982#[derive(Clone, Debug, Serialize, Deserialize)]
984pub struct NetworkInsightsAnalysis {
985 pub id: String,
986 pub path_id: String,
987}
988
989#[derive(Clone, Debug, Serialize, Deserialize)]
991pub struct NetworkInsightsAccessScope {
992 pub id: String,
993}
994
995#[derive(Clone, Debug, Serialize, Deserialize)]
997pub struct NetworkInsightsAccessScopeAnalysis {
998 pub id: String,
999 pub scope_id: String,
1000}
1001
1002#[derive(Clone, Debug, Serialize, Deserialize)]
1004pub struct CarrierGateway {
1005 pub id: String,
1006 pub vpc_id: String,
1007}
1008
1009#[derive(Clone, Debug, Serialize, Deserialize)]
1011pub struct InstanceConnectEndpoint {
1012 pub id: String,
1013 pub subnet_id: String,
1014}
1015
1016#[derive(Clone, Debug, Serialize, Deserialize)]
1018pub struct CoipPool {
1019 pub id: String,
1020 pub route_table_id: String,
1021}
1022
1023#[derive(Clone, Debug, Serialize, Deserialize)]
1025pub struct LocalGatewayRouteTable {
1026 pub id: String,
1027 pub local_gateway_id: String,
1028 pub mode: String,
1029}
1030
1031#[derive(Clone, Debug, Serialize, Deserialize)]
1033pub struct LocalGatewayRouteTableVpcAssoc {
1034 pub id: String,
1035 pub route_table_id: String,
1036 pub vpc_id: String,
1037}
1038
1039#[derive(Clone, Debug, Serialize, Deserialize)]
1041pub struct LocalGatewayVif {
1042 pub id: String,
1043 pub group_id: String,
1044 pub vlan: String,
1045 pub local_address: String,
1046 pub peer_address: String,
1047}
1048
1049#[derive(Clone, Debug, Serialize, Deserialize)]
1051pub struct LocalGatewayVifGroup {
1052 pub id: String,
1053 pub local_gateway_id: String,
1054}
1055
1056#[derive(Clone, Debug, Serialize, Deserialize)]
1058pub struct LocalGatewayRouteTableVifgAssoc {
1059 pub id: String,
1060 pub route_table_id: String,
1061 pub vif_group_id: String,
1062}
1063
1064#[derive(Clone, Debug, Serialize, Deserialize)]
1066pub struct ClientVpnEndpoint {
1067 pub id: String,
1068 pub description: String,
1069 pub status: String,
1070 pub server_cert_arn: String,
1071 pub transport_protocol: String,
1072 pub client_cidr: String,
1073 #[serde(default)]
1074 pub routes: Vec<String>,
1075 #[serde(default)]
1077 pub target_networks: Vec<(String, String)>,
1078 #[serde(default)]
1080 pub auth_rules: Vec<String>,
1081}
1082
1083#[derive(Clone, Debug, Serialize, Deserialize)]
1085pub struct TgwPeering {
1086 pub id: String,
1087 pub tgw_id: String,
1088 pub peer_tgw_id: String,
1089 pub peer_account: String,
1090 pub peer_region: String,
1091 pub state: String,
1092}
1093
1094#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1096pub struct PrefixListEntry {
1097 pub cidr: String,
1098 #[serde(default)]
1099 pub description: Option<String>,
1100}
1101
1102#[derive(Clone, Debug, Serialize, Deserialize)]
1107pub struct ManagedPrefixList {
1108 pub prefix_list_id: String,
1109 pub prefix_list_name: String,
1110 pub address_family: String,
1111 pub max_entries: i64,
1112 pub version: i64,
1113 pub state: String,
1115 #[serde(default)]
1116 pub entries: Vec<PrefixListEntry>,
1117 #[serde(default)]
1119 pub version_history: BTreeMap<i64, Vec<PrefixListEntry>>,
1120}
1121
1122#[derive(Clone, Debug, Serialize, Deserialize)]
1124pub struct EventWindowTimeRange {
1125 pub start_week_day: String,
1126 pub start_hour: i64,
1127 pub end_week_day: String,
1128 pub end_hour: i64,
1129}
1130
1131#[derive(Clone, Debug, Serialize, Deserialize)]
1133pub struct InstanceEventWindow {
1134 pub id: String,
1135 #[serde(default)]
1136 pub name: Option<String>,
1137 #[serde(default)]
1138 pub cron_expression: Option<String>,
1139 #[serde(default)]
1140 pub time_ranges: Vec<EventWindowTimeRange>,
1141 pub state: String,
1143 #[serde(default)]
1146 pub assoc_instance_ids: Vec<String>,
1147 #[serde(default)]
1148 pub assoc_dedicated_host_ids: Vec<String>,
1149 #[serde(default)]
1150 pub assoc_tags: Vec<Tag>,
1151}
1152
1153#[derive(Clone, Debug, Serialize, Deserialize)]
1155pub struct TrafficMirrorTarget {
1156 pub id: String,
1157 pub network_interface_id: Option<String>,
1158 pub network_load_balancer_arn: Option<String>,
1159 pub gateway_lb_endpoint_id: Option<String>,
1160 pub target_type: String,
1162 pub description: Option<String>,
1163}
1164
1165#[derive(Clone, Debug, Serialize, Deserialize)]
1167pub struct TrafficMirrorFilter {
1168 pub id: String,
1169 pub description: Option<String>,
1170 #[serde(default)]
1171 pub network_services: Vec<String>,
1172}
1173
1174#[derive(Clone, Debug, Serialize, Deserialize)]
1176pub struct TrafficMirrorFilterRule {
1177 pub id: String,
1178 pub filter_id: String,
1179 pub traffic_direction: String,
1180 pub rule_number: i64,
1181 pub rule_action: String,
1182 pub protocol: Option<i64>,
1183 pub destination_cidr_block: Option<String>,
1184 pub source_cidr_block: Option<String>,
1185 pub destination_port_range: Option<(i64, i64)>,
1187 pub source_port_range: Option<(i64, i64)>,
1188 pub description: Option<String>,
1189}
1190
1191#[derive(Clone, Debug, Serialize, Deserialize)]
1193pub struct TrafficMirrorSession {
1194 pub id: String,
1195 pub target_id: String,
1196 pub filter_id: String,
1197 pub network_interface_id: String,
1198 pub packet_length: Option<i64>,
1199 pub session_number: i64,
1200 pub virtual_network_id: Option<i64>,
1201 pub description: Option<String>,
1202}
1203
1204#[derive(Clone, Debug, Serialize, Deserialize)]
1206pub struct RouteServer {
1207 pub id: String,
1208 pub amazon_side_asn: i64,
1209 pub state: String,
1212 pub persist_routes_state: String,
1214 pub persist_routes_duration: Option<i64>,
1215 pub sns_notifications_enabled: bool,
1216}
1217
1218#[derive(Clone, Debug, Serialize, Deserialize)]
1220pub struct VpcEncryptionControl {
1221 pub id: String,
1222 pub vpc_id: String,
1223 pub mode: String,
1225 pub state: String,
1227 #[serde(default)]
1229 pub exclusions: BTreeMap<String, String>,
1230}
1231
1232#[derive(Clone, Debug, Serialize, Deserialize)]
1234pub struct VpcBpaExclusion {
1235 pub id: String,
1236 pub internet_gateway_exclusion_mode: String,
1238 pub resource_arn: Option<String>,
1239 pub state: String,
1241}
1242
1243#[derive(Clone, Debug, Serialize, Deserialize)]
1245pub struct FpgaImage {
1246 pub id: String,
1247 #[serde(default)]
1248 pub name: String,
1249 #[serde(default)]
1250 pub description: String,
1251 #[serde(default)]
1253 pub load_permission_users: Vec<String>,
1254 #[serde(default)]
1256 pub load_permission_groups: Vec<String>,
1257}
1258
1259#[derive(Clone, Debug, Default, Serialize, Deserialize)]
1262pub struct Ec2State {
1263 pub account_id: String,
1264 pub region: String,
1265 #[serde(default)]
1267 pub tags: BTreeMap<String, Vec<Tag>>,
1268 #[serde(default)]
1269 pub vpcs: BTreeMap<String, Vpc>,
1270 #[serde(default)]
1271 pub dhcp_options: BTreeMap<String, DhcpOptions>,
1272 #[serde(default)]
1273 pub subnets: BTreeMap<String, Subnet>,
1274 #[serde(default)]
1275 pub subnet_cidr_reservations: BTreeMap<String, SubnetCidrReservation>,
1276 #[serde(default)]
1277 pub security_groups: BTreeMap<String, SecurityGroup>,
1278 #[serde(default)]
1279 pub route_tables: BTreeMap<String, RouteTable>,
1280 #[serde(default)]
1281 pub internet_gateways: BTreeMap<String, InternetGateway>,
1282 #[serde(default)]
1283 pub egress_only_igws: BTreeMap<String, InternetGateway>,
1284 #[serde(default)]
1285 pub nat_gateways: BTreeMap<String, NatGateway>,
1286 #[serde(default)]
1288 pub elastic_ips: BTreeMap<String, ElasticIp>,
1289 #[serde(default)]
1291 pub key_pairs: BTreeMap<String, KeyPair>,
1292 #[serde(default)]
1294 pub placement_groups: BTreeMap<String, PlacementGroup>,
1295 #[serde(default)]
1296 pub network_interfaces: BTreeMap<String, NetworkInterface>,
1297 #[serde(default)]
1299 pub eni_permissions: BTreeMap<String, NetworkInterfacePermission>,
1300 #[serde(default)]
1301 pub instances: BTreeMap<String, Instance>,
1302 #[serde(default)]
1303 pub volumes: BTreeMap<String, Volume>,
1304 #[serde(default)]
1306 pub ebs_encryption_default: bool,
1307 #[serde(default)]
1309 pub ebs_default_kms_key_id: Option<String>,
1310 #[serde(default)]
1311 pub snapshots: BTreeMap<String, Snapshot>,
1312 #[serde(default)]
1314 pub snapshot_block_public_access: String,
1315 #[serde(default)]
1316 pub images: BTreeMap<String, Image>,
1317 #[serde(default)]
1319 pub image_watermarks: BTreeMap<String, BTreeMap<String, String>>,
1320 #[serde(default)]
1322 pub image_block_public_access: String,
1323 #[serde(default)]
1325 pub allowed_images_settings: String,
1326 #[serde(default)]
1330 pub allowed_image_criteria: Vec<Vec<String>>,
1331 #[serde(default)]
1332 pub network_acls: BTreeMap<String, NetworkAcl>,
1333 #[serde(default)]
1334 pub vpc_peerings: BTreeMap<String, VpcPeering>,
1335 #[serde(default)]
1336 pub vpc_endpoints: BTreeMap<String, VpcEndpoint>,
1337 #[serde(default)]
1338 pub endpoint_services: BTreeMap<String, EndpointService>,
1339 #[serde(default)]
1340 pub connection_notifications: BTreeMap<String, ConnectionNotification>,
1341 #[serde(default)]
1342 pub flow_logs: BTreeMap<String, FlowLog>,
1343 #[serde(default)]
1344 pub launch_templates: BTreeMap<String, LaunchTemplate>,
1345 #[serde(default)]
1346 pub spot_requests: BTreeMap<String, SpotRequest>,
1347 #[serde(default)]
1348 pub spot_fleets: BTreeMap<String, SpotFleet>,
1349 #[serde(default)]
1350 pub fleets: BTreeMap<String, Fleet>,
1351 #[serde(default)]
1353 pub spot_datafeed: Option<(String, String)>,
1354 #[serde(default)]
1355 pub capacity_reservations: BTreeMap<String, CapacityReservation>,
1356 #[serde(default)]
1358 pub capacity_reservation_fleets: BTreeMap<String, String>,
1359 #[serde(default)]
1360 pub reserved_instances: BTreeMap<String, ReservedInstances>,
1361 #[serde(default)]
1362 pub reserved_instances_listings: BTreeMap<String, ReservedInstancesListing>,
1363 #[serde(default)]
1364 pub reserved_instances_modifications: BTreeMap<String, ReservedInstancesModification>,
1365 #[serde(default)]
1366 pub dedicated_hosts: BTreeMap<String, DedicatedHost>,
1367 #[serde(default)]
1368 pub transit_gateways: BTreeMap<String, TransitGateway>,
1369 #[serde(default)]
1370 pub tgw_attachments: BTreeMap<String, TgwAttachment>,
1371 #[serde(default)]
1372 pub tgw_route_tables: BTreeMap<String, TgwRouteTable>,
1373 #[serde(default)]
1375 pub tgw_routes: BTreeMap<String, Vec<TgwRoute>>,
1376 #[serde(default)]
1378 pub tgw_rt_associations: BTreeMap<String, Vec<String>>,
1379 #[serde(default)]
1381 pub tgw_rt_propagations: BTreeMap<String, Vec<String>>,
1382 #[serde(default)]
1384 pub tgw_prefix_list_refs: BTreeMap<String, Vec<String>>,
1385 #[serde(default)]
1386 pub tgw_peerings: BTreeMap<String, TgwPeering>,
1387 #[serde(default)]
1389 pub tgw_connects: BTreeMap<String, (String, String)>,
1390 #[serde(default)]
1392 pub tgw_connect_peers: BTreeMap<String, String>,
1393 #[serde(default)]
1395 pub tgw_policy_tables: BTreeMap<String, String>,
1396 #[serde(default)]
1398 pub tgw_policy_table_associations: BTreeMap<String, Vec<String>>,
1399 #[serde(default)]
1401 pub tgw_announcements: BTreeMap<String, (String, String)>,
1402 #[serde(default)]
1403 pub tgw_multicast_domains: BTreeMap<String, TgwMulticastDomain>,
1404 #[serde(default)]
1405 pub tgw_metering_policies: BTreeMap<String, TgwMeteringPolicy>,
1406 #[serde(default)]
1407 pub customer_gateways: BTreeMap<String, CustomerGateway>,
1408 #[serde(default)]
1409 pub vpn_gateways: BTreeMap<String, VpnGateway>,
1410 #[serde(default)]
1411 pub vpn_connections: BTreeMap<String, VpnConnection>,
1412 #[serde(default)]
1413 pub vpn_concentrators: BTreeMap<String, VpnConcentrator>,
1414 #[serde(default)]
1415 pub client_vpn_endpoints: BTreeMap<String, ClientVpnEndpoint>,
1416 #[serde(default)]
1417 pub ipams: BTreeMap<String, Ipam>,
1418 #[serde(default)]
1419 pub ipam_scopes: BTreeMap<String, IpamScope>,
1420 #[serde(default)]
1421 pub ipam_pools: BTreeMap<String, IpamPool>,
1422 #[serde(default)]
1424 pub ipam_pool_cidrs: BTreeMap<String, Vec<(String, String)>>,
1425 #[serde(default)]
1427 pub ipam_pool_allocations: BTreeMap<String, Vec<(String, String)>>,
1428 #[serde(default)]
1429 pub ipam_resource_discoveries: BTreeMap<String, IpamResourceDiscovery>,
1430 #[serde(default)]
1432 pub ipam_rd_associations: BTreeMap<String, (String, String)>,
1433 #[serde(default)]
1435 pub ipam_byoasns: BTreeMap<String, String>,
1436 #[serde(default)]
1438 pub ipam_ext_tokens: BTreeMap<String, String>,
1439 #[serde(default)]
1440 pub ipam_policies: BTreeMap<String, IpamPolicy>,
1441 #[serde(default)]
1442 pub ipam_pl_resolvers: BTreeMap<String, IpamPrefixListResolver>,
1443 #[serde(default)]
1444 pub ipam_pl_resolver_targets: BTreeMap<String, IpamPrefixListResolverTarget>,
1445 #[serde(default)]
1447 pub ipam_policy_alloc_rules: BTreeMap<String, Vec<(String, String)>>,
1448 #[serde(default)]
1450 pub ipam_enabled_policy: Option<String>,
1451 #[serde(default)]
1452 pub va_instances: BTreeMap<String, VerifiedAccessInstance>,
1453 #[serde(default)]
1454 pub va_trust_providers: BTreeMap<String, VerifiedAccessTrustProvider>,
1455 #[serde(default)]
1456 pub va_groups: BTreeMap<String, VerifiedAccessGroup>,
1457 #[serde(default)]
1458 pub va_endpoints: BTreeMap<String, VerifiedAccessEndpoint>,
1459 #[serde(default)]
1461 pub va_group_policies: BTreeMap<String, String>,
1462 #[serde(default)]
1464 pub va_endpoint_policies: BTreeMap<String, String>,
1465 #[serde(default)]
1466 pub ni_paths: BTreeMap<String, NetworkInsightsPath>,
1467 #[serde(default)]
1468 pub ni_analyses: BTreeMap<String, NetworkInsightsAnalysis>,
1469 #[serde(default)]
1470 pub ni_access_scopes: BTreeMap<String, NetworkInsightsAccessScope>,
1471 #[serde(default)]
1472 pub ni_scope_analyses: BTreeMap<String, NetworkInsightsAccessScopeAnalysis>,
1473 #[serde(default)]
1474 pub carrier_gateways: BTreeMap<String, CarrierGateway>,
1475 #[serde(default)]
1476 pub coip_pools: BTreeMap<String, CoipPool>,
1477 #[serde(default)]
1479 pub coip_pool_cidrs: BTreeMap<String, Vec<String>>,
1480 #[serde(default)]
1481 pub lg_route_tables: BTreeMap<String, LocalGatewayRouteTable>,
1482 #[serde(default)]
1484 pub lg_routes: BTreeMap<String, Vec<String>>,
1485 #[serde(default)]
1486 pub lg_rt_vpc_assocs: BTreeMap<String, LocalGatewayRouteTableVpcAssoc>,
1487 #[serde(default)]
1488 pub lg_virtual_interfaces: BTreeMap<String, LocalGatewayVif>,
1489 #[serde(default)]
1490 pub lg_vif_groups: BTreeMap<String, LocalGatewayVifGroup>,
1491 #[serde(default)]
1492 pub lg_rt_vifg_assocs: BTreeMap<String, LocalGatewayRouteTableVifgAssoc>,
1493 #[serde(default)]
1494 pub instance_connect_endpoints: BTreeMap<String, InstanceConnectEndpoint>,
1495 #[serde(default)]
1497 pub fast_launch_images: std::collections::HashSet<String>,
1498 #[serde(default)]
1499 pub serial_console_access: bool,
1500 #[serde(default)]
1503 pub id_format: BTreeMap<String, bool>,
1504 #[serde(default)]
1506 pub identity_id_format: BTreeMap<String, BTreeMap<String, bool>>,
1507 #[serde(default)]
1510 pub default_credit_specs: BTreeMap<String, String>,
1511 #[serde(default)]
1514 pub instance_credit_specs: BTreeMap<String, String>,
1515 #[serde(default)]
1518 pub instance_metadata_defaults: Option<InstanceMetadataDefaults>,
1519 #[serde(default)]
1522 pub event_notification_tag_keys: Vec<String>,
1523 #[serde(default)]
1526 pub event_notification_include_all_tags: bool,
1527 #[serde(default)]
1530 pub vpc_bpa_internet_gateway_block_mode: Option<String>,
1531 #[serde(default)]
1534 pub managed_resource_default_visibility: Option<String>,
1535 #[serde(default)]
1538 pub az_group_optin: BTreeMap<String, String>,
1539 #[serde(default)]
1540 pub managed_prefix_lists: BTreeMap<String, ManagedPrefixList>,
1541 #[serde(default)]
1542 pub instance_event_windows: BTreeMap<String, InstanceEventWindow>,
1543 #[serde(default)]
1544 pub traffic_mirror_targets: BTreeMap<String, TrafficMirrorTarget>,
1545 #[serde(default)]
1546 pub traffic_mirror_filters: BTreeMap<String, TrafficMirrorFilter>,
1547 #[serde(default)]
1548 pub traffic_mirror_filter_rules: BTreeMap<String, TrafficMirrorFilterRule>,
1549 #[serde(default)]
1550 pub traffic_mirror_sessions: BTreeMap<String, TrafficMirrorSession>,
1551 #[serde(default)]
1552 pub route_servers: BTreeMap<String, RouteServer>,
1553 #[serde(default)]
1554 pub vpc_encryption_controls: BTreeMap<String, VpcEncryptionControl>,
1555 #[serde(default)]
1556 pub vpc_bpa_exclusions: BTreeMap<String, VpcBpaExclusion>,
1557 #[serde(default)]
1558 pub fpga_images: BTreeMap<String, FpgaImage>,
1559 #[serde(default)]
1562 pub ipam_allocation_descriptions: BTreeMap<String, String>,
1563}
1564
1565impl Ec2State {
1566 pub fn new(account_id: &str, region: &str) -> Self {
1567 let mut state = Self {
1568 account_id: account_id.to_string(),
1569 region: region.to_string(),
1570 ..Default::default()
1571 };
1572 crate::defaults::bootstrap_default_network(&mut state);
1578 crate::defaults::seed_public_images(&mut state);
1582 state
1583 }
1584
1585 pub fn ensure_public_images_seeded(&mut self) {
1591 crate::defaults::seed_public_images(self);
1592 }
1593
1594 pub fn upsert_tags(&mut self, resource_id: &str, new_tags: &[Tag]) {
1597 let entry = self.tags.entry(resource_id.to_string()).or_default();
1598 for t in new_tags {
1599 if let Some(existing) = entry.iter_mut().find(|e| e.key == t.key) {
1600 existing.value = t.value.clone();
1601 } else {
1602 entry.push(t.clone());
1603 }
1604 }
1605 }
1606
1607 pub fn remove_tags(&mut self, resource_id: &str, to_remove: &[(String, Option<String>)]) {
1611 if let Some(entry) = self.tags.get_mut(resource_id) {
1612 for (key, value) in to_remove {
1613 entry.retain(|e| {
1614 if &e.key != key {
1615 return true;
1616 }
1617 match value {
1618 Some(v) => &e.value != v,
1619 None => false,
1620 }
1621 });
1622 }
1623 if entry.is_empty() {
1624 self.tags.remove(resource_id);
1625 }
1626 }
1627 }
1628
1629 pub fn tags_for(&self, resource_id: &str) -> &[Tag] {
1631 self.tags.get(resource_id).map(Vec::as_slice).unwrap_or(&[])
1632 }
1633}
1634
1635#[cfg(test)]
1636mod tests {
1637 use super::*;
1638
1639 fn tag(k: &str, v: &str) -> Tag {
1640 Tag {
1641 key: k.to_string(),
1642 value: v.to_string(),
1643 }
1644 }
1645
1646 #[test]
1647 fn upsert_tags_inserts_then_overwrites_by_key() {
1648 let mut s = Ec2State::new("123456789012", "us-east-1");
1649 s.upsert_tags("vpc-1", &[tag("Name", "a"), tag("env", "dev")]);
1650 s.upsert_tags("vpc-1", &[tag("Name", "b")]);
1651 let tags = s.tags_for("vpc-1");
1652 assert_eq!(tags.len(), 2);
1653 assert_eq!(tags.iter().find(|t| t.key == "Name").unwrap().value, "b");
1654 }
1655
1656 #[test]
1657 fn remove_tags_by_key_and_by_key_value() {
1658 let mut s = Ec2State::new("123456789012", "us-east-1");
1659 s.upsert_tags(
1660 "i-1",
1661 &[tag("Name", "x"), tag("env", "prod"), tag("team", "a")],
1662 );
1663 s.remove_tags("i-1", &[("Name".to_string(), None)]);
1665 s.remove_tags("i-1", &[("env".to_string(), Some("dev".to_string()))]);
1667 s.remove_tags("i-1", &[("team".to_string(), Some("a".to_string()))]);
1669 let tags = s.tags_for("i-1");
1670 assert_eq!(tags.len(), 1);
1671 assert_eq!(tags[0].key, "env");
1672 }
1673
1674 #[test]
1675 fn empty_tag_set_drops_resource_entry() {
1676 let mut s = Ec2State::new("123456789012", "us-east-1");
1677 s.upsert_tags("sg-1", &[tag("Name", "x")]);
1678 s.remove_tags("sg-1", &[("Name".to_string(), None)]);
1679 assert!(!s.tags.contains_key("sg-1"));
1680 }
1681
1682 fn sample_instance() -> Instance {
1683 Instance {
1684 instance_id: "i-1".to_string(),
1685 image_id: "ami-1".to_string(),
1686 instance_type: "t3.micro".to_string(),
1687 state_code: 16,
1688 state_name: "running".to_string(),
1689 private_ip: "10.0.0.1".to_string(),
1690 public_ip: Some("52.0.0.1".to_string()),
1691 subnet_id: Some("subnet-1".to_string()),
1692 vpc_id: Some("vpc-1".to_string()),
1693 key_name: None,
1694 security_group_ids: vec!["sg-1".to_string()],
1695 reservation_id: "r-1".to_string(),
1696 ami_launch_index: 0,
1697 monitoring: false,
1698 az: "us-east-1a".to_string(),
1699 launch_time: "2024-01-01T00:00:00.000Z".to_string(),
1700 container_id: Some("abc".to_string()),
1701 disable_api_termination: true,
1702 disable_api_stop: true,
1703 source_dest_check: false,
1704 ebs_optimized: true,
1705 instance_initiated_shutdown_behavior: "terminate".to_string(),
1706 user_data: Some("ZWNobyBoaQ==".to_string()),
1707 metadata_options: MetadataOptions {
1708 http_tokens: "required".to_string(),
1709 ..MetadataOptions::default()
1710 },
1711 cpu_options: Some(CpuOptions {
1712 core_count: 4,
1713 threads_per_core: 2,
1714 }),
1715 bandwidth_weighting: Some("vpc-1".to_string()),
1716 maintenance_options: MaintenanceOptions::default(),
1717 placement_tenancy: Some("dedicated".to_string()),
1718 placement_affinity: None,
1719 placement_group_name: Some("cluster-1".to_string()),
1720 private_dns_hostname_type: Some("resource-name".to_string()),
1721 enable_resource_name_dns_a_record: true,
1722 enable_resource_name_dns_aaaa_record: false,
1723 }
1724 }
1725
1726 #[test]
1727 fn instance_attributes_round_trip_through_serde() {
1728 let inst = sample_instance();
1729 let json = serde_json::to_string(&inst).unwrap();
1730 let back: Instance = serde_json::from_str(&json).unwrap();
1731 assert!(back.disable_api_termination);
1732 assert!(back.disable_api_stop);
1733 assert!(!back.source_dest_check);
1734 assert!(back.ebs_optimized);
1735 assert_eq!(back.instance_initiated_shutdown_behavior, "terminate");
1736 assert_eq!(back.user_data.as_deref(), Some("ZWNobyBoaQ=="));
1737 assert_eq!(back.metadata_options.http_tokens, "required");
1738 assert_eq!(back.cpu_options.as_ref().unwrap().core_count, 4);
1739 assert_eq!(back.bandwidth_weighting.as_deref(), Some("vpc-1"));
1740 assert_eq!(back.placement_tenancy.as_deref(), Some("dedicated"));
1741 assert_eq!(back.placement_group_name.as_deref(), Some("cluster-1"));
1742 }
1743
1744 #[test]
1745 fn instance_attribute_defaults_load_from_legacy_snapshot() {
1746 let legacy = r#"{
1749 "instance_id":"i-1","image_id":"ami-1","instance_type":"t3.micro",
1750 "state_code":16,"state_name":"running","private_ip":"10.0.0.1",
1751 "public_ip":null,"subnet_id":null,"vpc_id":null,"key_name":null,
1752 "reservation_id":"r-1","ami_launch_index":0,"monitoring":false,
1753 "az":"us-east-1a","launch_time":"2024-01-01T00:00:00.000Z"
1754 }"#;
1755 let inst: Instance = serde_json::from_str(legacy).unwrap();
1756 assert!(!inst.disable_api_termination);
1757 assert!(inst.source_dest_check, "sourceDestCheck defaults to true");
1758 assert_eq!(inst.instance_initiated_shutdown_behavior, "stop");
1759 assert_eq!(inst.metadata_options.http_tokens, "optional");
1760 assert!(inst.cpu_options.is_none());
1761 }
1762}