1use serde::{Deserialize, Deserializer};
4
5pub mod aws;
6pub mod azure;
7pub mod gcp;
8pub mod kubernetes_cluster;
9
10pub use aws::{
11 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 AzureArtifactRegistryImportData, AzureBuildImportData, AzureComputeClusterImportData,
19 AzureContainerAppsEnvironmentImportData, AzureFlexibleServerPostgresImportData,
20 AzureKvImportData, AzureNetworkImportData, AzureQueueImportData,
21 AzureRemoteStackManagementImportData, AzureResourceGroupImportData,
22 AzureServiceAccountImportData, AzureServiceActivationImportData,
23 AzureServiceBusNamespaceImportData, AzureStorageAccountImportData, AzureStorageImportData,
24 AzureVaultImportData, AzureWorkerImportData,
25};
26pub use gcp::{
27 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 (
66 "aws_artifact_registry",
67 schema::<AwsArtifactRegistryImportData>(),
68 ),
69 ("aws_build", schema::<AwsBuildImportData>()),
70 (
71 "aws_compute_cluster",
72 schema::<AwsComputeClusterImportData>(),
73 ),
74 ("aws_email", schema::<AwsEmailImportData>()),
75 ("aws_function", schema::<AwsWorkerImportData>()),
76 ("aws_kv", schema::<AwsKvImportData>()),
77 ("aws_network", schema::<AwsNetworkImportData>()),
78 ("aws_open_search", schema::<AwsOpenSearchImportData>()),
79 ("aws_postgres", schema::<AwsPostgresImportData>()),
80 ("aws_queue", schema::<AwsQueueImportData>()),
81 (
82 "aws_remote_stack_management",
83 schema::<AwsRemoteStackManagementImportData>(),
84 ),
85 (
86 "aws_service_account",
87 schema::<AwsServiceAccountImportData>(),
88 ),
89 ("aws_storage", schema::<AwsStorageImportData>()),
90 ("aws_vault", schema::<AwsVaultImportData>()),
91 (
92 "azure_artifact_registry",
93 schema::<AzureArtifactRegistryImportData>(),
94 ),
95 ("azure_build", schema::<AzureBuildImportData>()),
96 (
97 "azure_container_apps_environment",
98 schema::<AzureContainerAppsEnvironmentImportData>(),
99 ),
100 (
101 "azure_compute_cluster",
102 schema::<AzureComputeClusterImportData>(),
103 ),
104 ("azure_function", schema::<AzureWorkerImportData>()),
105 ("azure_kv", schema::<AzureKvImportData>()),
106 ("azure_network", schema::<AzureNetworkImportData>()),
107 (
108 "azure_postgres",
109 schema::<AzureFlexibleServerPostgresImportData>(),
110 ),
111 ("azure_queue", schema::<AzureQueueImportData>()),
112 (
113 "azure_remote_stack_management",
114 schema::<AzureRemoteStackManagementImportData>(),
115 ),
116 (
117 "azure_resource_group",
118 schema::<AzureResourceGroupImportData>(),
119 ),
120 (
121 "azure_service_account",
122 schema::<AzureServiceAccountImportData>(),
123 ),
124 (
125 "azure_service_activation",
126 schema::<AzureServiceActivationImportData>(),
127 ),
128 (
129 "azure_service_bus_namespace",
130 schema::<AzureServiceBusNamespaceImportData>(),
131 ),
132 ("azure_storage", schema::<AzureStorageImportData>()),
133 (
134 "azure_storage_account",
135 schema::<AzureStorageAccountImportData>(),
136 ),
137 ("azure_vault", schema::<AzureVaultImportData>()),
138 (
139 "gcp_artifact_registry",
140 schema::<GcpArtifactRegistryImportData>(),
141 ),
142 ("gcp_build", schema::<GcpBuildImportData>()),
143 (
144 "gcp_compute_cluster",
145 schema::<GcpComputeClusterImportData>(),
146 ),
147 ("gcp_function", schema::<GcpWorkerImportData>()),
148 ("gcp_kv", schema::<GcpKvImportData>()),
149 ("gcp_network", schema::<GcpNetworkImportData>()),
150 ("gcp_postgres", schema::<GcpPostgresImportData>()),
151 ("gcp_queue", schema::<GcpQueueImportData>()),
152 (
153 "gcp_remote_stack_management",
154 schema::<GcpRemoteStackManagementImportData>(),
155 ),
156 (
157 "kubernetes_cluster",
158 schema::<KubernetesClusterImportData>(),
159 ),
160 (
161 "gcp_service_account",
162 schema::<GcpServiceAccountImportData>(),
163 ),
164 (
165 "gcp_service_activation",
166 schema::<GcpServiceActivationImportData>(),
167 ),
168 ("gcp_storage", schema::<GcpStorageImportData>()),
169 ("gcp_vault", schema::<GcpVaultImportData>()),
170 ]);
171
172 insta::assert_json_snapshot!("import_data_schemas", schemas);
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use serde_json::json;
180
181 #[test]
182 fn aws_import_data_accepts_cloudformation_string_booleans() {
183 let network: AwsNetworkImportData = serde_json::from_value(json!({
184 "vpcId": "vpc-123",
185 "cidrBlock": null,
186 "internetGatewayId": null,
187 "natGatewayId": null,
188 "eipAllocationId": null,
189 "publicSubnetIds": ["subnet-public"],
190 "privateSubnetIds": ["subnet-private"],
191 "publicRouteTableId": null,
192 "privateRouteTableId": null,
193 "securityGroupId": "sg-123",
194 "availabilityZones": [],
195 "isByoVpc": "true",
196 }))
197 .expect("network import data should parse");
198 assert!(network.is_byo_vpc);
199
200 let remote_stack_management: AwsRemoteStackManagementImportData =
201 serde_json::from_value(json!({
202 "roleName": "alien-manager",
203 "roleArn": "arn:aws:iam::123456789012:role/alien-manager",
204 "managementPermissionsApplied": "true",
205 }))
206 .expect("remote stack management import data should parse");
207 assert!(remote_stack_management.management_permissions_applied);
208
209 let service_account: AwsServiceAccountImportData = serde_json::from_value(json!({
210 "roleName": "alien-worker",
211 "roleArn": "arn:aws:iam::123456789012:role/alien-worker",
212 "stackPermissionsApplied": "false",
213 }))
214 .expect("service account import data should parse");
215 assert!(!service_account.stack_permissions_applied);
216 }
217}