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