alien_core/deployment/config.rs
1//! Deployment configuration and OTLP observability settings.
2
3use crate::{ExternalBindings, ManagementConfig, StackSettings};
4use bon::Builder;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8use super::{is_false, ComputeBackend, DomainMetadata, EnvironmentVariablesSnapshot};
9
10/// Deployment configuration
11///
12/// Configuration for how to perform the deployment.
13/// Note: Credentials (ClientConfig) are passed separately to step() function.
14#[derive(Debug, Clone, Serialize, Deserialize, Builder)]
15#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
16#[serde(rename_all = "camelCase")]
17pub struct DeploymentConfig {
18 /// Human-readable deployment name for cloud console metadata.
19 ///
20 /// This is separate from the physical resource prefix in StackState. It is
21 /// used only for display text such as IAM role descriptions, service
22 /// account descriptions, and custom role titles.
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub deployment_name: Option<String>,
25 /// User-customizable deployment settings (network, deployment model, approvals).
26 /// Provided by customer via CloudFormation, Terraform, CLI, or Helm.
27 #[serde(default)]
28 pub stack_settings: StackSettings,
29 /// Platform service account/role that will manage the infrastructure remotely.
30 /// Derived from Manager's ServiceAccount, not user-specified.
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub management_config: Option<ManagementConfig>,
33 /// Environment variables snapshot
34 pub environment_variables: EnvironmentVariablesSnapshot,
35 /// Allow frozen resource changes during updates
36 /// When true, skips the frozen resources compatibility check.
37 /// This requires running with elevated cloud credentials.
38 #[serde(default, skip_serializing_if = "is_false")]
39 pub allow_frozen_changes: bool,
40 /// Compute backend for Container and Worker resources.
41 /// When None, the platform default is used for cloud platforms.
42 /// Contains cluster IDs and management tokens for container orchestration.
43 /// Worker runtime credentials are provided through cloud identity and vault-backed secrets.
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub compute_backend: Option<ComputeBackend>,
46 /// External bindings for pre-existing services.
47 /// Required for Kubernetes platform (all infrastructure resources).
48 /// Optional for cloud platforms (override specific resources).
49 #[serde(default)]
50 pub external_bindings: ExternalBindings,
51 /// Cloud platform that owns imported base infrastructure for a Kubernetes
52 /// runtime deployment.
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 pub base_platform: Option<crate::Platform>,
55 /// Public URLs for exposed resources (optional override).
56 ///
57 /// Use this only when a caller already knows the public URL. Managed public
58 /// endpoint flows should prefer `domain_metadata` plus controller-reported
59 /// load balancer outputs so DNS, certificate renewal, and route readiness
60 /// stay tied to the resource state.
61 ///
62 /// If not set, platforms determine public URLs from other sources:
63 /// - Managed DNS/TLS flows: `domain_metadata` FQDN or load balancer DNS
64 /// - Local: `http://localhost:{allocated_port}`
65 /// - Custom or disabled exposure: no public URL unless a controller reports one
66 ///
67 /// Key: resource ID, Value: public URL (e.g., "https://api.acme.com")
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub public_urls: Option<HashMap<String, String>>,
70 /// Domain metadata for auto-managed public resources.
71 ///
72 /// Contains generated hostnames, DNS record state, certificate material,
73 /// and renewal markers for platforms that use managed public endpoints.
74 /// Kubernetes uses this only when its exposure mode is `generated`; BYO and
75 /// disabled Kubernetes exposure do not receive managed domain metadata.
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub domain_metadata: Option<DomainMetadata>,
78 /// OTLP observability configuration for log export (optional).
79 ///
80 /// When set, worker runtimes export captured application logs through this
81 /// endpoint. Container orchestrators may use it for their node-level log
82 /// collectors, but app container configs must not receive the auth header.
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub monitoring: Option<OtlpConfig>,
85 /// Manager base URL (e.g., "https://manager.alien.dev").
86 ///
87 /// The manager IS the container registry — its `/v2/` endpoint serves as
88 /// the OCI Distribution API. Controllers derive the proxy host from this
89 /// to configure pull auth (RegistryCredentials, imagePullSecrets).
90 ///
91 /// When None (e.g., `alien dev`), controllers use image URIs as-is.
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub manager_url: Option<String>,
94 /// Deployment token for pull authentication with the manager's registry.
95 ///
96 /// Used by controllers to configure registry credentials so cloud platforms
97 /// and K8s can pull images from the manager's `/v2/` endpoint.
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub deployment_token: Option<String>,
100 /// Native image registry host+prefix for platforms that require it.
101 ///
102 /// Lambda (ECR) and Cloud Run (GAR) require native registry URIs. Other
103 /// runtimes, including Azure Container Apps, pull through the manager's
104 /// registry proxy.
105 ///
106 /// Derived by the manager from the artifact registry binding:
107 /// - ECR: `{account_id}.dkr.ecr.{region}.amazonaws.com/{repository_prefix}`
108 /// - GAR: `{region}-docker.pkg.dev/{project_id}/{repository_name}`
109 #[serde(default, skip_serializing_if = "Option::is_none")]
110 pub native_image_host: Option<String>,
111}
112
113/// OTLP log export configuration for a deployment.
114///
115/// When set, injected compute runtimes export captured application logs
116/// through the given endpoint via OTLP/HTTP; which resources are injected
117/// is platform-dependent. Workers and daemons read auth headers from a
118/// runtime-only secret — never from application environment variables.
119/// Containers have no runtime wrapper, so they get the endpoint and auth
120/// header as plain OTEL env vars for the application's own exporter.
121#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
122#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
123#[serde(rename_all = "camelCase")]
124pub struct OtlpConfig {
125 /// Full OTLP logs endpoint URL.
126 /// Example: "https://<manager-host>/v1/logs"
127 pub logs_endpoint: String,
128 /// Auth header value in "key=value,..." format.
129 /// Example: "authorization=Bearer <write-token>"
130 pub logs_auth_header: String,
131 /// Full OTLP metrics endpoint URL (optional).
132 /// When set, the worker runtime exports its own VM/container orchestration metrics here.
133 /// Example: "https://api.axiom.co/v1/metrics"
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub metrics_endpoint: Option<String>,
136 /// Auth header value for the metrics endpoint in "key=value,..." format (optional).
137 ///
138 /// When absent, `logs_auth_header` is reused for metrics -- suitable when the same
139 /// credential covers both signals. When present (e.g. Axiom with separate datasets),
140 /// this value is used exclusively for metrics.
141 ///
142 /// Example: "authorization=Bearer <token>,x-axiom-dataset=<metrics-dataset>"
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub metrics_auth_header: Option<String>,
145 /// Resource attributes attached to every OTLP signal emitted for this deployment.
146 ///
147 /// Platform managers use this for stable identity such as `alien.workspace_id`,
148 /// `alien.project_id`, `alien.deployment_group_id`, and `alien.deployment_id`.
149 /// Runtime-specific resource attributes such as `service.name` remain owned by
150 /// the runtime/exporter.
151 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
152 pub resource_attributes: HashMap<String, String>,
153}