From 1218705fd52771a902eb6c64762623d0c6a13173 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Fri, 27 Sep 2024 12:16:23 -0500 Subject: refactor: merge Check into Status type --- src/api.rs | 32 ++++++++++---------------------- src/api/services.rs | 6 +++--- src/lib.rs | 16 ++++++++-------- src/service.rs | 10 +++++----- src/service/http.rs | 11 ++++------- src/service/systemd.rs | 20 +++++++++++--------- src/service/tcp.rs | 9 +++------ 7 files changed, 44 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/api.rs b/src/api.rs index e6a91ba..8cf66ea 100644 --- a/src/api.rs +++ b/src/api.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use axum::{extract::State, response::IntoResponse, Json}; use serde::{Deserialize, Serialize}; -use crate::{service::Services, Check, Error, Status}; +use crate::{service::Services, Error, Status}; pub mod services; @@ -19,15 +19,13 @@ pub fn router() -> axum::Router { #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Health { pub status: Status, - pub output: Option, - pub checks: HashMap, + pub checks: HashMap, } impl From for Health { fn from(value: T) -> Self { Health { - status: Status::Fail, - output: Some(value.to_string()), + status: value.into(), ..Default::default() } } @@ -42,30 +40,20 @@ impl IntoResponse for Health { pub async fn healthcheck(State(services): State) -> Health { let checks = match services.check().await { Ok(c) => c, - Err(err) => { - return Health { - status: Status::Fail, - output: Some(err.to_string()), - ..Default::default() - } - } + Err(err) => return err.into(), }; - let (status, output) = match checks + let status = match checks .values() - .filter(|s| !matches!(s.status, Status::Pass)) + .filter(|s| !matches!(s, Status::Pass)) .count() { - 0 => (Status::Pass, None), - 1 => (Status::Fail, Some("1 issue detected".to_string())), - n => (Status::Fail, Some(format!("{n} issues detected"))), + 0 => Status::Pass, + 1 => Status::Fail(Some("1 issue detected".to_string())), + n => Status::Fail(Some(format!("{n} issues detected"))), }; - Health { - status, - output, - checks, - } + Health { status, checks } } pub async fn fallback(uri: axum::http::Uri) -> Error { diff --git a/src/api/services.rs b/src/api/services.rs index 59e891f..63018f1 100644 --- a/src/api/services.rs +++ b/src/api/services.rs @@ -7,7 +7,7 @@ use axum::{ use axum_extra::routing::Resource; use serde::{Deserialize, Serialize}; -use crate::{service::Services, Check, Error, Status}; +use crate::{service::Services, Error, Status}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ServiceQuery { @@ -22,7 +22,7 @@ pub fn router() -> Router { pub async fn index( Query(query): Query, State(services): State, -) -> Result>, Error> { +) -> Result>, Error> { services .check_filtered(|name| (!query.name.as_ref().is_some_and(|s| s != name))) .await @@ -32,7 +32,7 @@ pub async fn index( pub async fn show( Path(name): Path, State(services): State, -) -> Result { +) -> Result { services .check_one(&name) .await diff --git a/src/lib.rs b/src/lib.rs index 2c9fa91..1ccecf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,21 +11,21 @@ pub mod error; pub mod service; #[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] +#[serde(rename_all = "lowercase", tag = "status", content = "output")] pub enum Status { #[default] Pass, - Fail, - Warn, + Fail(Option), + Warn(Option), } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct Check { - pub status: Status, - pub output: Option, +impl From for Status { + fn from(value: T) -> Self { + Status::Fail(Some(value.to_string())) + } } -impl axum::response::IntoResponse for Check { +impl axum::response::IntoResponse for Status { fn into_response(self) -> axum::response::Response { axum::Json(self).into_response() } diff --git a/src/service.rs b/src/service.rs index 677db17..bae6867 100644 --- a/src/service.rs +++ b/src/service.rs @@ -6,7 +6,7 @@ use serde::Deserialize; use systemd::Systemd; use tcp::Tcp; -use crate::{Check, Error}; +use crate::{Error, Status}; pub mod http; pub mod systemd; @@ -33,7 +33,7 @@ impl Services { reqwest::Client::new() } - pub async fn check(&self) -> Result, Error> { + pub async fn check(&self) -> Result, Error> { let checks = self .inner .values() @@ -50,11 +50,11 @@ impl Services { .collect::>()) } - pub async fn check_one(&self, name: &str) -> Option> { + pub async fn check_one(&self, name: &str) -> Option> { Some(self.inner.get(name)?.check(self.client.clone()).await) } - pub async fn check_filtered

(&self, mut predicate: P) -> Result, Error> + pub async fn check_filtered

(&self, mut predicate: P) -> Result, Error> where P: FnMut(&String) -> bool, { @@ -85,7 +85,7 @@ pub enum Service { } impl Service { - pub async fn check(&self, client: reqwest::Client) -> Result { + pub async fn check(&self, client: reqwest::Client) -> Result { match self { Service::Http(http) => http.check(client).await, Service::Tcp(tcp) => tcp.check().await, diff --git a/src/service/http.rs b/src/service/http.rs index 15696a1..fb3ff13 100644 --- a/src/service/http.rs +++ b/src/service/http.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use serde::Deserialize; -use crate::{Check, Error, Status}; +use crate::{Error, Status}; #[derive(Debug, Clone, Deserialize)] pub struct Http { @@ -30,7 +30,7 @@ impl Display for Http { } impl Http { - pub async fn check(&self, client: reqwest::Client) -> Result { + pub async fn check(&self, client: reqwest::Client) -> Result { let status_code = client .request(self.method.parse().map_err(|_| Error::Method)?, &self.url) .send() @@ -39,11 +39,8 @@ impl Http { .as_u16(); match status_code == self.status_code { - true => Ok(Check::default()), - false => Ok(Check { - status: Status::Fail, - output: Some(format!("Status code: {status_code}")), - }), + true => Ok(Status::Pass), + false => Ok(Status::Fail(Some(format!("Status code: {status_code}")))), } } } diff --git a/src/service/systemd.rs b/src/service/systemd.rs index 2e3b74c..45f3bf9 100644 --- a/src/service/systemd.rs +++ b/src/service/systemd.rs @@ -2,7 +2,7 @@ use std::{fmt::Display, process::Command}; use serde::Deserialize; -use crate::{Check, Error, Status}; +use crate::{Error, Status}; #[derive(Debug, Clone, Deserialize)] pub struct Systemd { @@ -16,18 +16,20 @@ impl Display for Systemd { } impl Systemd { - pub async fn check(&self) -> Result { + pub async fn check(&self) -> Result { let output = Command::new("systemctl") .arg("is-active") .arg(&self.service) .output()?; - let stdout = String::from_utf8_lossy(&output.stdout).to_string(); - Ok((!output.status.success()) - .then(|| Check { - status: Status::Fail, - output: Some(format!("Service state: {}", stdout.trim())), - }) - .unwrap_or_default()) + let status = match output.status.success() { + true => Status::Pass, + false => { + let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); + Status::Fail(Some(format!("Service state: {}", stdout))) + } + }; + + Ok(status) } } diff --git a/src/service/tcp.rs b/src/service/tcp.rs index 5f55091..87e696a 100644 --- a/src/service/tcp.rs +++ b/src/service/tcp.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use serde::Deserialize; -use crate::{Check, Error, Status}; +use crate::{Error, Status}; #[derive(Debug, Clone, Deserialize)] pub struct Tcp { @@ -16,13 +16,10 @@ impl Display for Tcp { } impl Tcp { - pub async fn check(&self) -> Result { + pub async fn check(&self) -> Result { Ok(std::net::TcpStream::connect(&self.address) .err() - .map(|err| Check { - status: Status::Fail, - output: Some(format!("error: {err}")), - }) + .map(Into::into) .unwrap_or_default()) } } -- cgit v1.2.3-70-g09d2