use std::path::PathBuf;
use clap::Args;
use net_sdk::deck::DaemonSnapshot;
use serde::Serialize;
use crate::context::{resolve_profile, CliContext};
use crate::error::{generic, CliError};
use crate::prelude::{emit_value, OutputFormat};
#[derive(Args, Debug)]
pub struct LsArgs {
#[arg(long)]
pub identity: Option<PathBuf>,
#[arg(long, default_value_t = crate::prelude::DEFAULT_SUPERVISOR_NODE)]
pub node: u64,
}
pub async fn run_ls(
args: LsArgs,
output: Option<OutputFormat>,
config_path: Option<&std::path::Path>,
profile_name: &str,
) -> Result<(), CliError> {
let profile = resolve_profile(config_path, profile_name).await?;
let ctx = CliContext::build(&profile, args.identity.as_deref(), args.node, false).await?;
let snapshot = ctx.deck().status();
let rows: Vec<DaemonRow> = snapshot
.daemons
.iter()
.map(|(id, d)| DaemonRow {
id: *id,
snapshot: d.clone(),
})
.collect();
emit_value(OutputFormat::resolve_oneshot(output), &rows)
.map_err(|e| generic(format!("write daemon ls: {e}")))?;
Ok(())
}
#[derive(Serialize)]
struct DaemonRow {
id: u64,
#[serde(flatten)]
snapshot: DaemonSnapshot,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn daemon_row_id_is_wrapper_field() {
let row = DaemonRow {
id: 0xDEADBEEF,
snapshot: DaemonSnapshot::default(),
};
let v = serde_json::to_value(&row).expect("serialise DaemonRow");
assert_eq!(
v.get("id").and_then(|v| v.as_u64()),
Some(0xDEADBEEF),
"DaemonRow.id must surface as the wrapper's id field; if this fails \
check whether DaemonSnapshot grew an id field that collides with the \
flatten - rename the wrapper field to daemon_id and update consumers"
);
}
}