alien_client_config/
client_config_ext.rs1use alien_client_core::{ErrorData, Result};
4use alien_core::{ClientConfig, ImpersonationConfig, Platform};
5use alien_error::{AlienError, Context};
6use async_trait::async_trait;
7use std::collections::HashMap;
8
9#[async_trait]
11pub trait ClientConfigExt {
12 async fn from_env(
30 platform: Platform,
31 environment_variables: &HashMap<String, String>,
32 ) -> Result<Self>
33 where
34 Self: Sized;
35
36 async fn from_std_env(platform: Platform) -> Result<Self>
52 where
53 Self: Sized;
54
55 fn platform(&self) -> Platform;
57
58 async fn impersonate(&self, config: ImpersonationConfig) -> Result<ClientConfig>;
80}
81
82#[async_trait]
83impl ClientConfigExt for ClientConfig {
84 async fn from_env(
85 platform: Platform,
86 environment_variables: &HashMap<String, String>,
87 ) -> Result<Self> {
88 match platform {
89 #[cfg(feature = "aws")]
90 Platform::Aws => {
91 use alien_aws_clients::AwsClientConfigExt;
92 let config = alien_aws_clients::AwsClientConfig::from_env(environment_variables).await
93 .map_err(|e| AlienError::new(ErrorData::InvalidClientConfig {
94 message: format!("Failed to create AWS client configuration from environment variables: {}", e),
95 errors: None,
96 }))?;
97 Ok(ClientConfig::Aws(Box::new(config)))
98 }
99 #[cfg(not(feature = "aws"))]
100 Platform::Aws => Err(AlienError::new(ErrorData::InvalidClientConfig {
101 message: "AWS support is not enabled in this build".to_string(),
102 errors: None,
103 })),
104 #[cfg(feature = "gcp")]
105 Platform::Gcp => {
106 use alien_gcp_clients::GcpClientConfigExt;
107 let config = alien_gcp_clients::GcpClientConfig::from_env(environment_variables).await
108 .map_err(|e| AlienError::new(ErrorData::InvalidClientConfig {
109 message: format!("Failed to create GCP client configuration from environment variables: {}", e),
110 errors: None,
111 }))?;
112 Ok(ClientConfig::Gcp(Box::new(config)))
113 }
114 #[cfg(not(feature = "gcp"))]
115 Platform::Gcp => Err(AlienError::new(ErrorData::InvalidClientConfig {
116 message: "GCP support is not enabled in this build".to_string(),
117 errors: None,
118 })),
119 #[cfg(feature = "azure")]
120 Platform::Azure => {
121 use alien_azure_clients::AzureClientConfigExt;
122 let config = alien_azure_clients::AzureClientConfig::from_env(environment_variables).await
123 .map_err(|e| AlienError::new(ErrorData::InvalidClientConfig {
124 message: format!("Failed to create Azure client configuration from environment variables: {}", e),
125 errors: None,
126 }))?;
127 Ok(ClientConfig::Azure(Box::new(config)))
128 }
129 #[cfg(not(feature = "azure"))]
130 Platform::Azure => Err(AlienError::new(ErrorData::InvalidClientConfig {
131 message: "Azure support is not enabled in this build".to_string(),
132 errors: None,
133 })),
134 #[cfg(feature = "kubernetes")]
135 Platform::Kubernetes => {
136 use alien_k8s_clients::KubernetesClientConfigExt;
137 let config = alien_k8s_clients::KubernetesClientConfig::from_env(environment_variables).await
138 .map_err(|e| AlienError::new(ErrorData::InvalidClientConfig {
139 message: format!("Failed to create Kubernetes client configuration from environment variables: {}", e),
140 errors: None,
141 }))?;
142 Ok(ClientConfig::Kubernetes(Box::new(config)))
143 }
144 #[cfg(not(feature = "kubernetes"))]
145 Platform::Kubernetes => Err(AlienError::new(ErrorData::InvalidClientConfig {
146 message: "Kubernetes support is not enabled in this build".to_string(),
147 errors: None,
148 })),
149 Platform::Test => Ok(ClientConfig::Test),
150 Platform::Local => {
151 let state_directory = environment_variables
153 .get("ALIEN_LOCAL_STATE_DIRECTORY")
154 .cloned()
155 .unwrap_or_else(|| "/tmp/alien-local".to_string());
156
157 Ok(ClientConfig::Local {
158 state_directory,
159 artifact_registry_config: None,
160 })
161 }
162 }
163 }
164
165 async fn from_std_env(platform: Platform) -> Result<Self> {
166 let env_vars: HashMap<String, String> = std::env::vars().collect();
167 Self::from_env(platform, &env_vars).await
168 }
169
170 fn platform(&self) -> Platform {
171 match self {
172 #[cfg(feature = "aws")]
173 ClientConfig::Aws(_) => Platform::Aws,
174 #[cfg(feature = "gcp")]
175 ClientConfig::Gcp(_) => Platform::Gcp,
176 #[cfg(feature = "azure")]
177 ClientConfig::Azure(_) => Platform::Azure,
178 #[cfg(feature = "kubernetes")]
179 ClientConfig::Kubernetes(_) => Platform::Kubernetes,
180 ClientConfig::Test => Platform::Test,
181 ClientConfig::Local { .. } => Platform::Local,
182 #[allow(unreachable_patterns)]
185 _ => unreachable!("ClientConfig requires at least one platform feature to be enabled"),
186 }
187 }
188
189 async fn impersonate(&self, config: ImpersonationConfig) -> Result<ClientConfig> {
190 match (self, config) {
191 #[cfg(feature = "aws")]
192 (ClientConfig::Aws(aws_config), ImpersonationConfig::Aws(imp_config)) => {
193 use alien_aws_clients::AwsClientConfigExt;
194 let new_config = aws_config.impersonate(imp_config).await.map_err(|e| {
195 AlienError::new(ErrorData::AuthenticationError {
196 message: format!("AWS role impersonation failed: {}", e),
197 })
198 })?;
199 Ok(ClientConfig::Aws(Box::new(new_config)))
200 }
201 #[cfg(feature = "gcp")]
202 (ClientConfig::Gcp(gcp_config), ImpersonationConfig::Gcp(imp_config)) => {
203 use alien_gcp_clients::GcpClientConfigExt;
204 let new_config = gcp_config.impersonate(imp_config).await.map_err(|e| {
205 AlienError::new(ErrorData::AuthenticationError {
206 message: format!("GCP service account impersonation failed: {}", e),
207 })
208 })?;
209 Ok(ClientConfig::Gcp(Box::new(new_config)))
210 }
211 #[cfg(feature = "azure")]
212 (ClientConfig::Azure(azure_config), ImpersonationConfig::Azure(imp_config)) => {
213 use alien_azure_clients::AzureClientConfigExt;
214 let new_config = azure_config.impersonate(imp_config).await.map_err(|e| {
215 AlienError::new(ErrorData::AuthenticationError {
216 message: format!("Azure managed identity impersonation failed: {}", e),
217 })
218 })?;
219 Ok(ClientConfig::Azure(Box::new(new_config)))
220 }
221 #[cfg(feature = "kubernetes")]
223 (ClientConfig::Kubernetes(_), _) => Err(AlienError::new(ErrorData::InvalidInput {
224 message: "Kubernetes platform does not support impersonation".to_string(),
225 field_name: Some("impersonation_config".to_string()),
226 })),
227 _ => Err(AlienError::new(ErrorData::InvalidInput {
228 message: "Platform config and impersonation config types must match".to_string(),
229 field_name: Some("impersonation_config".to_string()),
230 })),
231 }
232 }
233}