Skip to main content

alien_core/bindings/
artifact_registry.rs

1//! Service-type based artifact registry binding definitions
2
3use super::BindingValue;
4use serde::{Deserialize, Serialize};
5
6/// AWS ECR (Elastic Container Registry) binding configuration
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
9#[serde(rename_all = "camelCase")]
10pub struct EcrArtifactRegistryBinding {
11    /// Repository prefix for this registry (used to construct ECR repository names)
12    pub repository_prefix: BindingValue<String>,
13    /// ARN of the IAM role for pull permissions (optional — omit for single-account)
14    #[serde(default, skip_serializing_if = "Option::is_none")]
15    pub pull_role_arn: Option<BindingValue<String>>,
16    /// ARN of the IAM role for push+pull permissions (optional — omit for single-account)
17    #[serde(default, skip_serializing_if = "Option::is_none")]
18    pub push_role_arn: Option<BindingValue<String>>,
19}
20
21/// Azure Container Registry binding configuration
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
24#[serde(rename_all = "camelCase")]
25pub struct AcrArtifactRegistryBinding {
26    /// Registry name (e.g., "myregistry") - endpoint is derived from this
27    pub registry_name: BindingValue<String>,
28    /// Resource group name where the registry is located
29    pub resource_group_name: BindingValue<String>,
30    /// Repository prefix for this registry (used for proxy routing)
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub repository_prefix: Option<BindingValue<String>>,
33}
34
35/// Google Artifact Registry binding configuration
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
38#[serde(rename_all = "camelCase")]
39pub struct GarArtifactRegistryBinding {
40    /// Repository name in the Artifact Registry (e.g., "alien-test").
41    /// Used as the default when cross-account access methods are called
42    /// without a specific repo name.
43    pub repository_name: BindingValue<String>,
44    /// Optional service account email for pull permissions (omit for single-project)
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub pull_service_account_email: Option<BindingValue<String>>,
47    /// Optional service account email for push+pull permissions (omit for single-project)
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub push_service_account_email: Option<BindingValue<String>>,
50}
51
52/// Local container registry binding configuration.
53///
54/// The local registry runs on localhost only and does not require authentication.
55/// Security boundary is the OS process isolation on the customer's machine.
56/// External image access is secured by the manager's registry proxy (deployment tokens).
57#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
59#[serde(rename_all = "camelCase")]
60pub struct LocalArtifactRegistryBinding {
61    /// The registry URL endpoint (e.g., "localhost:5000")
62    pub registry_url: BindingValue<String>,
63    /// Optional base directory for registry data
64    pub data_dir: BindingValue<Option<String>>,
65}
66
67/// Service-type based artifact registry binding that supports multiple registry providers
68#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
69#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
70#[serde(tag = "service", rename_all = "lowercase")]
71pub enum ArtifactRegistryBinding {
72    /// AWS ECR (Elastic Container Registry)
73    Ecr(EcrArtifactRegistryBinding),
74    /// Azure Container Registry
75    Acr(AcrArtifactRegistryBinding),
76    /// Google Artifact Registry
77    Gar(GarArtifactRegistryBinding),
78    /// Local container registry
79    Local(LocalArtifactRegistryBinding),
80}
81
82impl ArtifactRegistryBinding {
83    /// Creates an ECR artifact registry binding
84    pub fn ecr(
85        repository_prefix: impl Into<BindingValue<String>>,
86        pull_role_arn: Option<impl Into<BindingValue<String>>>,
87        push_role_arn: Option<impl Into<BindingValue<String>>>,
88    ) -> Self {
89        Self::Ecr(EcrArtifactRegistryBinding {
90            repository_prefix: repository_prefix.into(),
91            pull_role_arn: pull_role_arn.map(|v| v.into()),
92            push_role_arn: push_role_arn.map(|v| v.into()),
93        })
94    }
95
96    /// Creates an ACR artifact registry binding
97    pub fn acr(
98        registry_name: impl Into<BindingValue<String>>,
99        resource_group_name: impl Into<BindingValue<String>>,
100    ) -> Self {
101        Self::Acr(AcrArtifactRegistryBinding {
102            registry_name: registry_name.into(),
103            resource_group_name: resource_group_name.into(),
104            repository_prefix: None,
105        })
106    }
107
108    /// Creates a GAR artifact registry binding
109    pub fn gar(
110        repository_name: impl Into<BindingValue<String>>,
111        pull_service_account_email: Option<impl Into<BindingValue<String>>>,
112        push_service_account_email: Option<impl Into<BindingValue<String>>>,
113    ) -> Self {
114        Self::Gar(GarArtifactRegistryBinding {
115            repository_name: repository_name.into(),
116            pull_service_account_email: pull_service_account_email.map(|v| v.into()),
117            push_service_account_email: push_service_account_email.map(|v| v.into()),
118        })
119    }
120
121    /// Creates a local artifact registry binding
122    pub fn local(
123        registry_url: impl Into<BindingValue<String>>,
124        data_dir: impl Into<BindingValue<Option<String>>>,
125    ) -> Self {
126        Self::Local(LocalArtifactRegistryBinding {
127            registry_url: registry_url.into(),
128            data_dir: data_dir.into(),
129        })
130    }
131}