alien_core/import/request.rs
1use crate::{ManagementConfig, Platform, ResourceType, StackSettings, StackState};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5/// Oldest setup import payload format this binary can read.
6pub const MIN_SUPPORTED_SETUP_IMPORT_FORMAT_VERSION: u32 = 1;
7
8/// Setup import payload format this binary writes.
9pub const CURRENT_SETUP_IMPORT_FORMAT_VERSION: u32 = 1;
10
11/// Managed Aurora credentials require readers that understand the JSON secret binding.
12pub const MANAGED_POSTGRES_SETUP_IMPORT_FORMAT_VERSION: u32 = 3;
13
14/// Latest setup payload this binary can read. GCP federation packages require v2.
15pub const MAX_SUPPORTED_SETUP_IMPORT_FORMAT_VERSION: u32 =
16 MANAGED_POSTGRES_SETUP_IMPORT_FORMAT_VERSION;
17
18pub fn setup_import_format_version_for_platform(platform: Platform) -> u32 {
19 if platform == Platform::Gcp {
20 2
21 } else {
22 CURRENT_SETUP_IMPORT_FORMAT_VERSION
23 }
24}
25
26/// Package source that produced an import request. Observability label
27/// only — the manager does not branch on this value, and any new deployment
28/// pathway can omit it without affecting import behavior.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
30#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
31#[serde(rename_all = "lowercase")]
32pub enum ImportSourceKind {
33 /// CloudFormation Custom Resource or Stack Outputs.
34 CloudFormation,
35 /// Terraform provider resource.
36 Terraform,
37 /// Helm chart local-import bootstrap path.
38 Helm,
39}
40
41/// Request body for manager-side stack import.
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
44#[serde(rename_all = "camelCase")]
45pub struct StackImportRequest {
46 /// Wire-format version for the setup import payload.
47 pub setup_import_format_version: u32,
48 /// Deployment-group token authorizing the import.
49 pub deployment_group_token: String,
50 /// User-chosen deployment name. Must be unique within the deployment
51 /// group; the manager returns 409 on collision rather than silently
52 /// resolving to an existing deployment. Each setup adapter picks
53 /// the natural source: CloudFormation defaults to the CFN stack name,
54 /// Helm to `{namespace}/{release}`, Terraform requires an explicit
55 /// `name` attribute on the `alien_deployment` resource.
56 pub deployment_name: String,
57 /// Stable physical-name prefix used by the setup package for generated
58 /// resources. Runtime controllers use it when addressing imported
59 /// resources.
60 pub resource_prefix: String,
61 /// Optional source label for observability. Does not affect import
62 /// behavior — the manager dispatches the same `ImporterRegistry`
63 /// regardless of which setup package emitted the payload.
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub source_kind: Option<ImportSourceKind>,
66 /// Setup source metadata needed by the control plane to guide privileged
67 /// teardown. The manager treats this as opaque JSON.
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub setup_metadata: Option<serde_json::Value>,
70 /// Optional release id that produced the setup package. When
71 /// omitted, the manager imports against the latest release.
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub release_id: Option<String>,
74 /// Platform being imported.
75 pub platform: Platform,
76 /// Optional base cloud platform for Kubernetes setup targets such as
77 /// EKS/GKE/AKS. The runtime platform remains Kubernetes.
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub base_platform: Option<Platform>,
80 /// Region or location reported by the setup artifact.
81 pub region: String,
82 /// Setup target this package was generated for.
83 pub setup_target: String,
84 /// Setup compatibility fingerprint embedded in the package.
85 pub setup_fingerprint: String,
86 /// Setup fingerprint algorithm version embedded in the package.
87 pub setup_fingerprint_version: u32,
88 /// Resolved stack settings supplied by the setup artifact.
89 pub stack_settings: StackSettings,
90 /// Platform-derived management configuration, when this setup creates a
91 /// cross-account/cross-tenant management identity.
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub management_config: Option<ManagementConfig>,
94 /// Deployer-provided stack input values collected by generated setup
95 /// surfaces. Platform-backed managers resolve these into runtime
96 /// environment variables before deployment creation; standalone managers
97 /// accept the field for setup package compatibility.
98 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
99 pub input_values: HashMap<String, serde_json::Value>,
100 /// Imported resources with typed per-resource payloads.
101 pub resources: Vec<ImportedResource>,
102}
103
104/// One resolved resource import payload.
105#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
107#[serde(rename_all = "camelCase")]
108pub struct ImportedResource {
109 /// Resource id from the active stack.
110 pub id: String,
111 /// Resource type from the active stack.
112 #[serde(rename = "type")]
113 pub resource_type: ResourceType,
114 /// Resolved typed payload for this resource.
115 #[cfg_attr(feature = "openapi", schema(value_type = Object))]
116 pub import_data: serde_json::Value,
117}
118
119/// Response body returned after a stack import.
120#[derive(Debug, Clone, Serialize, Deserialize)]
121#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
122#[serde(rename_all = "camelCase")]
123pub struct StackImportResponse {
124 /// Deployment created.
125 pub deployment_id: String,
126 /// Deployment bearer token for the imported deployment, when available.
127 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub deployment_token: Option<String>,
129 /// Stack settings persisted for the deployment.
130 pub stack_settings: StackSettings,
131 /// Fully populated imported stack state.
132 pub stack_state: StackState,
133}
134
135#[cfg(test)]
136mod tests {
137 use super::ImportSourceKind;
138
139 #[test]
140 fn import_source_kind_serializes_cloudformation_without_separator() {
141 let value = serde_json::to_value(ImportSourceKind::CloudFormation).unwrap();
142 assert_eq!(value, "cloudformation");
143
144 let source: ImportSourceKind = serde_json::from_value(value).unwrap();
145 assert_eq!(source, ImportSourceKind::CloudFormation);
146 }
147}