Skip to main content

data_source/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::{HashMap, HashSet};
3
4#[derive(Debug, Default, Serialize, Deserialize)]
5pub struct KnownResourceTypes {
6    pub known_resource_types: Vec<String>,
7}
8
9/// Resource type → valid GetAtt attribute names and their return types.
10#[derive(Debug, Default, Serialize, Deserialize)]
11pub struct GetattData {
12    pub getatt_attributes: HashMap<String, Vec<String>>,
13    pub getatt_attribute_types: HashMap<String, HashMap<String, String>>,
14}
15
16#[derive(Debug, Default, Serialize, Deserialize)]
17pub struct StatefulResourceTypes {
18    pub stateful_resource_types: HashSet<String>,
19}
20
21#[derive(Debug, Default, Serialize, Deserialize)]
22pub struct RetentionPeriodRequirements {
23    pub retention_period_requirements: HashMap<String, Vec<String>>,
24}
25
26#[derive(Debug, Default, Serialize, Deserialize)]
27pub struct PrimaryIdentifiers {
28    pub primary_identifiers: HashMap<String, Vec<String>>,
29}
30
31#[derive(Debug, Default, Serialize, Deserialize)]
32pub struct IamActionResourcePatterns {
33    pub iam_action_resource_patterns: HashMap<String, Vec<String>>,
34}
35
36#[derive(Debug, Default, Serialize, Deserialize)]
37pub struct CodepipelineArtifactCounts {
38    pub codepipeline_action_artifact_counts: HashMap<String, ArtifactCountEntry>,
39}
40
41#[derive(Debug, Default, Clone, Serialize, Deserialize)]
42pub struct ArtifactCountEntry {
43    pub min_input: usize,
44    pub max_input: usize,
45    pub min_output: usize,
46    pub max_output: usize,
47}
48
49#[derive(Debug, Default, Serialize, Deserialize)]
50pub struct DeprecatedResourceTypes {
51    pub deprecated_resource_types: Vec<String>,
52}
53
54#[derive(Debug, Default, Serialize, Deserialize)]
55pub struct SensitivePorts {
56    pub sensitive_ports: Vec<u16>,
57}
58
59#[derive(Debug, Default, Serialize, Deserialize)]
60pub struct SecretsManagerArnFields {
61    pub secretsmanager_arn_fields: Vec<String>,
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn required_document_fields_must_be_present() {
70        assert!(serde_json::from_str::<KnownResourceTypes>("{}").is_err());
71        assert!(serde_json::from_str::<GetattData>("{}").is_err());
72        assert!(serde_json::from_str::<StatefulResourceTypes>("{}").is_err());
73        assert!(serde_json::from_str::<RetentionPeriodRequirements>("{}").is_err());
74        assert!(serde_json::from_str::<PrimaryIdentifiers>("{}").is_err());
75        assert!(serde_json::from_str::<IamActionResourcePatterns>("{}").is_err());
76        assert!(serde_json::from_str::<CodepipelineArtifactCounts>("{}").is_err());
77        assert!(serde_json::from_str::<DeprecatedResourceTypes>("{}").is_err());
78        assert!(serde_json::from_str::<SensitivePorts>("{}").is_err());
79        assert!(serde_json::from_str::<SecretsManagerArnFields>("{}").is_err());
80    }
81
82    #[test]
83    fn postcard_roundtrip_known_resource_types() {
84        let original =
85            KnownResourceTypes { known_resource_types: vec!["AWS::S3::Bucket".into(), "AWS::EC2::Instance".into()] };
86        let bytes = postcard::to_allocvec(&original).unwrap();
87        let restored: KnownResourceTypes = postcard::from_bytes(&bytes).unwrap();
88        assert_eq!(restored.known_resource_types.len(), 2);
89        assert!(restored.known_resource_types.contains(&"AWS::S3::Bucket".to_string()));
90    }
91
92    #[test]
93    fn postcard_roundtrip_getatt_data() {
94        let mut original = GetattData::default();
95        original.getatt_attributes.insert("AWS::S3::Bucket".into(), vec!["Arn".into(), "DomainName".into()]);
96        original
97            .getatt_attribute_types
98            .insert("AWS::EC2::CapacityReservation".into(), [("InstanceCount".into(), "integer".into())].into());
99        let bytes = postcard::to_allocvec(&original).unwrap();
100        let restored: GetattData = postcard::from_bytes(&bytes).unwrap();
101        assert_eq!(restored.getatt_attributes["AWS::S3::Bucket"].len(), 2);
102        assert_eq!(restored.getatt_attribute_types["AWS::EC2::CapacityReservation"]["InstanceCount"], "integer");
103    }
104
105    #[test]
106    fn postcard_roundtrip_stateful_resource_types() {
107        let original = StatefulResourceTypes {
108            stateful_resource_types: ["AWS::SQS::Queue".into(), "AWS::DynamoDB::Table".into()].into(),
109        };
110        let bytes = postcard::to_allocvec(&original).unwrap();
111        let restored: StatefulResourceTypes = postcard::from_bytes(&bytes).unwrap();
112        assert!(restored.stateful_resource_types.contains("AWS::SQS::Queue"));
113    }
114
115    #[test]
116    fn postcard_roundtrip_retention_period_requirements() {
117        let original = RetentionPeriodRequirements {
118            retention_period_requirements: [("AWS::SQS::Queue".into(), vec!["MessageRetentionPeriod".into()])].into(),
119        };
120        let bytes = postcard::to_allocvec(&original).unwrap();
121        let restored: RetentionPeriodRequirements = postcard::from_bytes(&bytes).unwrap();
122        assert_eq!(restored.retention_period_requirements["AWS::SQS::Queue"], vec!["MessageRetentionPeriod"]);
123    }
124}