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