Skip to main content

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    /// DNS-style label domain used for Kubernetes resource ownership labels.
56    ///
57    /// Defaults to `alien.dev` when absent. Whitelabeled Operator builds set this
58    /// so generated workloads and optional log collectors share the same label
59    /// namespace.
60    #[serde(default, skip_serializing_if = "Option::is_none")]
61    pub label_domain: Option<String>,
62    /// Kubernetes label selector that narrows which raw resources the observe
63    /// pass reports (e.g. `app.kubernetes.io/part-of=my-app`). `None` observes
64    /// everything in the namespace. Ignored by cloud observers.
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub observe_label_selector: Option<String>,
67    /// When true the observe pass reports raw resources across every namespace
68    /// (cluster scope); otherwise it stays within the operator's own namespace.
69    /// The label selector, if any, still filters within whichever scope applies.
70    /// Ignored by cloud observers.
71    #[serde(default)]
72    #[builder(default)]
73    pub observe_all_namespaces: bool,
74    /// Public endpoint URLs for exposed resources (optional override).
75    ///
76    /// Use this only when a caller already knows the public URL. Managed public
77    /// endpoint flows should prefer `domain_metadata` plus controller-reported
78    /// load balancer outputs so DNS, certificate renewal, and route readiness
79    /// stay tied to the resource state.
80    ///
81    /// If not set, platforms determine public endpoint URLs from other sources:
82    /// - Managed DNS/TLS flows: `domain_metadata` FQDN or load balancer DNS
83    /// - Local: `http://localhost:{allocated_port}`
84    /// - Custom or disabled exposure: no public endpoint URL unless a controller reports one
85    ///
86    /// Outer key: resource ID. Inner key: endpoint name. Value: public URL.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub public_endpoints: Option<HashMap<String, HashMap<String, String>>>,
89    /// Domain metadata for auto-managed public resources.
90    ///
91    /// Contains generated hostnames, DNS record state, certificate material,
92    /// and renewal markers for platforms that use managed public endpoints.
93    /// Kubernetes uses this only when its exposure mode is `generated`; BYO and
94    /// disabled Kubernetes exposure do not receive managed domain metadata.
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub domain_metadata: Option<DomainMetadata>,
97    /// OTLP observability configuration for log export (optional).
98    ///
99    /// When set, worker runtimes export captured application logs through this
100    /// endpoint. Container orchestrators may use it for their node-level log
101    /// collectors, but app container configs must not receive the auth header.
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub monitoring: Option<OtlpConfig>,
104    /// Manager base URL (e.g., "https://manager.alien.dev").
105    ///
106    /// The manager IS the container registry — its `/v2/` endpoint serves as
107    /// the OCI Distribution API. Controllers derive the proxy host from this
108    /// to configure pull auth (RegistryCredentials, imagePullSecrets).
109    ///
110    /// When None (e.g., `alien dev`), controllers use image URIs as-is.
111    #[serde(default, skip_serializing_if = "Option::is_none")]
112    pub manager_url: Option<String>,
113    /// Deployment token for pull authentication with the manager's registry.
114    ///
115    /// Used by controllers to configure registry credentials so cloud platforms
116    /// and K8s can pull images from the manager's `/v2/` endpoint.
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub deployment_token: Option<String>,
119    /// Native image registry host+prefix for platforms that require it.
120    ///
121    /// Lambda (ECR) and Cloud Run (GAR) require native registry URIs. Other
122    /// runtimes, including Azure Container Apps, pull through the manager's
123    /// registry proxy.
124    ///
125    /// Derived by the manager from the artifact registry binding:
126    /// - ECR: `{account_id}.dkr.ecr.{region}.amazonaws.com/{repository_prefix}`
127    /// - GAR: `{region}-docker.pkg.dev/{project_id}/{repository_name}`
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub native_image_host: Option<String>,
130}
131
132/// Resource-attribute key marking OTLP telemetry as Alien system-component
133/// output (infrastructure daemons and internal runtimes) rather than user
134/// workload. Log consumers — the CLI log viewer and the dashboard — hide
135/// telemetry carrying this attribute by default. The value is the string
136/// `"true"`.
137///
138/// System components set this on their own telemetry's resource attributes so
139/// consumers can filter generically, without enumerating component names.
140pub const ALIEN_SYSTEM_RESOURCE_ATTRIBUTE: &str = "alien.system";
141
142/// OTLP log export configuration for a deployment.
143///
144/// When set, injected compute runtimes export captured application logs
145/// through the given endpoint via OTLP/HTTP; which resources are injected
146/// is platform-dependent. Workers and daemons read auth headers from a
147/// runtime-only secret — never from application environment variables.
148/// Containers have no runtime wrapper, so they get the endpoint and auth
149/// header as plain OTEL env vars for the application's own exporter.
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
151#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
152#[serde(rename_all = "camelCase")]
153pub struct OtlpConfig {
154    /// Full OTLP logs endpoint URL.
155    /// Example: "https://<manager-host>/v1/logs"
156    pub logs_endpoint: String,
157    /// Auth header value in "key=value,..." format.
158    /// Example: "authorization=Bearer <write-token>"
159    pub logs_auth_header: String,
160    /// Full OTLP metrics endpoint URL (optional).
161    /// When set, the worker runtime exports its own VM/container orchestration metrics here.
162    /// Example: "https://api.axiom.co/v1/metrics"
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub metrics_endpoint: Option<String>,
165    /// Auth header value for the metrics endpoint in "key=value,..." format (optional).
166    ///
167    /// When absent, `logs_auth_header` is reused for metrics -- suitable when the same
168    /// credential covers both signals. When present (e.g. Axiom with separate datasets),
169    /// this value is used exclusively for metrics.
170    ///
171    /// Example: "authorization=Bearer <token>,x-axiom-dataset=<metrics-dataset>"
172    #[serde(skip_serializing_if = "Option::is_none")]
173    pub metrics_auth_header: Option<String>,
174    /// Resource attributes attached to every OTLP signal emitted for this deployment.
175    ///
176    /// Platform managers use this for stable identity such as `alien.workspace_id`,
177    /// `alien.project_id`, `alien.deployment_group_id`, and `alien.deployment_id`.
178    /// Runtime-specific resource attributes such as `service.name` remain owned by
179    /// the runtime/exporter.
180    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
181    pub resource_attributes: HashMap<String, String>,
182}