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