1use std::collections::BTreeSet;23use anyhow::{ensure, Result};4use clap::Parser;5use nix_eval::nix_go_json;67use crate::host::Config;89#[derive(Parser)]10pub struct Info {11 #[clap(long)]12 json: bool,13 #[clap(subcommand)]14 cmd: InfoCmd,15}1617#[derive(Parser)]18pub enum InfoCmd {19 20 ListHosts {21 #[clap(long)]22 tagged: Vec<String>,23 },24 25 HostIps {26 host: String,27 #[clap(long)]28 external: bool,29 #[clap(long)]30 internal: bool,31 },32}3334impl Info {35 pub async fn run(self, config: &Config) -> Result<()> {36 let mut data = Vec::new();37 match self.cmd {38 InfoCmd::ListHosts { ref tagged } => {39 'host: for host in config.list_hosts().await? {40 if !tagged.is_empty() {41 let config = &config.config_unchecked_field;42 let tags: Vec<String> =43 nix_go_json!(config.hosts[{ host.name }].nixosSystem.config.tags);44 for tag in tagged {45 if !tags.contains(tag) {46 continue 'host;47 }48 }49 }50 data.push(host.name);51 }52 }53 InfoCmd::HostIps {54 host,55 external,56 internal,57 } => {58 ensure!(59 external || internal,60 "at leas one of --external or --internal must be set"61 );62 let mut out = <BTreeSet<String>>::new();63 let host = config.system_config(&host).await?;64 if external {65 let data: Vec<String> = nix_go_json!(host.network.externalIps);66 out.extend(data);67 }68 if internal {69 let data: Vec<String> = nix_go_json!(host.network.internalIps);70 out.extend(data);71 }72 for ip in out {73 data.push(ip);74 }75 }76 }7778 if self.json {79 let v = serde_json::to_string_pretty(&data)?;80 print!("{}", v);81 } else {82 for v in data {83 println!("{}", v);84 }85 }86 Ok(())87 }88}