use anyhow::{Context, Result};
use clap::Parser;
use wasmcloud_control_interface::{Host, HostInventory};
use crate::{
common::{boxed_err_to_anyhow, get_all_inventories},
config::WashConnectionOptions,
id::ServerId,
};
use super::CliConnectionOpts;
#[derive(Debug, Clone, Parser)]
pub struct GetClaimsCommand {
#[clap(flatten)]
pub opts: CliConnectionOpts,
}
#[derive(Debug, Clone, Parser)]
pub struct GetHostInventoriesCommand {
#[clap(flatten)]
pub opts: CliConnectionOpts,
#[clap(name = "host-id", value_parser)]
pub host_id: Option<ServerId>,
#[clap(long, num_args = 0..=1, default_missing_value = "5000", value_parser = parse_watch_interval)]
pub watch: Option<std::time::Duration>,
}
#[derive(Debug, Clone, Parser)]
pub struct GetLinksCommand {
#[clap(flatten)]
pub opts: CliConnectionOpts,
}
#[derive(Debug, Clone, Parser)]
pub struct GetHostsCommand {
#[clap(flatten)]
pub opts: CliConnectionOpts,
}
#[derive(Debug, Clone, Parser)]
pub enum GetCommand {
#[clap(name = "links")]
Links(GetLinksCommand),
#[clap(name = "claims")]
Claims(GetClaimsCommand),
#[clap(name = "hosts")]
Hosts(GetHostsCommand),
#[clap(name = "inventory", alias = "inventories")]
HostInventories(GetHostInventoriesCommand),
}
pub async fn get_host_inventories(cmd: GetHostInventoriesCommand) -> Result<Vec<HostInventory>> {
let wco: WashConnectionOptions = cmd.opts.try_into()?;
let client = wco.into_ctl_client(None).await?;
if let Some(host_id) = cmd.host_id {
if let Some(inventory) = client
.get_host_inventory(&host_id)
.await
.map(|inventory| inventory.response)
.map_err(boxed_err_to_anyhow)?
{
Ok(vec![inventory])
} else {
Ok(vec![])
}
} else {
let hosts = get_all_inventories(&client)
.await
.context("unable to fetch all inventory")?;
match hosts.len() {
0 => Err(anyhow::anyhow!(
"No hosts are available for inventory query."
)),
_ => Ok(hosts),
}
}
}
pub async fn get_hosts(cmd: GetHostsCommand) -> Result<Vec<Host>> {
let wco: WashConnectionOptions = cmd.opts.try_into()?;
let client = wco.into_ctl_client(None).await?;
client
.get_hosts()
.await
.map_err(boxed_err_to_anyhow)
.map(|hosts| {
hosts
.into_iter()
.filter_map(|h| h.response)
.collect::<Vec<_>>()
})
.context("Was able to connect to NATS, but failed to get hosts.")
}
fn parse_watch_interval(arg: &str) -> Result<std::time::Duration, std::num::ParseIntError> {
let milis = arg.parse::<u64>()?;
Ok(std::time::Duration::from_millis(milis))
}