alien_client_config/
client_config_ext.rs1use alien_client_core::{ErrorData, Result};
4use alien_core::{ClientConfig, ImpersonationConfig, Platform};
5use alien_error::AlienError;
6#[cfg(any(
7 feature = "aws",
8 feature = "gcp",
9 feature = "azure",
10 feature = "kubernetes"
11))]
12use alien_error::Context;
13use async_trait::async_trait;
14use std::collections::HashMap;
15
16#[async_trait]
18pub trait ClientConfigExt {
19 async fn from_env(
37 platform: Platform,
38 environment_variables: &HashMap<String, String>,
39 ) -> Result<Self>
40 where
41 Self: Sized;
42
43 async fn from_std_env(platform: Platform) -> Result<Self>
59 where
60 Self: Sized;
61
62 fn platform(&self) -> Platform;
64
65 async fn impersonate(&self, config: ImpersonationConfig) -> Result<ClientConfig>;
88}
89
90#[async_trait]
91impl ClientConfigExt for ClientConfig {
92 async fn from_env(
93 platform: Platform,
94 environment_variables: &HashMap<String, String>,
95 ) -> Result<Self> {
96 match platform {
97 #[cfg(feature = "aws")]
98 Platform::Aws => {
99 use alien_aws_clients::AwsClientConfigExt;
100 let config = alien_aws_clients::AwsClientConfig::from_env(environment_variables)
101 .await
102 .context(ErrorData::InvalidClientConfig {
103 message:
104 "Failed to create AWS client configuration from environment variables"
105 .to_string(),
106 errors: None,
107 })?;
108 Ok(ClientConfig::Aws(Box::new(config)))
109 }
110 #[cfg(not(feature = "aws"))]
111 Platform::Aws => Err(AlienError::new(ErrorData::InvalidClientConfig {
112 message: "AWS support is not enabled in this build".to_string(),
113 errors: None,
114 })),
115 #[cfg(feature = "gcp")]
116 Platform::Gcp => {
117 use alien_gcp_clients::GcpClientConfigExt;
118 let config = alien_gcp_clients::GcpClientConfig::from_env(environment_variables)
119 .await
120 .context(ErrorData::InvalidClientConfig {
121 message:
122 "Failed to create GCP client configuration from environment variables"
123 .to_string(),
124 errors: None,
125 })?;
126 Ok(ClientConfig::Gcp(Box::new(config)))
127 }
128 #[cfg(not(feature = "gcp"))]
129 Platform::Gcp => Err(AlienError::new(ErrorData::InvalidClientConfig {
130 message: "GCP support is not enabled in this build".to_string(),
131 errors: None,
132 })),
133 #[cfg(feature = "azure")]
134 Platform::Azure => {
135 use alien_azure_clients::AzureClientConfigExt;
136 let config = alien_azure_clients::AzureClientConfig::from_env(
137 environment_variables,
138 )
139 .await
140 .context(ErrorData::InvalidClientConfig {
141 message:
142 "Failed to create Azure client configuration from environment variables"
143 .to_string(),
144 errors: None,
145 })?;
146 Ok(ClientConfig::Azure(Box::new(config)))
147 }
148 #[cfg(not(feature = "azure"))]
149 Platform::Azure => Err(AlienError::new(ErrorData::InvalidClientConfig {
150 message: "Azure support is not enabled in this build".to_string(),
151 errors: None,
152 })),
153 #[cfg(feature = "kubernetes")]
154 Platform::Kubernetes => {
155 use alien_k8s_clients::KubernetesClientConfigExt;
156 let config = alien_k8s_clients::KubernetesClientConfig::from_env(environment_variables)
157 .await
158 .context(ErrorData::InvalidClientConfig {
159 message: "Failed to create Kubernetes client configuration from environment variables".to_string(),
160 errors: None,
161 })?;
162 Ok(ClientConfig::Kubernetes(Box::new(config)))
163 }
164 #[cfg(not(feature = "kubernetes"))]
165 Platform::Kubernetes => Err(AlienError::new(ErrorData::InvalidClientConfig {
166 message: "Kubernetes support is not enabled in this build".to_string(),
167 errors: None,
168 })),
169 Platform::Machines => Err(AlienError::new(ErrorData::InvalidClientConfig {
170 message: "Machines deployments do not use local cloud client configuration"
171 .to_string(),
172 errors: None,
173 })),
174 Platform::Test => Ok(ClientConfig::Test),
175 Platform::Local => {
176 let state_directory = environment_variables
178 .get("ALIEN_LOCAL_STATE_DIRECTORY")
179 .cloned()
180 .unwrap_or_else(|| "/tmp/alien-local".to_string());
181
182 Ok(ClientConfig::Local { state_directory })
183 }
184 }
185 }
186
187 async fn from_std_env(platform: Platform) -> Result<Self> {
188 let env_vars: HashMap<String, String> = std::env::vars().collect();
189 Self::from_env(platform, &env_vars).await
190 }
191
192 fn platform(&self) -> Platform {
193 match self {
194 #[cfg(feature = "aws")]
195 ClientConfig::Aws(_) => Platform::Aws,
196 #[cfg(feature = "gcp")]
197 ClientConfig::Gcp(_) => Platform::Gcp,
198 #[cfg(feature = "azure")]
199 ClientConfig::Azure(_) => Platform::Azure,
200 #[cfg(feature = "kubernetes")]
201 ClientConfig::Kubernetes(_) => Platform::Kubernetes,
202 #[cfg(feature = "kubernetes")]
203 ClientConfig::KubernetesCloud { .. } => Platform::Kubernetes,
204 ClientConfig::Test => Platform::Test,
205 ClientConfig::Local { .. } => Platform::Local,
206 #[allow(unreachable_patterns)]
209 _ => unreachable!("ClientConfig requires at least one platform feature to be enabled"),
210 }
211 }
212
213 async fn impersonate(&self, config: ImpersonationConfig) -> Result<ClientConfig> {
214 match (self, config) {
215 #[cfg(feature = "aws")]
216 (ClientConfig::Aws(aws_config), ImpersonationConfig::Aws(imp_config)) => {
217 use alien_aws_clients::AwsClientConfigExt;
218 let new_config = aws_config.impersonate(imp_config).await.map_err(|e| {
219 AlienError::new(ErrorData::AuthenticationError {
220 message: format!("AWS role impersonation failed: {}", e),
221 })
222 })?;
223 Ok(ClientConfig::Aws(Box::new(new_config)))
224 }
225 #[cfg(feature = "gcp")]
226 (ClientConfig::Gcp(gcp_config), ImpersonationConfig::Gcp(imp_config)) => {
227 use alien_gcp_clients::GcpClientConfigExt;
228 let new_config = gcp_config.impersonate(imp_config).await.map_err(|e| {
229 AlienError::new(ErrorData::AuthenticationError {
230 message: format!("GCP service account impersonation failed: {}", e),
231 })
232 })?;
233 Ok(ClientConfig::Gcp(Box::new(new_config)))
234 }
235 #[cfg(feature = "azure")]
236 (ClientConfig::Azure(azure_config), ImpersonationConfig::Azure(imp_config)) => {
237 use alien_azure_clients::AzureClientConfigExt;
238 let new_config = azure_config.impersonate(imp_config).await.map_err(|e| {
239 AlienError::new(ErrorData::AuthenticationError {
240 message: format!("Azure managed identity impersonation failed: {}", e),
241 })
242 })?;
243 Ok(ClientConfig::Azure(Box::new(new_config)))
244 }
245 #[cfg(feature = "kubernetes")]
247 (ClientConfig::Kubernetes(_), _) => Err(AlienError::new(ErrorData::InvalidInput {
248 message: "Kubernetes platform does not support impersonation".to_string(),
249 field_name: Some("impersonation_config".to_string()),
250 })),
251 _ => Err(AlienError::new(ErrorData::InvalidInput {
252 message: "Platform config and impersonation config types must match".to_string(),
253 field_name: Some("impersonation_config".to_string()),
254 })),
255 }
256 }
257}