Skip to main content

orch/cli/
nodes.rs

1use crate::cluster::{discovery, local};
2
3/// The cluster's members as this machine's service sees them
4pub async fn run() -> anyhow::Result<()> {
5    if !crate::cluster::enabled() {
6        println!("orch runs on this machine only: the config has no cluster section");
7        return Ok(());
8    }
9
10    let Some(endpoint) = local::daemon_endpoint().await else {
11        anyhow::bail!("the orch service is not running");
12    };
13    let members = local::fetch_nodes(&endpoint).await?;
14    let tailnet = discovery::status().await.ok();
15    let name_of = |addr: &str| {
16        let ip = addr.split(':').next().unwrap_or_default();
17        tailnet
18            .as_ref()
19            .and_then(|t| {
20                std::iter::once(&t.me)
21                    .chain(&t.peers)
22                    .find(|h| h.ip == ip)
23                    .map(|h| (h.name.clone(), h.online))
24            })
25            .unwrap_or_else(|| (ip.to_string(), true))
26    };
27    println!("{:<20} {:<22} {:<8} STATE", "NODE", "ADDRESS", "ROLE");
28    for m in members {
29        let (name, online) = name_of(&m.addr);
30        let role = if m.voter { "voter" } else { "learner" };
31        let mut state = Vec::new();
32        if m.leader {
33            state.push("leader");
34        }
35        if m.me {
36            state.push("this machine");
37        }
38        if !online {
39            state.push("offline");
40        }
41        println!("{name:<20} {:<22} {role:<8} {}", m.addr, state.join(", "));
42    }
43
44    Ok(())
45}