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::Test => Ok(ClientConfig::Test),
170 Platform::Local => {
171 let state_directory = environment_variables
173 .get("ALIEN_LOCAL_STATE_DIRECTORY")
174 .cloned()
175 .unwrap_or_else(|| "/tmp/alien-local".to_string());
176
177 Ok(ClientConfig::Local { state_directory })
178 }
179 }
180 }
181
182 async fn from_std_env(platform: Platform) -> Result<Self> {
183 let env_vars: HashMap<String, String> = std::env::vars().collect();
184 Self::from_env(platform, &env_vars).await
185 }
186
187 fn platform(&self) -> Platform {
188 match self {
189 #[cfg(feature = "aws")]
190 ClientConfig::Aws(_) => Platform::Aws,
191 #[cfg(feature = "gcp")]
192 ClientConfig::Gcp(_) => Platform::Gcp,
193 #[cfg(feature = "azure")]
194 ClientConfig::Azure(_) => Platform::Azure,
195 #[cfg(feature = "kubernetes")]
196 ClientConfig::Kubernetes(_) => Platform::Kubernetes,
197 #[cfg(feature = "kubernetes")]
198 ClientConfig::KubernetesCloud { .. } => Platform::Kubernetes,
199 ClientConfig::Test => Platform::Test,
200 ClientConfig::Local { .. } => Platform::Local,
201 #[allow(unreachable_patterns)]
204 _ => unreachable!("ClientConfig requires at least one platform feature to be enabled"),
205 }
206 }
207
208 async fn impersonate(&self, config: ImpersonationConfig) -> Result<ClientConfig> {
209 match (self, config) {
210 #[cfg(feature = "aws")]
211 (ClientConfig::Aws(aws_config), ImpersonationConfig::Aws(imp_config)) => {
212 use alien_aws_clients::AwsClientConfigExt;
213 let new_config = aws_config.impersonate(imp_config).await.map_err(|e| {
214 AlienError::new(ErrorData::AuthenticationError {
215 message: format!("AWS role impersonation failed: {}", e),
216 })
217 })?;
218 Ok(ClientConfig::Aws(Box::new(new_config)))
219 }
220 #[cfg(feature = "gcp")]
221 (ClientConfig::Gcp(gcp_config), ImpersonationConfig::Gcp(imp_config)) => {
222 use alien_gcp_clients::GcpClientConfigExt;
223 let new_config = gcp_config.impersonate(imp_config).await.map_err(|e| {
224 AlienError::new(ErrorData::AuthenticationError {
225 message: format!("GCP service account impersonation failed: {}", e),
226 })
227 })?;
228 Ok(ClientConfig::Gcp(Box::new(new_config)))
229 }
230 #[cfg(feature = "azure")]
231 (ClientConfig::Azure(azure_config), ImpersonationConfig::Azure(imp_config)) => {
232 use alien_azure_clients::AzureClientConfigExt;
233 let new_config = azure_config.impersonate(imp_config).await.map_err(|e| {
234 AlienError::new(ErrorData::AuthenticationError {
235 message: format!("Azure managed identity impersonation failed: {}", e),
236 })
237 })?;
238 Ok(ClientConfig::Azure(Box::new(new_config)))
239 }
240 #[cfg(feature = "kubernetes")]
242 (ClientConfig::Kubernetes(_), _) => Err(AlienError::new(ErrorData::InvalidInput {
243 message: "Kubernetes platform does not support impersonation".to_string(),
244 field_name: Some("impersonation_config".to_string()),
245 })),
246 _ => Err(AlienError::new(ErrorData::InvalidInput {
247 message: "Platform config and impersonation config types must match".to_string(),
248 field_name: Some("impersonation_config".to_string()),
249 })),
250 }
251 }
252}