use anyhow::Context; use directories_next::ProjectDirs; use log::debug; use std::path::{Path, PathBuf}; use structopt::StructOpt; use vmadm::cmd; use vmadm::config::Configuration; use vmadm::spec::Specification; const QUALIFIER: &str = ""; const ORG: &str = ""; const APP: &str = "vmadm"; #[derive(StructOpt, Debug)] struct Cli { #[structopt(subcommand)] cmd: Command, } #[derive(StructOpt, Debug)] enum Command { New { #[structopt(flatten)] common: CommonOptions, #[structopt(parse(from_os_str))] spec: PathBuf, }, List { #[structopt(flatten)] common: CommonOptions, }, Delete { #[structopt(flatten)] common: CommonOptions, #[structopt(parse(from_os_str))] spec: PathBuf, }, CloudInit { #[structopt(flatten)] common: CommonOptions, #[structopt(parse(from_os_str))] spec: PathBuf, #[structopt(parse(from_os_str))] dirname: PathBuf, }, } #[derive(StructOpt, Debug)] struct CommonOptions { #[structopt(short, long, parse(from_os_str))] config: Option, } fn main() -> anyhow::Result<()> { pretty_env_logger::init_custom_env("VMADM_LOG"); let cli = Cli::from_args(); debug!("{:#?}", cli); match cli.cmd { Command::New { common, spec } => { let specs = get_specs(&common, &spec)?; cmd::new(&specs)?; } Command::List { common } => { let config = config(&common)?; cmd::list(&config)?; } Command::Delete { common, spec } => { let specs = get_specs(&common, &spec)?; cmd::delete(&specs)?; } Command::CloudInit { common, spec, dirname, } => { let specs = get_specs(&common, &spec)?; cmd::cloud_init(&specs, &dirname)?; } } Ok(()) } fn get_specs(common: &CommonOptions, spec: &Path) -> anyhow::Result> { let config = config(&common)?; let specs = Specification::from_file(&config, &spec)?; Ok(specs) } fn config(common: &CommonOptions) -> anyhow::Result { let filename = config_filename(common); let config = Configuration::from_file(&filename) .with_context(|| format!("reading configuration file {}", filename.display()))?; Ok(config) } fn config_filename(common: &CommonOptions) -> PathBuf { if let Some(ref filename) = common.config { filename.to_path_buf() } else { if let Some(dirs) = ProjectDirs::from(QUALIFIER, ORG, APP) { dirs.config_dir().join("config.yaml") } else { PathBuf::from("xxx") } } }