Skip to main content

orch/cli/
nodes.rs

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