Skip to main content

fakecloud_ssm/
state.rs

1use chrono::{DateTime, Utc};
2use parking_lot::RwLock;
3use std::collections::{BTreeMap, HashMap};
4use std::sync::Arc;
5
6#[derive(Debug, Clone)]
7pub struct SsmParameter {
8    pub name: String,
9    pub value: String,
10    pub param_type: String, // String, StringList, SecureString
11    pub version: i64,
12    pub arn: String,
13    pub last_modified: DateTime<Utc>,
14    pub history: Vec<SsmParameterVersion>,
15    pub tags: HashMap<String, String>,
16    pub labels: HashMap<i64, Vec<String>>, // version -> labels
17    pub description: Option<String>,
18    pub allowed_pattern: Option<String>,
19    pub key_id: Option<String>,
20    pub data_type: String, // "text" or "aws:ec2:image"
21    pub tier: String,      // "Standard", "Advanced", "Intelligent-Tiering"
22    pub policies: Option<String>,
23}
24
25#[derive(Debug, Clone)]
26pub struct SsmParameterVersion {
27    pub value: String,
28    pub version: i64,
29    pub last_modified: DateTime<Utc>,
30    pub param_type: String,
31    pub description: Option<String>,
32    pub key_id: Option<String>,
33    pub labels: Vec<String>,
34}
35
36#[derive(Debug, Clone)]
37pub struct SsmDocument {
38    pub name: String,
39    pub content: String,
40    pub document_type: String,
41    pub document_format: String,
42    pub target_type: Option<String>,
43    pub version_name: Option<String>,
44    pub tags: HashMap<String, String>,
45    pub versions: Vec<SsmDocumentVersion>,
46    pub default_version: String,
47    pub latest_version: String,
48    pub created_date: DateTime<Utc>,
49    pub owner: String,
50    pub status: String,
51    pub permissions: HashMap<String, Vec<String>>, // permission_type -> account_ids
52}
53
54#[derive(Debug, Clone)]
55pub struct SsmDocumentVersion {
56    pub content: String,
57    pub document_version: String,
58    pub version_name: Option<String>,
59    pub created_date: DateTime<Utc>,
60    pub status: String,
61    pub document_format: String,
62    pub is_default_version: bool,
63}
64
65#[derive(Debug, Clone)]
66pub struct SsmCommand {
67    pub command_id: String,
68    pub document_name: String,
69    pub instance_ids: Vec<String>,
70    pub parameters: HashMap<String, Vec<String>>,
71    pub status: String,
72    pub requested_date_time: DateTime<Utc>,
73    pub comment: Option<String>,
74    pub output_s3_bucket_name: Option<String>,
75    pub output_s3_key_prefix: Option<String>,
76    pub output_s3_region: Option<String>,
77    pub timeout_seconds: Option<i64>,
78    pub service_role_arn: Option<String>,
79    pub notification_config: Option<serde_json::Value>,
80    pub targets: Vec<serde_json::Value>,
81    pub document_hash: Option<String>,
82    pub document_hash_type: Option<String>,
83}
84
85#[derive(Debug, Clone)]
86pub struct MaintenanceWindowTarget {
87    pub window_target_id: String,
88    pub window_id: String,
89    pub resource_type: String,
90    pub targets: Vec<serde_json::Value>,
91    pub name: Option<String>,
92    pub description: Option<String>,
93    pub owner_information: Option<String>,
94}
95
96#[derive(Debug, Clone)]
97pub struct MaintenanceWindowTask {
98    pub window_task_id: String,
99    pub window_id: String,
100    pub task_arn: String,
101    pub task_type: String,
102    pub targets: Vec<serde_json::Value>,
103    pub max_concurrency: Option<String>,
104    pub max_errors: Option<String>,
105    pub priority: i64,
106    pub service_role_arn: Option<String>,
107    pub name: Option<String>,
108    pub description: Option<String>,
109}
110
111#[derive(Debug, Clone)]
112pub struct MaintenanceWindow {
113    pub id: String,
114    pub name: String,
115    pub schedule: String,
116    pub duration: i64,
117    pub cutoff: i64,
118    pub allow_unassociated_targets: bool,
119    pub enabled: bool,
120    pub description: Option<String>,
121    pub tags: HashMap<String, String>,
122    pub targets: Vec<MaintenanceWindowTarget>,
123    pub tasks: Vec<MaintenanceWindowTask>,
124    pub schedule_timezone: Option<String>,
125    pub schedule_offset: Option<i64>,
126    pub start_date: Option<String>,
127    pub end_date: Option<String>,
128    pub client_token: Option<String>,
129}
130
131#[derive(Debug, Clone)]
132pub struct PatchBaseline {
133    pub id: String,
134    pub name: String,
135    pub operating_system: String,
136    pub description: Option<String>,
137    pub approval_rules: Option<serde_json::Value>,
138    pub approved_patches: Vec<String>,
139    pub rejected_patches: Vec<String>,
140    pub tags: HashMap<String, String>,
141    pub approved_patches_compliance_level: String,
142    pub rejected_patches_action: String,
143    pub global_filters: Option<serde_json::Value>,
144    pub sources: Vec<serde_json::Value>,
145    pub approved_patches_enable_non_security: bool,
146    pub available_security_updates_compliance_status: Option<String>,
147    pub client_token: Option<String>,
148}
149
150#[derive(Debug, Clone)]
151pub struct PatchGroup {
152    pub baseline_id: String,
153    pub patch_group: String,
154}
155
156#[derive(Debug, Clone)]
157pub struct SsmAssociation {
158    pub association_id: String,
159    pub name: String, // document name
160    pub targets: Vec<serde_json::Value>,
161    pub schedule_expression: Option<String>,
162    pub parameters: HashMap<String, Vec<String>>,
163    pub association_name: Option<String>,
164    pub document_version: Option<String>,
165    pub output_location: Option<serde_json::Value>,
166    pub automation_target_parameter_name: Option<String>,
167    pub max_errors: Option<String>,
168    pub max_concurrency: Option<String>,
169    pub compliance_severity: Option<String>,
170    pub sync_compliance: Option<String>,
171    pub apply_only_at_cron_interval: bool,
172    pub calendar_names: Vec<String>,
173    pub target_locations: Vec<serde_json::Value>,
174    pub schedule_offset: Option<i64>,
175    pub target_maps: Vec<serde_json::Value>,
176    pub tags: HashMap<String, String>,
177    pub status: String,
178    pub status_date: DateTime<Utc>,
179    pub overview: serde_json::Value,
180    pub created_date: DateTime<Utc>,
181    pub last_update_association_date: DateTime<Utc>,
182    pub last_execution_date: Option<DateTime<Utc>>,
183    pub instance_id: Option<String>,
184    pub versions: Vec<SsmAssociationVersion>,
185}
186
187#[derive(Debug, Clone)]
188pub struct SsmAssociationVersion {
189    pub version: i64,
190    pub name: String,
191    pub targets: Vec<serde_json::Value>,
192    pub schedule_expression: Option<String>,
193    pub parameters: HashMap<String, Vec<String>>,
194    pub document_version: Option<String>,
195    pub created_date: DateTime<Utc>,
196    pub association_name: Option<String>,
197    pub max_errors: Option<String>,
198    pub max_concurrency: Option<String>,
199    pub compliance_severity: Option<String>,
200}
201
202#[derive(Debug, Clone)]
203pub struct SsmOpsItem {
204    pub ops_item_id: String,
205    pub title: String,
206    pub description: Option<String>,
207    pub source: String,
208    pub status: String,
209    pub priority: Option<i64>,
210    pub severity: Option<String>,
211    pub category: Option<String>,
212    pub operational_data: HashMap<String, serde_json::Value>,
213    pub notifications: Vec<serde_json::Value>,
214    pub related_ops_items: Vec<serde_json::Value>,
215    pub tags: HashMap<String, String>,
216    pub created_time: DateTime<Utc>,
217    pub last_modified_time: DateTime<Utc>,
218    pub created_by: String,
219    pub last_modified_by: String,
220    pub ops_item_type: Option<String>,
221    pub planned_start_time: Option<DateTime<Utc>>,
222    pub planned_end_time: Option<DateTime<Utc>>,
223    pub actual_start_time: Option<DateTime<Utc>>,
224    pub actual_end_time: Option<DateTime<Utc>>,
225}
226
227#[derive(Debug, Clone)]
228pub struct SsmResourcePolicy {
229    pub policy_id: String,
230    pub policy_hash: String,
231    pub policy: String,
232    pub resource_arn: String,
233}
234
235#[derive(Debug, Clone)]
236pub struct SsmServiceSetting {
237    pub setting_id: String,
238    pub setting_value: String,
239    pub last_modified_date: DateTime<Utc>,
240    pub last_modified_user: String,
241    pub status: String,
242}
243
244#[derive(Debug, Clone)]
245pub struct OpsItemRelatedItem {
246    pub association_id: String,
247    pub ops_item_id: String,
248    pub association_type: String,
249    pub resource_type: String,
250    pub resource_uri: String,
251    pub created_time: DateTime<Utc>,
252    pub created_by: String,
253    pub last_modified_time: DateTime<Utc>,
254    pub last_modified_by: String,
255}
256
257#[derive(Debug, Clone)]
258pub struct OpsItemEvent {
259    pub ops_item_id: String,
260    pub event_id: String,
261    pub source: String,
262    pub detail_type: String,
263    pub created_time: DateTime<Utc>,
264    pub created_by: String,
265}
266
267#[derive(Debug, Clone)]
268pub struct OpsMetadataEntry {
269    pub ops_metadata_arn: String,
270    pub resource_id: String,
271    pub metadata: HashMap<String, serde_json::Value>,
272    pub creation_date: DateTime<Utc>,
273}
274
275#[derive(Debug, Clone)]
276pub struct AutomationExecution {
277    pub automation_execution_id: String,
278    pub document_name: String,
279    pub document_version: Option<String>,
280    pub automation_execution_status: String,
281    pub execution_start_time: DateTime<Utc>,
282    pub execution_end_time: Option<DateTime<Utc>>,
283    pub parameters: HashMap<String, Vec<String>>,
284    pub outputs: HashMap<String, Vec<String>>,
285    pub mode: String,
286    pub target: Option<String>,
287    pub targets: Vec<serde_json::Value>,
288    pub max_concurrency: Option<String>,
289    pub max_errors: Option<String>,
290    pub executed_by: String,
291    pub step_executions: Vec<AutomationStepExecution>,
292    pub automation_subtype: Option<String>,
293    pub runbooks: Vec<serde_json::Value>,
294    pub change_request_name: Option<String>,
295    pub scheduled_time: Option<DateTime<Utc>>,
296}
297
298#[derive(Debug, Clone)]
299pub struct AutomationStepExecution {
300    pub step_name: String,
301    pub action: String,
302    pub step_status: String,
303    pub execution_start_time: Option<DateTime<Utc>>,
304    pub execution_end_time: Option<DateTime<Utc>>,
305    pub inputs: HashMap<String, String>,
306    pub outputs: HashMap<String, Vec<String>>,
307    pub step_execution_id: String,
308}
309
310#[derive(Debug, Clone)]
311pub struct SsmSession {
312    pub session_id: String,
313    pub target: String,
314    pub status: String,
315    pub start_date: DateTime<Utc>,
316    pub end_date: Option<DateTime<Utc>>,
317    pub owner: String,
318    pub reason: Option<String>,
319}
320
321#[derive(Debug, Clone)]
322pub struct SsmActivation {
323    pub activation_id: String,
324    pub iam_role: String,
325    pub registration_limit: i64,
326    pub registrations_count: i64,
327    pub expiration_date: Option<DateTime<Utc>>,
328    pub description: Option<String>,
329    pub default_instance_name: Option<String>,
330    pub created_date: DateTime<Utc>,
331    pub expired: bool,
332    pub tags: HashMap<String, String>,
333}
334
335#[derive(Debug, Clone)]
336pub struct ManagedInstance {
337    pub instance_id: String,
338    pub activation_id: Option<String>,
339    pub iam_role: String,
340    pub ping_status: String,
341    pub platform_type: String,
342    pub platform_name: String,
343    pub platform_version: String,
344    pub agent_version: String,
345    pub last_ping_date_time: DateTime<Utc>,
346    pub registration_date: DateTime<Utc>,
347    pub resource_type: String,
348    pub computer_name: String,
349    pub ip_address: String,
350    pub is_latest_version: bool,
351    pub association_status: Option<String>,
352    pub source_id: Option<String>,
353    pub source_type: Option<String>,
354}
355
356#[derive(Debug, Clone)]
357pub struct ExecutionPreview {
358    pub execution_preview_id: String,
359    pub document_name: String,
360    pub status: String,
361    pub created_time: DateTime<Utc>,
362}
363
364pub struct SsmState {
365    pub account_id: String,
366    pub region: String,
367    pub parameters: BTreeMap<String, SsmParameter>, // name -> param (BTreeMap for path queries)
368    pub documents: BTreeMap<String, SsmDocument>,
369    pub commands: Vec<SsmCommand>,
370    pub maintenance_windows: HashMap<String, MaintenanceWindow>,
371    pub patch_baselines: HashMap<String, PatchBaseline>,
372    pub patch_groups: Vec<PatchGroup>,
373    pub associations: HashMap<String, SsmAssociation>,
374    pub ops_items: HashMap<String, SsmOpsItem>,
375    pub resource_policies: Vec<SsmResourcePolicy>,
376    pub service_settings: HashMap<String, SsmServiceSetting>,
377    pub default_patch_baseline_id: Option<String>,
378    pub ops_item_counter: u64,
379    pub maintenance_window_executions: Vec<MaintenanceWindowExecution>,
380    pub inventory_entries: HashMap<String, InventoryEntry>, // instance_id -> entry
381    pub inventory_deletions: Vec<InventoryDeletion>,
382    pub compliance_items: Vec<ComplianceItem>,
383    pub resource_data_syncs: HashMap<String, ResourceDataSync>,
384    pub mw_execution_counter: u64,
385    pub inventory_deletion_counter: u64,
386    pub ops_item_related_items: Vec<OpsItemRelatedItem>,
387    pub ops_item_related_item_counter: u64,
388    pub ops_item_events: Vec<OpsItemEvent>,
389    pub ops_metadata: HashMap<String, OpsMetadataEntry>,
390    pub automation_executions: HashMap<String, AutomationExecution>,
391    pub automation_execution_counter: u64,
392    pub sessions: HashMap<String, SsmSession>,
393    pub session_counter: u64,
394    pub activations: HashMap<String, SsmActivation>,
395    pub activation_counter: u64,
396    pub managed_instances: HashMap<String, ManagedInstance>,
397    pub execution_previews: HashMap<String, ExecutionPreview>,
398    pub execution_preview_counter: u64,
399}
400
401impl SsmState {
402    pub fn new(account_id: &str, region: &str) -> Self {
403        let mut state = Self {
404            account_id: account_id.to_string(),
405            region: region.to_string(),
406            parameters: BTreeMap::new(),
407            documents: BTreeMap::new(),
408            commands: Vec::new(),
409            maintenance_windows: HashMap::new(),
410            patch_baselines: HashMap::new(),
411            patch_groups: Vec::new(),
412            associations: HashMap::new(),
413            ops_items: HashMap::new(),
414            resource_policies: Vec::new(),
415            service_settings: HashMap::new(),
416            default_patch_baseline_id: None,
417            ops_item_counter: 0,
418            maintenance_window_executions: Vec::new(),
419            inventory_entries: HashMap::new(),
420            inventory_deletions: Vec::new(),
421            compliance_items: Vec::new(),
422            resource_data_syncs: HashMap::new(),
423            mw_execution_counter: 0,
424            inventory_deletion_counter: 0,
425            ops_item_related_items: Vec::new(),
426            ops_item_related_item_counter: 0,
427            ops_item_events: Vec::new(),
428            ops_metadata: HashMap::new(),
429            automation_executions: HashMap::new(),
430            automation_execution_counter: 0,
431            sessions: HashMap::new(),
432            session_counter: 0,
433            activations: HashMap::new(),
434            activation_counter: 0,
435            managed_instances: HashMap::new(),
436            execution_previews: HashMap::new(),
437            execution_preview_counter: 0,
438        };
439        state.seed_defaults();
440        state
441    }
442
443    pub fn reset(&mut self) {
444        self.parameters.clear();
445        self.documents.clear();
446        self.commands.clear();
447        self.maintenance_windows.clear();
448        self.patch_baselines.clear();
449        self.patch_groups.clear();
450        self.associations.clear();
451        self.ops_items.clear();
452        self.resource_policies.clear();
453        self.service_settings.clear();
454        self.default_patch_baseline_id = None;
455        self.ops_item_counter = 0;
456        self.maintenance_window_executions.clear();
457        self.inventory_entries.clear();
458        self.inventory_deletions.clear();
459        self.compliance_items.clear();
460        self.resource_data_syncs.clear();
461        self.mw_execution_counter = 0;
462        self.inventory_deletion_counter = 0;
463        self.ops_item_related_items.clear();
464        self.ops_item_related_item_counter = 0;
465        self.ops_item_events.clear();
466        self.ops_metadata.clear();
467        self.automation_executions.clear();
468        self.automation_execution_counter = 0;
469        self.sessions.clear();
470        self.session_counter = 0;
471        self.activations.clear();
472        self.activation_counter = 0;
473        self.managed_instances.clear();
474        self.execution_previews.clear();
475        self.execution_preview_counter = 0;
476        self.seed_defaults();
477    }
478
479    fn seed_defaults(&mut self) {
480        let now = chrono::Utc::now();
481
482        // Seed region parameters
483        let regions: &[(&str, &str)] = &[
484            ("af-south-1", "Africa (Cape Town)"),
485            ("ap-east-1", "Asia Pacific (Hong Kong)"),
486            ("ap-northeast-1", "Asia Pacific (Tokyo)"),
487            ("ap-northeast-2", "Asia Pacific (Seoul)"),
488            ("ap-northeast-3", "Asia Pacific (Osaka)"),
489            ("ap-south-1", "Asia Pacific (Mumbai)"),
490            ("ap-south-2", "Asia Pacific (Hyderabad)"),
491            ("ap-southeast-1", "Asia Pacific (Singapore)"),
492            ("ap-southeast-2", "Asia Pacific (Sydney)"),
493            ("ap-southeast-3", "Asia Pacific (Jakarta)"),
494            ("ca-central-1", "Canada (Central)"),
495            ("eu-central-1", "Europe (Frankfurt)"),
496            ("eu-central-2", "Europe (Zurich)"),
497            ("eu-north-1", "Europe (Stockholm)"),
498            ("eu-south-1", "Europe (Milan)"),
499            ("eu-south-2", "Europe (Spain)"),
500            ("eu-west-1", "Europe (Ireland)"),
501            ("eu-west-2", "Europe (London)"),
502            ("eu-west-3", "Europe (Paris)"),
503            ("me-central-1", "Middle East (UAE)"),
504            ("me-south-1", "Middle East (Bahrain)"),
505            ("sa-east-1", "South America (Sao Paulo)"),
506            ("us-east-1", "US East (N. Virginia)"),
507            ("us-east-2", "US East (Ohio)"),
508            ("us-west-1", "US West (N. California)"),
509            ("us-west-2", "US West (Oregon)"),
510        ];
511
512        for (region_code, long_name) in regions {
513            let base_path = format!("/aws/service/global-infrastructure/regions/{region_code}");
514            self.insert_default_param(&base_path, region_code, now);
515            self.insert_default_param(&format!("{base_path}/longName"), long_name, now);
516            self.insert_default_param(&format!("{base_path}/domain"), "amazonaws.com", now);
517            self.insert_default_param(&format!("{base_path}/geolocationRegion"), region_code, now);
518            let country = match region_code.split('-').next().unwrap_or("") {
519                "us" => "US",
520                "eu" => "DE",
521                "ap" => "JP",
522                "sa" => "BR",
523                "ca" => "CA",
524                "me" => "BH",
525                "af" => "ZA",
526                "il" => "IL",
527                _ => "US",
528            };
529            self.insert_default_param(&format!("{base_path}/geolocationCountry"), country, now);
530            self.insert_default_param(&format!("{base_path}/partition"), "aws", now);
531        }
532
533        // Seed service parameters
534        let services = [
535            "acm",
536            "apigateway",
537            "autoscaling",
538            "cloudformation",
539            "cloudfront",
540            "cloudwatch",
541            "codebuild",
542            "codecommit",
543            "codedeploy",
544            "dynamodb",
545            "ec2",
546            "ecr",
547            "ecs",
548            "eks",
549            "elasticache",
550            "elasticbeanstalk",
551            "elasticloadbalancing",
552            "es",
553            "events",
554            "firehose",
555            "iam",
556            "kinesis",
557            "kms",
558            "lambda",
559            "logs",
560            "rds",
561            "redshift",
562            "route53",
563            "s3",
564            "ses",
565            "sns",
566            "sqs",
567            "ssm",
568            "sts",
569        ];
570        for svc in &services {
571            let name = format!("/aws/service/global-infrastructure/services/{svc}");
572            self.insert_default_param(&name, svc, now);
573        }
574
575        // Seed AMI parameters (10 entries per region)
576        let ami_names = [
577            "al2023-ami-kernel-default-x86_64",
578            "al2023-ami-kernel-default-arm64",
579            "al2023-ami-minimal-kernel-default-x86_64",
580            "al2023-ami-minimal-kernel-default-arm64",
581            "amzn2-ami-hvm-x86_64-gp2",
582            "amzn2-ami-hvm-arm64-gp2",
583            "amzn2-ami-kernel-5.10-hvm-x86_64-gp2",
584            "amzn2-ami-kernel-5.10-hvm-arm64-gp2",
585            "amzn2-ami-minimal-hvm-x86_64-ebs",
586            "amzn2-ami-minimal-hvm-arm64-ebs",
587        ];
588
589        // Generate region-specific AMI IDs using a simple hash
590        for (i, ami_name) in ami_names.iter().enumerate() {
591            let name = format!("/aws/service/ami-amazon-linux-latest/{ami_name}");
592            let ami_id = format!(
593                "ami-{:017x}",
594                // Simple region-specific hash
595                {
596                    let mut h: u64 = 0xcbf29ce484222325;
597                    for b in self.region.as_bytes() {
598                        h ^= *b as u64;
599                        h = h.wrapping_mul(0x100000001b3);
600                    }
601                    for b in ami_name.as_bytes() {
602                        h ^= *b as u64;
603                        h = h.wrapping_mul(0x100000001b3);
604                    }
605                    h.wrapping_add(i as u64)
606                }
607            );
608            self.insert_default_param(&name, &ami_id, now);
609        }
610    }
611
612    fn insert_default_param(&mut self, name: &str, value: &str, now: DateTime<Utc>) {
613        let arn = if name.starts_with('/') {
614            format!(
615                "arn:aws:ssm:{}:{}:parameter{}",
616                self.region, self.account_id, name
617            )
618        } else {
619            format!(
620                "arn:aws:ssm:{}:{}:parameter/{}",
621                self.region, self.account_id, name
622            )
623        };
624        self.parameters.insert(
625            name.to_string(),
626            SsmParameter {
627                name: name.to_string(),
628                value: value.to_string(),
629                param_type: "String".to_string(),
630                version: 1,
631                arn,
632                last_modified: now,
633                history: Vec::new(),
634                tags: HashMap::new(),
635                labels: HashMap::new(),
636                description: None,
637                allowed_pattern: None,
638                key_id: None,
639                data_type: "text".to_string(),
640                tier: "Standard".to_string(),
641                policies: None,
642            },
643        );
644    }
645}
646
647#[derive(Debug, Clone)]
648pub struct MaintenanceWindowExecution {
649    pub window_execution_id: String,
650    pub window_id: String,
651    pub status: String,
652    pub start_time: DateTime<Utc>,
653    pub end_time: Option<DateTime<Utc>>,
654    pub tasks: Vec<MaintenanceWindowExecutionTask>,
655}
656
657#[derive(Debug, Clone)]
658pub struct MaintenanceWindowExecutionTask {
659    pub task_execution_id: String,
660    pub window_execution_id: String,
661    pub task_arn: String,
662    pub task_type: String,
663    pub status: String,
664    pub start_time: DateTime<Utc>,
665    pub end_time: Option<DateTime<Utc>>,
666    pub invocations: Vec<MaintenanceWindowExecutionTaskInvocation>,
667}
668
669#[derive(Debug, Clone)]
670pub struct MaintenanceWindowExecutionTaskInvocation {
671    pub invocation_id: String,
672    pub task_execution_id: String,
673    pub window_execution_id: String,
674    pub execution_id: Option<String>,
675    pub status: String,
676    pub start_time: DateTime<Utc>,
677    pub end_time: Option<DateTime<Utc>>,
678    pub parameters: Option<String>,
679    pub owner_information: Option<String>,
680    pub window_target_id: Option<String>,
681    pub status_details: Option<String>,
682}
683
684#[derive(Debug, Clone)]
685pub struct InventoryItem {
686    pub type_name: String,
687    pub schema_version: String,
688    pub capture_time: String,
689    pub content: Vec<HashMap<String, String>>,
690    pub content_hash: Option<String>,
691    pub context: Option<HashMap<String, String>>,
692}
693
694#[derive(Debug, Clone)]
695pub struct InventoryEntry {
696    pub instance_id: String,
697    pub items: Vec<InventoryItem>,
698}
699
700#[derive(Debug, Clone)]
701pub struct InventoryDeletion {
702    pub deletion_id: String,
703    pub type_name: String,
704    pub deletion_start_time: DateTime<Utc>,
705    pub last_status: String,
706    pub last_status_message: String,
707    pub deletion_summary: serde_json::Value,
708    pub last_status_update_time: DateTime<Utc>,
709}
710
711#[derive(Debug, Clone)]
712pub struct ComplianceItem {
713    pub resource_id: String,
714    pub resource_type: String,
715    pub compliance_type: String,
716    pub severity: String,
717    pub status: String,
718    pub title: Option<String>,
719    pub id: Option<String>,
720    pub details: HashMap<String, String>,
721    pub execution_summary: serde_json::Value,
722}
723
724#[derive(Debug, Clone)]
725pub struct ResourceDataSync {
726    pub sync_name: String,
727    pub sync_type: Option<String>,
728    pub sync_source: Option<serde_json::Value>,
729    pub s3_destination: Option<serde_json::Value>,
730    pub created_date: DateTime<Utc>,
731    pub last_sync_time: Option<DateTime<Utc>>,
732    pub last_successful_sync_time: Option<DateTime<Utc>>,
733    pub last_status: String,
734    pub sync_last_modified_time: DateTime<Utc>,
735}
736
737pub type SharedSsmState = Arc<RwLock<SsmState>>;