From cc46f73720a22f4b401feb57ef4f37ee5468d85a Mon Sep 17 00:00:00 2001 From: Codekloeppler Date: Sat, 9 Aug 2025 22:13:26 +0200 Subject: [PATCH] Add healthcheck w/o credentials to stalwart-cli (#1880) * Add healthcheck w/o credentials to stalwart-cli * Rename enum Response variant The HealthcheckStatus identifier is not as generic, as it should be. The Response data format, generated by the function `into_http_response()` for `JsonProblemResponse` * Aktualisieren von database.rs * Healthcheck with direct call --- crates/cli/src/main.rs | 22 ++++++++++++++-------- crates/cli/src/modules/cli.rs | 9 +++++++++ crates/cli/src/modules/database.rs | 27 ++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 3e4e0d02..7da83432 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -43,14 +43,20 @@ async fn main() -> std::io::Result<()> { } else if let Ok(credentials) = std::env::var("CREDENTIALS") { parse_credentials(&credentials) } else { - let credentials = rpassword::prompt_password( - "\nEnter administrator credentials or press [ENTER] to use OAuth: ", - ) - .unwrap(); - if !credentials.is_empty() { + if args.anonymous { + let credentials = "anonymous:".to_string(); parse_credentials(&credentials) } else { - oauth(&url).await + let credentials = rpassword::prompt_password( + "\nEnter administrator credentials or press [ENTER] to use OAuth: ", + ) + .unwrap(); + + if !credentials.is_empty() { + parse_credentials(&credentials) + } else { + oauth(&url).await + } } }, timeout: args.timeout, @@ -172,7 +178,7 @@ async fn oauth(url: &str) -> Credentials { #[serde(untagged)] pub enum Response { Error(ManagementApiError), - Data { data: T }, + Data { data: T } } #[derive(Deserialize)] @@ -281,7 +287,7 @@ impl Client { Response::Error(error) => { eprintln!("Request failed: {error})"); std::process::exit(1); - } + }, } } } diff --git a/crates/cli/src/modules/cli.rs b/crates/cli/src/modules/cli.rs index 82413591..ef1808f2 100644 --- a/crates/cli/src/modules/cli.rs +++ b/crates/cli/src/modules/cli.rs @@ -25,6 +25,9 @@ pub struct Cli { /// Connection timeout in seconds #[clap(short, long)] pub timeout: Option, + /// Do not ask for credentials + #[clap(short, long)] + pub anonymous: bool, } #[derive(Subcommand)] @@ -450,6 +453,12 @@ pub enum ServerCommands { /// Prefix to filter configuration entries by prefix: Option, }, + + /// Perform Healthcheck + Healthcheck { + /// Status `ready` (default) or `live` to check for + check: Option + }, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] diff --git a/crates/cli/src/modules/database.rs b/crates/cli/src/modules/database.rs index 59c99a44..dd7fdc02 100644 --- a/crates/cli/src/modules/database.rs +++ b/crates/cli/src/modules/database.rs @@ -5,12 +5,11 @@ */ use std::collections::HashMap; - use prettytable::{Attr, Cell, Row, Table}; -use reqwest::Method; +use reqwest::{Method, StatusCode}; use serde_json::Value; -use crate::modules::Response; +use crate::modules::{Response, UnwrapResult}; use super::cli::{Client, ServerCommands}; @@ -112,6 +111,28 @@ impl ServerCommands { if results.len() == 1 { "" } else { "s" } ); } + ServerCommands::Healthcheck { check } => { + let response = reqwest::get( + format!("{}/healthz/{}", + client.url, + check.unwrap_or("ready".to_string())) + ) + .await + .unwrap(); + + match response.status() { + StatusCode::OK => { + eprintln!("Success") + }, + _ => { + eprintln!( + "Request failed: {}", + response.text().await.unwrap_result("fetch text") + ); + std::process::exit(1); + } + } + } } } }