--- /dev/null +++ b/cmds/fleet/src/cmds/info.rs @@ -0,0 +1,81 @@ +use std::collections::BTreeSet; + +use crate::host::Config; +use anyhow::{ensure, Result}; +use structopt::StructOpt; + +#[derive(StructOpt)] +pub struct Info { + #[structopt(long)] + json: bool, + #[structopt(subcommand)] + cmd: InfoCmd, +} + +#[derive(StructOpt)] +pub enum InfoCmd { + /// List hosts + ListHosts { + #[structopt(long)] + tagged: Vec, + }, + /// List ips + HostIps { + host: String, + #[structopt(long)] + external: bool, + #[structopt(long)] + internal: bool, + }, +} + +impl Info { + pub fn run(self, config: &Config) -> Result<()> { + let mut data = Vec::new(); + match self.cmd { + InfoCmd::ListHosts { ref tagged } => { + 'host: for host in config.list_hosts()? { + if !tagged.is_empty() { + let tags: Vec = config.config_attr(&host, "tags")?; + for tag in tagged { + if !tags.contains(&tag) { + continue 'host; + } + } + } + data.push(host); + } + } + InfoCmd::HostIps { + host, + external, + internal, + } => { + ensure!( + external || internal, + "at leas one of --external or --internal must be set" + ); + let mut out = >::new(); + if external { + out.extend(config.config_attr::>(&host, "network.externalIps")?); + } + if internal { + out.extend(config.config_attr::>(&host, "network.internalIps")?); + } + for ip in out { + data.push(ip); + } + } + } + + if self.json { + let v = serde_json::to_string_pretty(&data)?; + print!("{}", v); + } else { + for v in data { + println!("{}", v); + } + } + Ok(()) + } +} --- a/cmds/fleet/src/cmds/mod.rs +++ b/cmds/fleet/src/cmds/mod.rs @@ -1,2 +1,3 @@ pub mod build_systems; pub mod secrets; +pub mod info; --- a/cmds/fleet/src/host.rs +++ b/cmds/fleet/src/host.rs @@ -9,6 +9,7 @@ }; use anyhow::Result; +use serde::de::DeserializeOwned; use structopt::clap::ArgGroup; use structopt::StructOpt; @@ -80,6 +81,17 @@ .inherit_stdio() .run_json() } + pub fn config_attr(&self, host: &str, attr: &str) -> Result { + Command::new("nix") + .arg("eval") + .arg(self.full_attr_name(&format!( + "fleetConfigurations.default.configuredSystems.{}.config.{}", + host, attr + ))) + .args(&["--json", "--show-trace"]) + .inherit_stdio() + .run_json() + } pub fn data(&self) -> Ref { self.data.borrow() --- a/cmds/fleet/src/main.rs +++ b/cmds/fleet/src/main.rs @@ -11,7 +11,7 @@ use structopt::clap::AppSettings::*; use structopt::StructOpt; -use cmds::{build_systems::BuildSystems, secrets::Secrets}; +use cmds::{build_systems::BuildSystems, info::Info, secrets::Secrets}; use host::{Config, FleetOpts}; #[derive(StructOpt)] @@ -20,6 +20,8 @@ BuildSystems(BuildSystems), /// Secret management Secrets(Secrets), + /// Config parsing + Info(Info), } #[derive(StructOpt)] @@ -40,6 +42,7 @@ match command { Opts::BuildSystems(c) => c.run(config)?, Opts::Secrets(s) => s.run(config)?, + Opts::Info(i) => i.run(config)?, }; Ok(()) }