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