use std::env::{self, VarError};
use super::cloud::{Auth, CloudConfig};
use crate::Error;
trait Environment {
fn get(&self, name: &'static str) -> Result<String, VarError>;
}
#[derive(Debug, Clone, Copy)]
struct RealEnvironment;
impl Environment for RealEnvironment {
fn get(&self, name: &'static str) -> Result<String, VarError> {
env::var(name)
}
}
#[inline]
fn _from_env<E: Environment>(env: E) -> Result<CloudConfig, Error> {
if let Ok(cloud_name) = env.get("OS_CLOUD") {
return CloudConfig::from_config(cloud_name);
}
let auth = Auth {
auth_url: env.get("OS_AUTH_URL").ok(),
endpoint: env.get("OS_ENDPOINT").ok(),
password: env.get("OS_PASSWORD").ok(),
project_id: env.get("OS_PROJECT_ID").ok(),
project_name: env.get("OS_PROJECT_NAME").ok(),
project_domain_id: env.get("OS_PROJECT_DOMAIN_ID").ok(),
project_domain_name: env.get("OS_PROJECT_DOMAIN_NAME").ok(),
token: env.get("OS_TOKEN").ok(),
username: env.get("OS_USERNAME").ok(),
user_domain_name: env.get("OS_USER_DOMAIN_NAME").ok(),
user_id: env.get("OS_USER_ID").ok(),
application_credential_id: env.get("OS_APPLICATION_CREDENTIAL_ID").ok(),
application_credential_secret: env.get("OS_APPLICATION_CREDENTIAL_SECRET").ok(),
application_credential_name: env.get("OS_APPLICATION_CREDENTIAL_NAME").ok(),
};
let config = CloudConfig {
auth: Some(auth),
auth_type: env.get("OS_AUTH_TYPE").ok(),
cacert: env.get("OS_CACERT").ok(),
interface: env.get("OS_INTERFACE").ok(),
region_name: env.get("OS_REGION_NAME").ok(),
options: Default::default(),
};
Ok(config)
}
pub fn from_env() -> Result<CloudConfig, Error> {
_from_env(RealEnvironment)
}
#[cfg(test)]
pub mod test {
use std::collections::HashMap;
use std::env::VarError;
use maplit::hashmap;
use super::{Environment, _from_env};
impl Environment for HashMap<&'static str, &'static str> {
fn get(&self, name: &'static str) -> Result<String, VarError> {
self.get(name)
.cloned()
.map(From::from)
.ok_or_else(|| VarError::NotPresent)
}
}
fn check(env: impl Environment) {
let _ = _from_env(env).unwrap().create_session_config().unwrap();
}
#[test]
fn test_password_no_domains() {
let env = hashmap! {
"OS_AUTH_URL" => "http://example.com",
"OS_USERNAME" => "admin",
"OS_PASSWORD" => "password",
"OS_PROJECT_NAME" => "admin",
};
check(env);
}
#[test]
fn test_password_with_domains() {
let env = hashmap! {
"OS_AUTH_URL" => "http://example.com",
"OS_USERNAME" => "admin",
"OS_PASSWORD" => "password",
"OS_PROJECT_NAME" => "admin",
"OS_USER_DOMAIN_NAME" => "Default",
"OS_PROJECT_DOMAIN_NAME" => "Default",
};
check(env);
}
#[test]
fn test_password_with_type() {
let env = hashmap! {
"OS_AUTH_TYPE" => "password",
"OS_AUTH_URL" => "http://example.com",
"OS_USERNAME" => "admin",
"OS_PASSWORD" => "password",
"OS_PROJECT_NAME" => "admin",
"OS_USER_DOMAIN_NAME" => "Default",
"OS_PROJECT_DOMAIN_NAME" => "Default",
};
check(env);
}
#[test]
fn test_token_no_domains() {
let env = hashmap! {
"OS_AUTH_URL" => "http://example.com",
"OS_TOKEN" => "abcdef",
"OS_PROJECT_NAME" => "admin",
};
check(env);
}
#[test]
fn test_token_with_domains() {
let env = hashmap! {
"OS_AUTH_URL" => "http://example.com",
"OS_TOKEN" => "abcdef",
"OS_PROJECT_NAME" => "admin",
"OS_PROJECT_DOMAIN_NAME" => "Default",
};
check(env);
}
#[test]
fn test_token_with_type() {
let env = hashmap! {
"OS_AUTH_TYPE" => "v3token",
"OS_AUTH_URL" => "http://example.com",
"OS_TOKEN" => "abcdef",
"OS_PROJECT_NAME" => "admin",
"OS_PROJECT_DOMAIN_NAME" => "Default",
};
check(env);
}
#[test]
fn test_http_basic() {
let env = hashmap! {
"OS_AUTH_TYPE" => "http_basic",
"OS_ENDPOINT" => "http://example.com",
"OS_USERNAME" => "admin",
"OS_PASSWORD" => "password",
};
check(env);
}
#[test]
fn test_none() {
let env = hashmap! {
"OS_AUTH_TYPE" => "none",
"OS_ENDPOINT" => "http://example.com",
};
check(env);
}
}