From 9fe8d9f6e585616db6718d37af409b4d55225567 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 18 Apr 2026 03:48:56 +0000 Subject: [PATCH] feat: fleet secret list subcommand --- --- a/cmds/fleet/src/cmds/secrets.rs +++ b/cmds/fleet/src/cmds/secrets.rs @@ -137,42 +137,57 @@ bail!("failed to find suitable decrypting host"); } Secret::List {} => { - /* - let _span = info_span!("loading secrets").entered(); - let configured = config.list_configured_shared()?; - #[derive(Tabled)] - struct SecretDisplay { + let secrets = config.data.secrets.read().expect("not poisoned"); + + #[derive(tabled::Tabled)] + struct Row { #[tabled(rename = "Name")] name: String, + #[tabled(rename = "Dist")] + dist: String, #[tabled(rename = "Owners")] owners: String, } - // let mut table = vec![]; - for name in configured.iter().cloned() { - let config = config.clone(); - let data = config.shared_secret(&name).expect("exists"); - /* - let definition = config.shared_secret_definition(&name)?; - let expectations = definition.expectations()?; - let owners = data - .owners() - .map(|o| { - if expectations.owners.contains(o) { - o.green().to_string() - } else { - o.red().to_string() - } - }) - .collect::>(); - table.push(SecretDisplay { - owners: owners.join(", "), - name, - }) - */ + + let mut rows = Vec::new(); + for name in secrets.keys() { + let dists = secrets.get(name).unwrap(); + for (idx, dist) in dists.all_distributions().enumerate() { + let active: Vec<_> = dist + .owners() + .filter_map(|o| o.as_host()) + .map(str::to_owned) + .collect(); + let pruned: Vec<_> = dist + .owners_pending_prune() + .filter_map(|o| o.as_host()) + .map(|h| format!("{h} (pruned)")) + .collect(); + let mut all_owners = active; + all_owners.extend(pruned); + + let dist_label = if dist.is_pending_prune() { + format!("{idx} (pruned)") + } else { + idx.to_string() + }; + + rows.push(Row { + name: if idx == 0 { + name.clone() + } else { + String::new() + }, + dist: dist_label, + owners: all_owners.join("\n"), + }); + } } - // info!("loaded\n{}", Table::new(table).to_string()) - */ - todo!() + + use tabled::settings::{Style, width::Width}; + let mut table = tabled::Table::new(rows); + table.with(Width::wrap(80)); + println!("{table}"); } Secret::Prune { name, --- a/crates/fleet-base/src/fleetdata.rs +++ b/crates/fleet-base/src/fleetdata.rs @@ -218,6 +218,12 @@ pub fn owners(&self) -> impl Iterator { self.owners_ex(false) } + pub fn owners_pending_prune(&self) -> impl Iterator { + self.owners_pending_prune.keys() + } + pub fn is_pending_prune(&self) -> bool { + self.pending_prune.is_some() + } pub fn prune(&mut self, reason: String) { assert!( @@ -466,6 +472,9 @@ } } + pub fn all_distributions(&self) -> impl Iterator { + self.stored.iter() + } pub fn distributions(&self) -> impl Iterator { self.stored.iter().filter(|v| v.pending_prune.is_none()) } -- gitstuff