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