Skip to main content

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}