difftreelog
feat fleet secret list subcommand
in: trunk
2 files changed
cmds/fleet/src/cmds/secrets.rsdiffbeforeafterboth--- 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::<Vec<_>>();
- 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,
crates/fleet-base/src/fleetdata.rsdiffbeforeafterboth218 pub fn owners(&self) -> impl Iterator<Item = &SecretOwner> {218 pub fn owners(&self) -> impl Iterator<Item = &SecretOwner> {219 self.owners_ex(false)219 self.owners_ex(false)220 }220 }221 pub fn owners_pending_prune(&self) -> impl Iterator<Item = &SecretOwner> {222 self.owners_pending_prune.keys()223 }224 pub fn is_pending_prune(&self) -> bool {225 self.pending_prune.is_some()226 }221227222 pub fn prune(&mut self, reason: String) {228 pub fn prune(&mut self, reason: String) {223 assert!(229 assert!(466 }472 }467 }473 }468474475 pub fn all_distributions(&self) -> impl Iterator<Item = &FleetSecretDistribution> {476 self.stored.iter()477 }469 pub fn distributions(&self) -> impl Iterator<Item = &FleetSecretDistribution> {478 pub fn distributions(&self) -> impl Iterator<Item = &FleetSecretDistribution> {470 self.stored.iter().filter(|v| v.pending_prune.is_none())479 self.stored.iter().filter(|v| v.pending_prune.is_none())471 }480 }