Skip to main content

nomad_cli/
client.rs

1use serde::Deserialize;
2
3#[derive(Deserialize)]
4pub struct Envelope {
5    pub success: bool,
6    pub data: serde_json::Value,
7    pub error: Option<String>,
8    pub meta: Option<Meta>,
9}
10
11#[derive(Deserialize)]
12pub struct Meta {
13    pub duration_ms: Option<f64>,
14    pub daemon_rss_kb: Option<u64>,
15    pub daemon_uptime_secs: Option<u64>,
16    pub daemon_connections: Option<u32>,
17}
18
19pub fn daemon_alive(port: u16) -> bool {
20    let url = format!("http://127.0.0.1:{}/api/health", port);
21    reqwest::blocking::get(&url).is_ok()
22}
23
24pub fn health(port: u16, json_output: bool) -> Result<(), Box<dyn std::error::Error>> {
25    let url = format!("http://127.0.0.1:{}/api/health", port);
26    match reqwest::blocking::get(&url) {
27        Ok(resp) => {
28            if let Ok(e) = resp.json::<Envelope>() {
29                if e.success {
30                    let d = &e.data;
31                    let pid = d.get("pid").and_then(|v| v.as_u64()).unwrap_or(0);
32                    let rss = d.get("rss_kb").and_then(|v| v.as_u64()).unwrap_or(0);
33                    let uptime = d.get("uptime_secs").and_then(|v| v.as_u64()).unwrap_or(0);
34                    let conns = d.get("connections").and_then(|v| v.as_u64()).unwrap_or(0);
35                    let ver = d.get("version").and_then(|v| v.as_str()).unwrap_or("?");
36                    if json_output {
37                        println!("{}", serde_json::to_string_pretty(&e.data)?);
38                    } else {
39                        let rss_mb = rss as f64 / 1024.0;
40                        let (uptime_str, _) = format_duration(uptime);
41                        println!(" ● nomad-daemon: RUNNING");
42                        println!("   PID:    {pid}");
43                        println!("   Port:   {port}");
44                        println!("   RSS:    {rss_mb:.1} MB");
45                        println!("   Uptime: {uptime_str}");
46                        println!("   Conns:  {conns}");
47                        println!("   Ver:    {ver}");
48                    }
49                } else {
50                    let err = e.error.unwrap_or_else(|| "unknown".into());
51                    if json_output {
52                        println!(r#"{{"running":false,"error":"{err}"}}"#);
53                    } else {
54                        println!(" ● nomad-daemon: ERROR  {err}");
55                    }
56                }
57            }
58        }
59        Err(_) => {
60            if json_output {
61                println!(r#"{{"running":false}}"#);
62            } else {
63                println!(" ● nomad-daemon: STOPPED. Start with: nom daemon start");
64            }
65        }
66    }
67    Ok(())
68}
69
70fn format_duration(secs: u64) -> (String, u64) {
71    let h = secs / 3600;
72    let m = (secs % 3600) / 60;
73    let s = secs % 60;
74    if h > 0 {
75        (format!("{h}h {m}m"), secs)
76    } else if m > 0 {
77        (format!("{m}m {s}s"), secs)
78    } else {
79        (format!("{s}s"), secs)
80    }
81}