From 12012916b7eeb8e2d62db4d48a30a2b50d9d884d Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 1 May 2026 20:51:49 +0200 Subject: [PATCH] simplify the `garage health` subcommand --- src/garage/cli/remote/cluster.rs | 50 ++++++++++++++------------------ src/garage/cli/remote/mod.rs | 7 ++--- src/garage/cli/structs.rs | 12 ++++---- src/garage/main.rs | 1 - 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/garage/cli/remote/cluster.rs b/src/garage/cli/remote/cluster.rs index fe54a0e4..ff533289 100644 --- a/src/garage/cli/remote/cluster.rs +++ b/src/garage/cli/remote/cluster.rs @@ -9,37 +9,29 @@ use crate::cli::remote::*; use crate::cli::structs::*; impl Cli { - pub async fn cmd_health_check(&self, quiet: bool) -> Result<(), Error> { - let status = self.api_request(GetClusterStatusRequest).await?; + pub async fn cmd_health(&self, quiet: bool) -> Result<(), Error> { + let health = self.api_request(GetClusterHealthRequest).await?; - let mut result = Err(Error::Message( - "Failed to find node id in configuration".into(), - )); - - if let Some(config) = &self.config { - let local_node_id = hex::encode( - garage_rpc::system::read_node_id(&config.metadata_dir) - .err_context(crate::cli::local::init::READ_KEY_ERROR)? - ).to_string(); - result = Err(Error::Message("Cluster is not healthy".into())); - - for node in status.nodes.iter() { - if node.id == local_node_id { - result = Ok(()) - } - } - if !quiet { - match result { - Ok(_) => { - println!("Healthy"); - } - Err(_) => { - println!("Not healthy"); - } - } - } + if !quiet { + let table = vec![ + format!("Cluster health:\t{}", health.status.to_uppercase()), + format!("Known nodes:\t{}", health.known_nodes), + format!("Connected nodes:\t{}", health.connected_nodes), + format!("Storage nodes:\t{}", health.storage_nodes), + format!("Storage nodes up:\t{}", health.storage_nodes_up), + format!("Partitions:\t{}", health.partitions), + format!("Partitions with quorum:\t{}", health.partitions_quorum), + format!("Fully healthy partitions:\t{}", health.partitions_all_ok), + ]; + format_table(table); + } + + match health.status.as_str() { + "unavailable" => Err(Error::Message( + "Cluster is currently unavailable".to_string(), + )), + _ => Ok(()), } - result } pub async fn cmd_status(&self) -> Result<(), Error> { diff --git a/src/garage/cli/remote/mod.rs b/src/garage/cli/remote/mod.rs index 56077c23..a30b5c1a 100644 --- a/src/garage/cli/remote/mod.rs +++ b/src/garage/cli/remote/mod.rs @@ -18,23 +18,22 @@ use garage_util::error::*; use garage_rpc::*; -use crate::cli::structs::*; use garage_api_admin::api::*; use garage_api_admin::api_server::{AdminRpc as ProxyRpc, AdminRpcResponse as ProxyRpcResponse}; use garage_api_admin::RequestHandler; -use garage_util::config::Config; + +use crate::cli::structs::*; pub struct Cli { pub proxy_rpc_endpoint: Arc>, pub rpc_host: NodeID, - pub config: Option, } impl Cli { pub async fn handle(&self, cmd: Command) -> Result<(), Error> { match cmd { Command::Status => self.cmd_status().await, - Command::HealthCheck(opt) => self.cmd_health_check(opt.quiet).await, + Command::Health(opt) => self.cmd_health(opt.quiet).await, Command::Node(NodeOperation::Connect(connect_opt)) => { self.cmd_connect(connect_opt).await } diff --git a/src/garage/cli/structs.rs b/src/garage/cli/structs.rs index bde0cc13..368581cb 100644 --- a/src/garage/cli/structs.rs +++ b/src/garage/cli/structs.rs @@ -10,14 +10,14 @@ pub enum Command { #[structopt(name = "server", version = garage_version())] Server(ServerOpt), + /// Check the cluster health and set the exit code to 1 if it is unavailable + #[structopt(name = "health", version = garage_version())] + Health(HealthOpt), + /// Get network status #[structopt(name = "status", version = garage_version())] Status, - /// Check the local node health and set the exit code to 1 if it is unhealthy. - #[structopt(name = "health-check", version = garage_version())] - HealthCheck(HealthCheckOpt), - /// Operations on individual Garage nodes #[structopt(name = "node", version = garage_version())] Node(NodeOperation), @@ -108,11 +108,11 @@ pub struct ServerOpt { } // ------------------------- -// ---- garage health-check ... ---- +// ---- garage health ---- // ------------------------- #[derive(StructOpt, Debug)] -pub struct HealthCheckOpt { +pub struct HealthOpt { /// Do not print healthyness to stdout #[structopt(short = "q", long = "quiet")] pub(crate) quiet: bool, diff --git a/src/garage/main.rs b/src/garage/main.rs index f3f1422c..62d10c82 100644 --- a/src/garage/main.rs +++ b/src/garage/main.rs @@ -351,7 +351,6 @@ async fn cli_command(opt: Opt) -> Result<(), Error> { let cli = cli::remote::Cli { proxy_rpc_endpoint, rpc_host: id, - config: config, }; cli.handle(opt.cmd).await