use std::sync::Arc;
use std::sync::Mutex;
use anyhow::Result;
use super::config::Config;
#[derive(Clone)]
#[cfg_attr(test, derive(Debug))]
pub struct Credential {
pub access_key_id: String,
pub secret_access_key: String,
pub security_token: Option<String>,
}
#[derive(Default)]
#[cfg_attr(test, derive(Debug))]
pub struct CredentialLoader {
config: Config,
credential: Arc<Mutex<Option<Credential>>>,
}
impl CredentialLoader {
pub fn new(config: Config) -> Self {
Self {
config,
credential: Arc::default(),
}
}
pub async fn load(&self) -> Result<Option<Credential>> {
if let Some(cred) = self.credential.lock().expect("lock poisoned").clone() {
return Ok(Some(cred));
}
let cred = self.load_inner().await?;
let mut lock = self.credential.lock().expect("lock poisoned");
*lock = cred.clone();
Ok(cred)
}
async fn load_inner(&self) -> Result<Option<Credential>> {
if let Some(cred) = self.load_via_config()? {
return Ok(Some(cred));
}
Ok(None)
}
fn load_via_config(&self) -> Result<Option<Credential>> {
if let (Some(ak), Some(sk)) = (&self.config.access_key_id, &self.config.secret_access_key) {
let cred = Credential {
access_key_id: ak.clone(),
secret_access_key: sk.clone(),
security_token: self.config.security_token.clone(),
};
return Ok(Some(cred));
}
Ok(None)
}
}