1use std::collections::HashMap;
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
17impl fakecloud_core::multi_account::AccountState for Ec2State {
18 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
19 Self::new(account_id, region)
20 }
21}
22
23#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
25pub struct Tag {
26 pub key: String,
27 pub value: String,
28}
29
30#[derive(Clone, Debug, Serialize, Deserialize)]
32pub struct VpcCidrAssoc {
33 pub association_id: String,
34 pub cidr_block: String,
35 pub state: String,
37}
38
39#[derive(Clone, Debug, Serialize, Deserialize)]
41pub struct Vpc {
42 pub vpc_id: String,
43 pub cidr_block: String,
44 pub state: String,
46 pub dhcp_options_id: String,
47 pub instance_tenancy: String,
49 pub is_default: bool,
50 pub enable_dns_support: bool,
51 pub enable_dns_hostnames: bool,
52 #[serde(default)]
53 pub cidr_associations: Vec<VpcCidrAssoc>,
54}
55
56#[derive(Clone, Debug, Serialize, Deserialize)]
58pub struct DhcpConfig {
59 pub key: String,
60 pub values: Vec<String>,
61}
62
63#[derive(Clone, Debug, Serialize, Deserialize)]
65pub struct DhcpOptions {
66 pub dhcp_options_id: String,
67 pub configurations: Vec<DhcpConfig>,
68}
69
70#[derive(Clone, Debug, Serialize, Deserialize)]
72pub struct Subnet {
73 pub subnet_id: String,
74 pub vpc_id: String,
75 pub cidr_block: String,
76 pub availability_zone: String,
77 pub availability_zone_id: String,
78 pub state: String,
80 pub available_ip_address_count: i32,
81 pub default_for_az: bool,
82 pub map_public_ip_on_launch: bool,
83 pub assign_ipv6_address_on_creation: bool,
84 pub map_customer_owned_ip_on_launch: bool,
85 pub enable_dns64: bool,
86 pub private_dns_hostname_type: String,
88}
89
90#[derive(Clone, Debug, Serialize, Deserialize)]
92pub struct SubnetCidrReservation {
93 pub subnet_cidr_reservation_id: String,
94 pub subnet_id: String,
95 pub cidr: String,
96 pub reservation_type: String,
98 pub description: String,
99}
100
101#[derive(Clone, Debug, Serialize, Deserialize)]
103pub struct SecurityGroupRule {
104 pub rule_id: String,
105 pub group_id: String,
106 pub is_egress: bool,
107 pub ip_protocol: String,
108 pub from_port: i64,
109 pub to_port: i64,
110 pub cidr_ipv4: Option<String>,
111 pub cidr_ipv6: Option<String>,
112 pub prefix_list_id: Option<String>,
113 pub referenced_group_id: Option<String>,
114 pub description: String,
115}
116
117#[derive(Clone, Debug, Serialize, Deserialize)]
119pub struct SecurityGroup {
120 pub group_id: String,
121 pub group_name: String,
122 pub description: String,
123 pub vpc_id: String,
124 #[serde(default)]
125 pub rules: Vec<SecurityGroupRule>,
126}
127
128#[derive(Clone, Debug, Default, Serialize, Deserialize)]
130pub struct Route {
131 pub destination_cidr_block: Option<String>,
132 pub destination_ipv6_cidr_block: Option<String>,
133 pub destination_prefix_list_id: Option<String>,
134 pub gateway_id: Option<String>,
135 pub nat_gateway_id: Option<String>,
136 pub network_interface_id: Option<String>,
137 pub instance_id: Option<String>,
138 pub vpc_peering_connection_id: Option<String>,
139 pub transit_gateway_id: Option<String>,
140 pub egress_only_internet_gateway_id: Option<String>,
141 pub state: String,
143 pub origin: String,
145}
146
147#[derive(Clone, Debug, Serialize, Deserialize)]
149pub struct RouteTableAssociation {
150 pub association_id: String,
151 pub route_table_id: String,
152 pub subnet_id: Option<String>,
153 pub gateway_id: Option<String>,
154 pub main: bool,
155}
156
157#[derive(Clone, Debug, Serialize, Deserialize)]
159pub struct RouteTable {
160 pub route_table_id: String,
161 pub vpc_id: String,
162 #[serde(default)]
163 pub routes: Vec<Route>,
164 #[serde(default)]
165 pub associations: Vec<RouteTableAssociation>,
166}
167
168#[derive(Clone, Debug, Serialize, Deserialize)]
170pub struct InternetGateway {
171 pub internet_gateway_id: String,
172 #[serde(default)]
174 pub attachments: Vec<(String, String)>,
175}
176
177#[derive(Clone, Debug, Serialize, Deserialize)]
179pub struct NatGateway {
180 pub nat_gateway_id: String,
181 pub subnet_id: String,
182 pub vpc_id: String,
183 pub state: String,
185 pub connectivity_type: String,
187 pub allocation_id: Option<String>,
188}
189
190#[derive(Clone, Debug, Serialize, Deserialize)]
192pub struct ElasticIp {
193 pub allocation_id: String,
194 pub public_ip: String,
195 pub domain: String,
197 pub association_id: Option<String>,
198 pub instance_id: Option<String>,
199 pub network_interface_id: Option<String>,
200 pub private_ip_address: Option<String>,
201}
202
203#[derive(Clone, Debug, Serialize, Deserialize)]
205pub struct KeyPair {
206 pub key_pair_id: String,
207 pub key_name: String,
208 pub key_type: String,
210 pub key_fingerprint: String,
211}
212
213#[derive(Clone, Debug, Serialize, Deserialize)]
215pub struct PlacementGroup {
216 pub group_id: String,
217 pub group_name: String,
218 pub strategy: String,
220 pub state: String,
222 pub partition_count: Option<i64>,
223 pub spread_level: Option<String>,
224}
225
226#[derive(Clone, Debug, Serialize, Deserialize)]
228pub struct EniAttachment {
229 pub attachment_id: String,
230 pub instance_id: String,
231 pub device_index: i64,
232 pub status: String,
234}
235
236#[derive(Clone, Debug, Serialize, Deserialize)]
238pub struct NetworkInterface {
239 pub network_interface_id: String,
240 pub subnet_id: String,
241 pub vpc_id: String,
242 pub availability_zone: String,
243 pub description: String,
244 pub mac_address: String,
245 pub private_ip_address: String,
246 pub status: String,
248 pub interface_type: String,
249 pub source_dest_check: bool,
250 #[serde(default)]
251 pub group_ids: Vec<String>,
252 #[serde(default)]
253 pub private_ips: Vec<String>,
254 #[serde(default)]
255 pub ipv6_addresses: Vec<String>,
256 pub attachment: Option<EniAttachment>,
257}
258
259#[derive(Clone, Debug, Serialize, Deserialize)]
261pub struct NetworkInterfacePermission {
262 pub permission_id: String,
263 pub network_interface_id: String,
264 pub aws_account_id: String,
265 pub permission: String,
267}
268
269#[derive(Clone, Debug, Serialize, Deserialize)]
271pub struct Instance {
272 pub instance_id: String,
273 pub image_id: String,
274 pub instance_type: String,
275 pub state_code: i64,
278 pub state_name: String,
279 pub private_ip: String,
280 pub public_ip: Option<String>,
281 pub subnet_id: Option<String>,
282 pub vpc_id: Option<String>,
283 pub key_name: Option<String>,
284 #[serde(default)]
285 pub security_group_ids: Vec<String>,
286 pub reservation_id: String,
287 pub ami_launch_index: i64,
288 pub monitoring: bool,
289 pub az: String,
290 pub launch_time: String,
291}
292
293#[derive(Clone, Debug, Serialize, Deserialize)]
295pub struct VolumeAttachment {
296 pub volume_id: String,
297 pub instance_id: String,
298 pub device: String,
299 pub status: String,
301 pub delete_on_termination: bool,
302}
303
304#[derive(Clone, Debug, Serialize, Deserialize)]
306pub struct Volume {
307 pub volume_id: String,
308 pub size: i64,
309 pub snapshot_id: Option<String>,
310 pub availability_zone: String,
311 pub state: String,
313 pub volume_type: String,
314 pub iops: Option<i64>,
315 pub throughput: Option<i64>,
316 pub encrypted: bool,
317 pub kms_key_id: Option<String>,
318 pub multi_attach_enabled: bool,
319 pub auto_enable_io: bool,
320 #[serde(default)]
321 pub attachments: Vec<VolumeAttachment>,
322 #[serde(default)]
323 pub in_recycle_bin: bool,
324}
325
326#[derive(Clone, Debug, Serialize, Deserialize)]
328pub struct Snapshot {
329 pub snapshot_id: String,
330 pub volume_id: String,
331 pub state: String,
333 pub volume_size: i64,
334 pub description: String,
335 pub encrypted: bool,
336 pub storage_tier: String,
338 #[serde(default)]
339 pub in_recycle_bin: bool,
340 #[serde(default)]
341 pub locked: bool,
342 pub lock_mode: Option<String>,
343}
344
345#[derive(Clone, Debug, Serialize, Deserialize)]
347pub struct Image {
348 pub image_id: String,
349 pub name: String,
350 pub description: String,
351 pub state: String,
353 pub architecture: String,
354 pub public: bool,
355 pub source_instance_id: Option<String>,
356 #[serde(default)]
357 pub in_recycle_bin: bool,
358 pub deprecation_time: Option<String>,
359 #[serde(default)]
360 pub deregistration_protection: bool,
361}
362
363#[derive(Clone, Debug, Serialize, Deserialize)]
365pub struct NetworkAclEntry {
366 pub rule_number: i64,
367 pub protocol: String,
368 pub rule_action: String,
370 pub egress: bool,
371 pub cidr_block: Option<String>,
372 pub ipv6_cidr_block: Option<String>,
373 pub port_range: Option<(i64, i64)>,
375 pub icmp_type_code: Option<(i64, i64)>,
377}
378
379#[derive(Clone, Debug, Serialize, Deserialize)]
381pub struct NetworkAclAssoc {
382 pub association_id: String,
383 pub subnet_id: String,
384}
385
386#[derive(Clone, Debug, Serialize, Deserialize)]
388pub struct NetworkAcl {
389 pub network_acl_id: String,
390 pub vpc_id: String,
391 pub is_default: bool,
392 #[serde(default)]
393 pub entries: Vec<NetworkAclEntry>,
394 #[serde(default)]
395 pub associations: Vec<NetworkAclAssoc>,
396}
397
398#[derive(Clone, Debug, Serialize, Deserialize)]
400pub struct VpcPeering {
401 pub id: String,
402 pub requester_vpc_id: String,
403 pub accepter_vpc_id: String,
404 pub status: String,
406 #[serde(default)]
408 pub requester_allow_dns: bool,
409 #[serde(default)]
411 pub accepter_allow_dns: bool,
412}
413
414#[derive(Clone, Debug, Serialize, Deserialize)]
416pub struct VpcEndpoint {
417 pub id: String,
418 pub endpoint_type: String,
420 pub vpc_id: String,
421 pub service_name: String,
422 pub state: String,
423 #[serde(default)]
424 pub subnet_ids: Vec<String>,
425 #[serde(default)]
426 pub route_table_ids: Vec<String>,
427 #[serde(default)]
428 pub private_dns_enabled: bool,
429}
430
431#[derive(Clone, Debug, Serialize, Deserialize)]
433pub struct EndpointService {
434 pub service_id: String,
435 pub service_name: String,
436 pub state: String,
437 pub acceptance_required: bool,
438 pub payer_responsibility: String,
439 #[serde(default)]
440 pub nlb_arns: Vec<String>,
441}
442
443#[derive(Clone, Debug, Serialize, Deserialize)]
445pub struct ConnectionNotification {
446 pub id: String,
447 pub arn: String,
448 pub service_id: Option<String>,
449 #[serde(default)]
450 pub events: Vec<String>,
451}
452
453#[derive(Clone, Debug, Serialize, Deserialize)]
455pub struct FlowLog {
456 pub id: String,
457 pub resource_id: String,
458 pub traffic_type: String,
459 pub log_destination_type: String,
460 pub log_group_name: Option<String>,
461 pub log_destination: Option<String>,
463}
464
465#[derive(Clone, Debug, Serialize, Deserialize)]
467pub struct LaunchTemplate {
468 pub id: String,
469 pub name: String,
470 pub default_version: i64,
471 pub latest_version: i64,
472}
473
474#[derive(Clone, Debug, Serialize, Deserialize)]
476pub struct SpotRequest {
477 pub id: String,
478 pub state: String,
480 pub request_type: String,
481 pub spot_price: String,
482}
483
484#[derive(Clone, Debug, Serialize, Deserialize)]
486pub struct SpotFleet {
487 pub id: String,
488 pub state: String,
489}
490
491#[derive(Clone, Debug, Serialize, Deserialize)]
493pub struct Fleet {
494 pub id: String,
495 pub state: String,
496 pub fleet_type: String,
497}
498
499#[derive(Clone, Debug, Serialize, Deserialize)]
501pub struct CapacityReservation {
502 pub id: String,
503 pub instance_type: String,
504 pub instance_platform: String,
505 pub availability_zone: String,
506 pub tenancy: String,
507 pub total_instance_count: i64,
508 pub available_instance_count: i64,
509 pub state: String,
511 pub end_date_type: String,
512 pub instance_match_criteria: String,
513}
514
515#[derive(Clone, Debug, Serialize, Deserialize)]
517pub struct ReservedInstances {
518 pub id: String,
519 pub instance_type: String,
520 pub availability_zone: String,
521 pub instance_count: i64,
522 pub product_description: String,
523 pub state: String,
524 pub duration: i64,
525 pub fixed_price: String,
526 pub usage_price: String,
527}
528
529#[derive(Clone, Debug, Serialize, Deserialize)]
531pub struct DedicatedHost {
532 pub id: String,
533 pub auto_placement: String,
534 pub availability_zone: String,
535 pub instance_type: String,
536 pub state: String,
537 pub host_recovery: String,
538 pub host_maintenance: String,
539}
540
541#[derive(Clone, Debug, Serialize, Deserialize)]
543pub struct TransitGateway {
544 pub id: String,
545 pub description: String,
546 #[serde(default = "tgw_default_state")]
548 pub state: String,
549}
550
551fn tgw_default_state() -> String {
552 "available".to_string()
553}
554
555#[derive(Clone, Debug, Serialize, Deserialize)]
557pub struct TgwAttachment {
558 pub id: String,
559 pub tgw_id: String,
560 pub resource_id: String,
561 pub resource_type: String,
562 #[serde(default)]
563 pub subnet_ids: Vec<String>,
564 pub state: String,
565}
566
567#[derive(Clone, Debug, Serialize, Deserialize)]
569pub struct TgwRouteTable {
570 pub id: String,
571 pub tgw_id: String,
572}
573
574#[derive(Clone, Debug, Serialize, Deserialize)]
576pub struct TgwRoute {
577 pub cidr: String,
578 pub attachment_id: String,
579 pub state: String,
580}
581
582#[derive(Clone, Debug, Serialize, Deserialize)]
584pub struct TgwMulticastDomain {
585 pub id: String,
586 pub tgw_id: String,
587}
588
589#[derive(Clone, Debug, Serialize, Deserialize)]
591pub struct TgwMeteringPolicy {
592 pub id: String,
593 pub tgw_id: String,
594}
595
596#[derive(Clone, Debug, Serialize, Deserialize)]
598pub struct CustomerGateway {
599 pub id: String,
600 pub state: String,
601 pub ip_address: String,
602 pub bgp_asn: String,
603}
604
605#[derive(Clone, Debug, Serialize, Deserialize)]
607pub struct VpnGateway {
608 pub id: String,
609 pub state: String,
610 #[serde(default)]
611 pub attachments: Vec<String>,
612}
613
614#[derive(Clone, Debug, Serialize, Deserialize)]
616pub struct VpnConnection {
617 pub id: String,
618 pub state: String,
619 pub customer_gateway_id: String,
620 pub vpn_gateway_id: Option<String>,
621 #[serde(default)]
622 pub routes: Vec<String>,
623}
624
625#[derive(Clone, Debug, Serialize, Deserialize)]
627pub struct VpnConcentrator {
628 pub id: String,
629 pub state: String,
630}
631
632#[derive(Clone, Debug, Serialize, Deserialize)]
634pub struct Ipam {
635 pub id: String,
636 pub public_scope_id: String,
637 pub private_scope_id: String,
638 pub tier: String,
639 #[serde(default)]
640 pub description: String,
641}
642
643#[derive(Clone, Debug, Serialize, Deserialize)]
645pub struct IpamScope {
646 pub id: String,
647 pub ipam_id: String,
648 #[serde(default)]
650 pub scope_type: String,
651 #[serde(default)]
652 pub description: String,
653}
654
655#[derive(Clone, Debug, Serialize, Deserialize)]
657pub struct IpamPool {
658 pub id: String,
659 pub scope_id: String,
660 pub address_family: String,
661 #[serde(default)]
662 pub description: String,
663}
664
665#[derive(Clone, Debug, Serialize, Deserialize)]
667pub struct IpamResourceDiscovery {
668 pub id: String,
669 #[serde(default)]
670 pub description: String,
671}
672
673#[derive(Clone, Debug, Serialize, Deserialize)]
675pub struct IpamPolicy {
676 pub id: String,
677 pub ipam_id: String,
678}
679
680#[derive(Clone, Debug, Serialize, Deserialize)]
682pub struct IpamPrefixListResolver {
683 pub id: String,
684 pub ipam_id: String,
685 pub address_family: String,
686 #[serde(default)]
687 pub description: String,
688}
689
690#[derive(Clone, Debug, Serialize, Deserialize)]
692pub struct IpamPrefixListResolverTarget {
693 pub id: String,
694 pub resolver_id: String,
695 pub prefix_list_id: String,
696 pub prefix_list_region: String,
697 #[serde(default)]
698 pub track_latest_version: bool,
699}
700
701#[derive(Clone, Debug, Serialize, Deserialize)]
703pub struct VerifiedAccessInstance {
704 pub id: String,
705 pub description: String,
706 #[serde(default)]
707 pub trust_providers: Vec<String>,
708}
709
710#[derive(Clone, Debug, Serialize, Deserialize)]
712pub struct VerifiedAccessTrustProvider {
713 pub id: String,
714 pub trust_provider_type: String,
715 pub policy_reference_name: String,
716 pub description: String,
717}
718
719#[derive(Clone, Debug, Serialize, Deserialize)]
721pub struct VerifiedAccessGroup {
722 pub id: String,
723 pub instance_id: String,
724 pub description: String,
725}
726
727#[derive(Clone, Debug, Serialize, Deserialize)]
729pub struct VerifiedAccessEndpoint {
730 pub id: String,
731 pub group_id: String,
732 pub instance_id: String,
733 pub endpoint_type: String,
734 pub attachment_type: String,
735}
736
737#[derive(Clone, Debug, Serialize, Deserialize)]
739pub struct NetworkInsightsPath {
740 pub id: String,
741 pub source: String,
742 pub destination: String,
743 pub protocol: String,
744}
745
746#[derive(Clone, Debug, Serialize, Deserialize)]
748pub struct NetworkInsightsAnalysis {
749 pub id: String,
750 pub path_id: String,
751}
752
753#[derive(Clone, Debug, Serialize, Deserialize)]
755pub struct NetworkInsightsAccessScope {
756 pub id: String,
757}
758
759#[derive(Clone, Debug, Serialize, Deserialize)]
761pub struct NetworkInsightsAccessScopeAnalysis {
762 pub id: String,
763 pub scope_id: String,
764}
765
766#[derive(Clone, Debug, Serialize, Deserialize)]
768pub struct CarrierGateway {
769 pub id: String,
770 pub vpc_id: String,
771}
772
773#[derive(Clone, Debug, Serialize, Deserialize)]
775pub struct InstanceConnectEndpoint {
776 pub id: String,
777 pub subnet_id: String,
778}
779
780#[derive(Clone, Debug, Serialize, Deserialize)]
782pub struct CoipPool {
783 pub id: String,
784 pub route_table_id: String,
785}
786
787#[derive(Clone, Debug, Serialize, Deserialize)]
789pub struct LocalGatewayRouteTable {
790 pub id: String,
791 pub local_gateway_id: String,
792 pub mode: String,
793}
794
795#[derive(Clone, Debug, Serialize, Deserialize)]
797pub struct LocalGatewayRouteTableVpcAssoc {
798 pub id: String,
799 pub route_table_id: String,
800 pub vpc_id: String,
801}
802
803#[derive(Clone, Debug, Serialize, Deserialize)]
805pub struct LocalGatewayVif {
806 pub id: String,
807 pub group_id: String,
808 pub vlan: String,
809 pub local_address: String,
810 pub peer_address: String,
811}
812
813#[derive(Clone, Debug, Serialize, Deserialize)]
815pub struct LocalGatewayVifGroup {
816 pub id: String,
817 pub local_gateway_id: String,
818}
819
820#[derive(Clone, Debug, Serialize, Deserialize)]
822pub struct LocalGatewayRouteTableVifgAssoc {
823 pub id: String,
824 pub route_table_id: String,
825 pub vif_group_id: String,
826}
827
828#[derive(Clone, Debug, Serialize, Deserialize)]
830pub struct ClientVpnEndpoint {
831 pub id: String,
832 pub description: String,
833 pub status: String,
834 pub server_cert_arn: String,
835 pub transport_protocol: String,
836 pub client_cidr: String,
837 #[serde(default)]
838 pub routes: Vec<String>,
839 #[serde(default)]
841 pub target_networks: Vec<(String, String)>,
842 #[serde(default)]
844 pub auth_rules: Vec<String>,
845}
846
847#[derive(Clone, Debug, Serialize, Deserialize)]
849pub struct TgwPeering {
850 pub id: String,
851 pub tgw_id: String,
852 pub peer_tgw_id: String,
853 pub peer_account: String,
854 pub peer_region: String,
855 pub state: String,
856}
857
858#[derive(Clone, Debug, Default, Serialize, Deserialize)]
861pub struct Ec2State {
862 pub account_id: String,
863 pub region: String,
864 #[serde(default)]
866 pub tags: HashMap<String, Vec<Tag>>,
867 #[serde(default)]
868 pub vpcs: HashMap<String, Vpc>,
869 #[serde(default)]
870 pub dhcp_options: HashMap<String, DhcpOptions>,
871 #[serde(default)]
872 pub subnets: HashMap<String, Subnet>,
873 #[serde(default)]
874 pub subnet_cidr_reservations: HashMap<String, SubnetCidrReservation>,
875 #[serde(default)]
876 pub security_groups: HashMap<String, SecurityGroup>,
877 #[serde(default)]
878 pub route_tables: HashMap<String, RouteTable>,
879 #[serde(default)]
880 pub internet_gateways: HashMap<String, InternetGateway>,
881 #[serde(default)]
882 pub egress_only_igws: HashMap<String, InternetGateway>,
883 #[serde(default)]
884 pub nat_gateways: HashMap<String, NatGateway>,
885 #[serde(default)]
887 pub elastic_ips: HashMap<String, ElasticIp>,
888 #[serde(default)]
890 pub key_pairs: HashMap<String, KeyPair>,
891 #[serde(default)]
893 pub placement_groups: HashMap<String, PlacementGroup>,
894 #[serde(default)]
895 pub network_interfaces: HashMap<String, NetworkInterface>,
896 #[serde(default)]
898 pub eni_permissions: HashMap<String, NetworkInterfacePermission>,
899 #[serde(default)]
900 pub instances: HashMap<String, Instance>,
901 #[serde(default)]
902 pub volumes: HashMap<String, Volume>,
903 #[serde(default)]
905 pub ebs_encryption_default: bool,
906 #[serde(default)]
908 pub ebs_default_kms_key_id: Option<String>,
909 #[serde(default)]
910 pub snapshots: HashMap<String, Snapshot>,
911 #[serde(default)]
913 pub snapshot_block_public_access: String,
914 #[serde(default)]
915 pub images: HashMap<String, Image>,
916 #[serde(default)]
918 pub image_block_public_access: String,
919 #[serde(default)]
921 pub allowed_images_settings: String,
922 #[serde(default)]
923 pub network_acls: HashMap<String, NetworkAcl>,
924 #[serde(default)]
925 pub vpc_peerings: HashMap<String, VpcPeering>,
926 #[serde(default)]
927 pub vpc_endpoints: HashMap<String, VpcEndpoint>,
928 #[serde(default)]
929 pub endpoint_services: HashMap<String, EndpointService>,
930 #[serde(default)]
931 pub connection_notifications: HashMap<String, ConnectionNotification>,
932 #[serde(default)]
933 pub flow_logs: HashMap<String, FlowLog>,
934 #[serde(default)]
935 pub launch_templates: HashMap<String, LaunchTemplate>,
936 #[serde(default)]
937 pub spot_requests: HashMap<String, SpotRequest>,
938 #[serde(default)]
939 pub spot_fleets: HashMap<String, SpotFleet>,
940 #[serde(default)]
941 pub fleets: HashMap<String, Fleet>,
942 #[serde(default)]
944 pub spot_datafeed: Option<(String, String)>,
945 #[serde(default)]
946 pub capacity_reservations: HashMap<String, CapacityReservation>,
947 #[serde(default)]
949 pub capacity_reservation_fleets: HashMap<String, String>,
950 #[serde(default)]
951 pub reserved_instances: HashMap<String, ReservedInstances>,
952 #[serde(default)]
953 pub dedicated_hosts: HashMap<String, DedicatedHost>,
954 #[serde(default)]
955 pub transit_gateways: HashMap<String, TransitGateway>,
956 #[serde(default)]
957 pub tgw_attachments: HashMap<String, TgwAttachment>,
958 #[serde(default)]
959 pub tgw_route_tables: HashMap<String, TgwRouteTable>,
960 #[serde(default)]
962 pub tgw_routes: HashMap<String, Vec<TgwRoute>>,
963 #[serde(default)]
965 pub tgw_rt_associations: HashMap<String, Vec<String>>,
966 #[serde(default)]
968 pub tgw_rt_propagations: HashMap<String, Vec<String>>,
969 #[serde(default)]
971 pub tgw_prefix_list_refs: HashMap<String, Vec<String>>,
972 #[serde(default)]
973 pub tgw_peerings: HashMap<String, TgwPeering>,
974 #[serde(default)]
976 pub tgw_connects: HashMap<String, (String, String)>,
977 #[serde(default)]
979 pub tgw_connect_peers: HashMap<String, String>,
980 #[serde(default)]
982 pub tgw_policy_tables: HashMap<String, String>,
983 #[serde(default)]
985 pub tgw_policy_table_associations: HashMap<String, Vec<String>>,
986 #[serde(default)]
988 pub tgw_announcements: HashMap<String, (String, String)>,
989 #[serde(default)]
990 pub tgw_multicast_domains: HashMap<String, TgwMulticastDomain>,
991 #[serde(default)]
992 pub tgw_metering_policies: HashMap<String, TgwMeteringPolicy>,
993 #[serde(default)]
994 pub customer_gateways: HashMap<String, CustomerGateway>,
995 #[serde(default)]
996 pub vpn_gateways: HashMap<String, VpnGateway>,
997 #[serde(default)]
998 pub vpn_connections: HashMap<String, VpnConnection>,
999 #[serde(default)]
1000 pub vpn_concentrators: HashMap<String, VpnConcentrator>,
1001 #[serde(default)]
1002 pub client_vpn_endpoints: HashMap<String, ClientVpnEndpoint>,
1003 #[serde(default)]
1004 pub ipams: HashMap<String, Ipam>,
1005 #[serde(default)]
1006 pub ipam_scopes: HashMap<String, IpamScope>,
1007 #[serde(default)]
1008 pub ipam_pools: HashMap<String, IpamPool>,
1009 #[serde(default)]
1011 pub ipam_pool_cidrs: HashMap<String, Vec<(String, String)>>,
1012 #[serde(default)]
1014 pub ipam_pool_allocations: HashMap<String, Vec<(String, String)>>,
1015 #[serde(default)]
1016 pub ipam_resource_discoveries: HashMap<String, IpamResourceDiscovery>,
1017 #[serde(default)]
1019 pub ipam_rd_associations: HashMap<String, (String, String)>,
1020 #[serde(default)]
1022 pub ipam_byoasns: HashMap<String, String>,
1023 #[serde(default)]
1025 pub ipam_ext_tokens: HashMap<String, String>,
1026 #[serde(default)]
1027 pub ipam_policies: HashMap<String, IpamPolicy>,
1028 #[serde(default)]
1029 pub ipam_pl_resolvers: HashMap<String, IpamPrefixListResolver>,
1030 #[serde(default)]
1031 pub ipam_pl_resolver_targets: HashMap<String, IpamPrefixListResolverTarget>,
1032 #[serde(default)]
1034 pub ipam_policy_alloc_rules: HashMap<String, Vec<(String, String)>>,
1035 #[serde(default)]
1037 pub ipam_enabled_policy: Option<String>,
1038 #[serde(default)]
1039 pub va_instances: HashMap<String, VerifiedAccessInstance>,
1040 #[serde(default)]
1041 pub va_trust_providers: HashMap<String, VerifiedAccessTrustProvider>,
1042 #[serde(default)]
1043 pub va_groups: HashMap<String, VerifiedAccessGroup>,
1044 #[serde(default)]
1045 pub va_endpoints: HashMap<String, VerifiedAccessEndpoint>,
1046 #[serde(default)]
1048 pub va_group_policies: HashMap<String, String>,
1049 #[serde(default)]
1051 pub va_endpoint_policies: HashMap<String, String>,
1052 #[serde(default)]
1053 pub ni_paths: HashMap<String, NetworkInsightsPath>,
1054 #[serde(default)]
1055 pub ni_analyses: HashMap<String, NetworkInsightsAnalysis>,
1056 #[serde(default)]
1057 pub ni_access_scopes: HashMap<String, NetworkInsightsAccessScope>,
1058 #[serde(default)]
1059 pub ni_scope_analyses: HashMap<String, NetworkInsightsAccessScopeAnalysis>,
1060 #[serde(default)]
1061 pub carrier_gateways: HashMap<String, CarrierGateway>,
1062 #[serde(default)]
1063 pub coip_pools: HashMap<String, CoipPool>,
1064 #[serde(default)]
1066 pub coip_pool_cidrs: HashMap<String, Vec<String>>,
1067 #[serde(default)]
1068 pub lg_route_tables: HashMap<String, LocalGatewayRouteTable>,
1069 #[serde(default)]
1071 pub lg_routes: HashMap<String, Vec<String>>,
1072 #[serde(default)]
1073 pub lg_rt_vpc_assocs: HashMap<String, LocalGatewayRouteTableVpcAssoc>,
1074 #[serde(default)]
1075 pub lg_virtual_interfaces: HashMap<String, LocalGatewayVif>,
1076 #[serde(default)]
1077 pub lg_vif_groups: HashMap<String, LocalGatewayVifGroup>,
1078 #[serde(default)]
1079 pub lg_rt_vifg_assocs: HashMap<String, LocalGatewayRouteTableVifgAssoc>,
1080 #[serde(default)]
1081 pub instance_connect_endpoints: HashMap<String, InstanceConnectEndpoint>,
1082 #[serde(default)]
1084 pub fast_launch_images: std::collections::HashSet<String>,
1085 #[serde(default)]
1086 pub serial_console_access: bool,
1087}
1088
1089impl Ec2State {
1090 pub fn new(account_id: &str, region: &str) -> Self {
1091 Self {
1092 account_id: account_id.to_string(),
1093 region: region.to_string(),
1094 ..Default::default()
1095 }
1096 }
1097
1098 pub fn upsert_tags(&mut self, resource_id: &str, new_tags: &[Tag]) {
1101 let entry = self.tags.entry(resource_id.to_string()).or_default();
1102 for t in new_tags {
1103 if let Some(existing) = entry.iter_mut().find(|e| e.key == t.key) {
1104 existing.value = t.value.clone();
1105 } else {
1106 entry.push(t.clone());
1107 }
1108 }
1109 }
1110
1111 pub fn remove_tags(&mut self, resource_id: &str, to_remove: &[(String, Option<String>)]) {
1115 if let Some(entry) = self.tags.get_mut(resource_id) {
1116 for (key, value) in to_remove {
1117 entry.retain(|e| {
1118 if &e.key != key {
1119 return true;
1120 }
1121 match value {
1122 Some(v) => &e.value != v,
1123 None => false,
1124 }
1125 });
1126 }
1127 if entry.is_empty() {
1128 self.tags.remove(resource_id);
1129 }
1130 }
1131 }
1132
1133 pub fn tags_for(&self, resource_id: &str) -> &[Tag] {
1135 self.tags.get(resource_id).map(Vec::as_slice).unwrap_or(&[])
1136 }
1137}
1138
1139#[cfg(test)]
1140mod tests {
1141 use super::*;
1142
1143 fn tag(k: &str, v: &str) -> Tag {
1144 Tag {
1145 key: k.to_string(),
1146 value: v.to_string(),
1147 }
1148 }
1149
1150 #[test]
1151 fn upsert_tags_inserts_then_overwrites_by_key() {
1152 let mut s = Ec2State::new("123456789012", "us-east-1");
1153 s.upsert_tags("vpc-1", &[tag("Name", "a"), tag("env", "dev")]);
1154 s.upsert_tags("vpc-1", &[tag("Name", "b")]);
1155 let tags = s.tags_for("vpc-1");
1156 assert_eq!(tags.len(), 2);
1157 assert_eq!(tags.iter().find(|t| t.key == "Name").unwrap().value, "b");
1158 }
1159
1160 #[test]
1161 fn remove_tags_by_key_and_by_key_value() {
1162 let mut s = Ec2State::new("123456789012", "us-east-1");
1163 s.upsert_tags(
1164 "i-1",
1165 &[tag("Name", "x"), tag("env", "prod"), tag("team", "a")],
1166 );
1167 s.remove_tags("i-1", &[("Name".to_string(), None)]);
1169 s.remove_tags("i-1", &[("env".to_string(), Some("dev".to_string()))]);
1171 s.remove_tags("i-1", &[("team".to_string(), Some("a".to_string()))]);
1173 let tags = s.tags_for("i-1");
1174 assert_eq!(tags.len(), 1);
1175 assert_eq!(tags[0].key, "env");
1176 }
1177
1178 #[test]
1179 fn empty_tag_set_drops_resource_entry() {
1180 let mut s = Ec2State::new("123456789012", "us-east-1");
1181 s.upsert_tags("sg-1", &[tag("Name", "x")]);
1182 s.remove_tags("sg-1", &[("Name".to_string(), None)]);
1183 assert!(!s.tags.contains_key("sg-1"));
1184 }
1185}