1use serde::{Deserialize, Deserializer};
4
5pub mod aws;
6pub mod azure;
7pub mod gcp;
8pub mod kubernetes_cluster;
9
10pub use aws::{
11 AwsAiImportData, AwsArtifactRegistryImportData, AwsBuildImportData, AwsComputeClusterImportData,
12 AwsEmailDkimTokenImportData, AwsEmailDomainImportData, AwsEmailImportData, AwsKvImportData,
13 AwsNetworkImportData, AwsOpenSearchImportData, AwsPostgresImportData, AwsQueueImportData,
14 AwsRemoteStackManagementImportData, AwsServiceAccountImportData, AwsStorageImportData,
15 AwsVaultImportData, AwsWorkerImportData,
16};
17pub use azure::{
18 AzureAiImportData, AzureArtifactRegistryImportData, AzureBuildImportData,
19 AzureComputeClusterImportData, AzureContainerAppsEnvironmentImportData,
20 AzureFlexibleServerPostgresImportData, AzureKvImportData, AzureNetworkImportData,
21 AzureQueueImportData, AzureRemoteStackManagementImportData, AzureResourceGroupImportData,
22 AzureServiceAccountImportData, AzureServiceActivationImportData,
23 AzureServiceBusNamespaceImportData, AzureStorageAccountImportData, AzureStorageImportData,
24 AzureVaultImportData, AzureWorkerImportData,
25};
26pub use gcp::{
27 GcpAiImportData, GcpArtifactRegistryImportData, GcpBuildImportData, GcpComputeClusterImportData,
28 GcpKvImportData, GcpNetworkImportData, GcpPostgresImportData, GcpQueueImportData,
29 GcpRemoteStackManagementImportData, GcpServiceAccountImportData,
30 GcpServiceActivationImportData, GcpStorageImportData, GcpVaultImportData, GcpWorkerImportData,
31};
32pub use kubernetes_cluster::{
33 AzureApplicationGatewayForContainersBootstrap, KubernetesClusterImportData,
34};
35
36pub(crate) fn deserialize_bool_from_bool_or_string<'de, D>(
37 deserializer: D,
38) -> Result<bool, D::Error>
39where
40 D: Deserializer<'de>,
41{
42 let value = serde_json::Value::deserialize(deserializer)?;
43 match value {
44 serde_json::Value::Bool(value) => Ok(value),
45 serde_json::Value::String(value) if value.eq_ignore_ascii_case("true") => Ok(true),
46 serde_json::Value::String(value) if value.eq_ignore_ascii_case("false") => Ok(false),
47 other => Err(serde::de::Error::custom(format!(
48 "expected boolean or boolean string, got {other}"
49 ))),
50 }
51}
52
53#[cfg(all(test, feature = "jsonschema"))]
54mod schema_snapshots {
55 use super::*;
56 use indexmap::IndexMap;
57
58 fn schema<T: schemars::JsonSchema>() -> serde_json::Value {
59 serde_json::to_value(schemars::schema_for!(T)).expect("schema should serialize")
60 }
61
62 #[test]
63 fn import_data_schema_snapshot() {
64 let schemas = IndexMap::from([
65 ("aws_ai", schema::<AwsAiImportData>()),
66 (
67 "aws_artifact_registry",
68 schema::<AwsArtifactRegistryImportData>(),
69 ),
70 ("aws_build", schema::<AwsBuildImportData>()),
71 (
72 "aws_compute_cluster",
73 schema::<AwsComputeClusterImportData>(),
74 ),
75 ("aws_email", schema::<AwsEmailImportData>()),
76 ("aws_function", schema::<AwsWorkerImportData>()),
77 ("aws_kv", schema::<AwsKvImportData>()),
78 ("aws_network", schema::<AwsNetworkImportData>()),
79 ("aws_open_search", schema::<AwsOpenSearchImportData>()),
80 ("aws_postgres", schema::<AwsPostgresImportData>()),
81 ("aws_queue", schema::<AwsQueueImportData>()),
82 (
83 "aws_remote_stack_management",
84 schema::<AwsRemoteStackManagementImportData>(),
85 ),
86 (
87 "aws_service_account",
88 schema::<AwsServiceAccountImportData>(),
89 ),
90 ("aws_storage", schema::<AwsStorageImportData>()),
91 ("aws_vault", schema::<AwsVaultImportData>()),
92 ("azure_ai", schema::<AzureAiImportData>()),
93 (
94 "azure_artifact_registry",
95 schema::<AzureArtifactRegistryImportData>(),
96 ),
97 ("azure_build", schema::<AzureBuildImportData>()),
98 (
99 "azure_container_apps_environment",
100 schema::<AzureContainerAppsEnvironmentImportData>(),
101 ),
102 (
103 "azure_compute_cluster",
104 schema::<AzureComputeClusterImportData>(),
105 ),
106 ("azure_function", schema::<AzureWorkerImportData>()),
107 ("azure_kv", schema::<AzureKvImportData>()),
108 ("azure_network", schema::<AzureNetworkImportData>()),
109 (
110 "azure_postgres",
111 schema::<AzureFlexibleServerPostgresImportData>(),
112 ),
113 ("azure_queue", schema::<AzureQueueImportData>()),
114 (
115 "azure_remote_stack_management",
116 schema::<AzureRemoteStackManagementImportData>(),
117 ),
118 (
119 "azure_resource_group",
120 schema::<AzureResourceGroupImportData>(),
121 ),
122 (
123 "azure_service_account",
124 schema::<AzureServiceAccountImportData>(),
125 ),
126 (
127 "azure_service_activation",
128 schema::<AzureServiceActivationImportData>(),
129 ),
130 (
131 "azure_service_bus_namespace",
132 schema::<AzureServiceBusNamespaceImportData>(),
133 ),
134 ("azure_storage", schema::<AzureStorageImportData>()),
135 (
136 "azure_storage_account",
137 schema::<AzureStorageAccountImportData>(),
138 ),
139 ("azure_vault", schema::<AzureVaultImportData>()),
140 ("gcp_ai", schema::<GcpAiImportData>()),
141 (
142 "gcp_artifact_registry",
143 schema::<GcpArtifactRegistryImportData>(),
144 ),
145 ("gcp_build", schema::<GcpBuildImportData>()),
146 (
147 "gcp_compute_cluster",
148 schema::<GcpComputeClusterImportData>(),
149 ),
150 ("gcp_function", schema::<GcpWorkerImportData>()),
151 ("gcp_kv", schema::<GcpKvImportData>()),
152 ("gcp_network", schema::<GcpNetworkImportData>()),
153 ("gcp_postgres", schema::<GcpPostgresImportData>()),
154 ("gcp_queue", schema::<GcpQueueImportData>()),
155 (
156 "gcp_remote_stack_management",
157 schema::<GcpRemoteStackManagementImportData>(),
158 ),
159 (
160 "kubernetes_cluster",
161 schema::<KubernetesClusterImportData>(),
162 ),
163 (
164 "gcp_service_account",
165 schema::<GcpServiceAccountImportData>(),
166 ),
167 (
168 "gcp_service_activation",
169 schema::<GcpServiceActivationImportData>(),
170 ),
171 ("gcp_storage", schema::<GcpStorageImportData>()),
172 ("gcp_vault", schema::<GcpVaultImportData>()),
173 ]);
174
175 insta::assert_json_snapshot!("import_data_schemas", schemas);
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182 use serde_json::json;
183
184 #[test]
185 fn aws_import_data_accepts_cloudformation_string_booleans() {
186 let network: AwsNetworkImportData = serde_json::from_value(json!({
187 "vpcId": "vpc-123",
188 "cidrBlock": null,
189 "internetGatewayId": null,
190 "natGatewayId": null,
191 "eipAllocationId": null,
192 "publicSubnetIds": ["subnet-public"],
193 "privateSubnetIds": ["subnet-private"],
194 "publicRouteTableId": null,
195 "privateRouteTableId": null,
196 "securityGroupId": "sg-123",
197 "availabilityZones": [],
198 "isByoVpc": "true",
199 }))
200 .expect("network import data should parse");
201 assert!(network.is_byo_vpc);
202
203 let remote_stack_management: AwsRemoteStackManagementImportData =
204 serde_json::from_value(json!({
205 "roleName": "alien-manager",
206 "roleArn": "arn:aws:iam::123456789012:role/alien-manager",
207 "managementPermissionsApplied": "true",
208 }))
209 .expect("remote stack management import data should parse");
210 assert!(remote_stack_management.management_permissions_applied);
211
212 let service_account: AwsServiceAccountImportData = serde_json::from_value(json!({
213 "roleName": "alien-worker",
214 "roleArn": "arn:aws:iam::123456789012:role/alien-worker",
215 "stackPermissionsApplied": "false",
216 }))
217 .expect("service account import data should parse");
218 assert!(!service_account.stack_permissions_applied);
219 }
220}