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}