use std::collections::{HashMap, HashSet};
use duct::cmd;
use lazy_settings::settings;
use eyre::Result;
use gazebo::prelude::SliceExt;
use itertools::Itertools;
use crate::provider::SecretProvider;
#[settings(key = "fly")]
struct FlySettings {
application: String,
}
pub struct FlyProvider {
settings: FlySettings,
}
impl FlyProvider {
pub fn new(instance_name: &str) -> Result<Self> {
Ok(Self {
settings: FlySettings::get(instance_name)?
})
}
}
impl SecretProvider for FlyProvider {
fn get_keys(&self) -> Result<HashSet<String>> {
let secrets_json = cmd!("flyctl", "secrets", "-a", self.settings.application(), "list", "--json").read()?;
let secrets: Vec<HashMap<String, String>> = serde_json::from_str(secrets_json.as_str())?;
let result: Result<HashSet<String>> = secrets.into_iter().map(|m| m.get("Name").cloned().ok_or(eyre::eyre!("Invalid value"))).collect();
Ok(result?)
}
fn get_all(&self) -> Result<HashMap<String, String>> {
todo!()
}
fn set_all(&self, secrets: &HashMap<String, String>) -> Result<()> {
let new_keys: HashSet<String> = secrets.clone().into_keys().collect();
let keys_to_be_removed: Vec<String> = self.get_keys()?.difference(&new_keys).map(|x| x.clone()).collect();
if !keys_to_be_removed.is_empty() {
let mut args = vec!["secrets".to_string(), "-a".to_string(), self.settings.application().to_string(), "unset".to_string()];
args.extend(keys_to_be_removed);
cmd("fly", &args).run()?;
}
let stdin_string = secrets.iter().map(|(k, v)| {
if v.contains("\n") {
format!("{}=\"\"\"{}\"\"\"", k, v)
} else {
format!("{}={}", k, v)
}
}).join("\n");
cmd!("fly", "secrets", "-a", self.settings.application(), "import").stdin_bytes(stdin_string.as_bytes())
.read()?;
Ok(())
}
fn remove_keys(&self) -> Result<()> {
todo!()
}
}
#[cfg(test)]
mod test {
use super::*;
use maplit::hashmap;
#[test]
fn test_fly() {
let settings = FlySettings::get("test").unwrap();
let provider = FlyProvider {
settings
};
dbg!(provider.set_all(&hashmap! {
"a".to_string() => "haha".to_string(),
"b".to_string() => r#"yeah
yeah"#.to_string(),
}).unwrap());
}
}