alien_core/
network_ids.rs1use serde::{Deserialize, Deserializer};
7
8pub fn deserialize_ids<'de, D: Deserializer<'de>>(
10 deserializer: D,
11) -> Result<Vec<String>, D::Error> {
12 let ids = Vec::<String>::deserialize(deserializer)?;
13 Ok(ids
14 .into_iter()
15 .map(|id| id.trim().to_string())
16 .filter(|id| !id.is_empty())
17 .collect())
18}
19
20pub fn deserialize_ids_or_csv<'de, D: Deserializer<'de>>(
23 deserializer: D,
24) -> Result<Vec<String>, D::Error> {
25 #[derive(Deserialize)]
26 #[serde(untagged)]
27 enum Input {
28 List(Vec<String>),
29 Csv(String),
30 }
31 let values = match Input::deserialize(deserializer)? {
32 Input::List(values) => values,
33 Input::Csv(value) => value.split(',').map(str::to_string).collect(),
34 };
35 Ok(values
36 .into_iter()
37 .map(|value| value.trim().to_string())
38 .filter(|value| !value.is_empty())
39 .collect())
40}
41
42pub fn deserialize_optional_id<'de, D: Deserializer<'de>>(
44 deserializer: D,
45) -> Result<Option<String>, D::Error> {
46 let id = Option::<String>::deserialize(deserializer)?;
47 Ok(id
48 .map(|id| id.trim().to_string())
49 .filter(|id| !id.is_empty()))
50}
51
52#[cfg(test)]
53mod tests {
54 use crate::{import::data::AwsNetworkImportData, NetworkSettings};
55 use serde_json::json;
56
57 #[test]
58 fn setup_network_settings_normalize_all_aws_id_lists_and_round_trip() {
59 for (ids, expected) in [
60 (json!([]), json!([])),
61 (json!([""]), json!([])),
62 (json!([" "]), json!([])),
63 (json!(["", " id-a ", "id-b", ""]), json!(["id-a", "id-b"])),
64 ] {
65 let value = json!({"type": "byo-vpc-aws", "vpc_id": "vpc-test", "public_subnet_ids": ids, "private_subnet_ids": ids, "security_group_ids": ids});
66 let parsed: NetworkSettings = serde_json::from_value(value).unwrap();
67 let serialized = serde_json::to_value(&parsed).unwrap();
68 for key in [
69 "public_subnet_ids",
70 "private_subnet_ids",
71 "security_group_ids",
72 ] {
73 assert_eq!(serialized[key], expected);
74 }
75 assert_eq!(
76 serde_json::from_value::<NetworkSettings>(serialized).unwrap(),
77 parsed
78 );
79 }
80 }
81
82 #[test]
83 fn network_import_normalizes_flat_and_zonal_ids_and_optional_security_group() {
84 for group in [json!(null), json!(""), json!(" "), json!(" sg-real ")] {
85 let data: AwsNetworkImportData = serde_json::from_value(json!({
86 "vpcId": "vpc-test", "publicSubnetIds": ["", " "],
87 "privateSubnetIds": ["", " subnet-private "], "securityGroupId": group,
88 "availabilityZones": [], "isByoVpc": "true",
89 "subnetsByFailureDomain": {"us-east-1a": {"publicSubnetIds": [""], "privateSubnetIds": [" subnet-private ", ""]}}
90 })).unwrap();
91 assert!(data.public_subnet_ids.is_empty());
92 assert_eq!(data.private_subnet_ids, ["subnet-private"]);
93 assert_eq!(
94 data.security_group_id.as_deref(),
95 if group == " sg-real " {
96 Some("sg-real")
97 } else {
98 None
99 }
100 );
101 assert!(data.subnets_by_failure_domain["us-east-1a"]
102 .public_subnet_ids
103 .is_empty());
104 assert_eq!(
105 data.subnets_by_failure_domain["us-east-1a"].private_subnet_ids,
106 ["subnet-private"]
107 );
108 }
109 }
110}