mirror of
https://github.com/pcvolkmer/checkbar.git
synced 2025-04-19 19:16:50 +00:00
Extract checks into modules
This commit is contained in:
parent
774a843005
commit
1d7b163035
45
src/checker/actuator.rs
Normal file
45
src/checker/actuator.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::checker::{CheckResult, CheckState};
|
||||||
|
use crate::config::CheckConfig;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct ActuatorResponse {
|
||||||
|
status: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Checker<'a> {
|
||||||
|
check_config: &'a CheckConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Checker<'_> {
|
||||||
|
pub fn new(check_config: &CheckConfig) -> Checker {
|
||||||
|
Checker { check_config }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check(&self) -> CheckResult {
|
||||||
|
let state = match reqwest::get(self.check_config.url.as_str()).await {
|
||||||
|
Ok(r) => {
|
||||||
|
if r.status().is_success() {
|
||||||
|
match r.json::<ActuatorResponse>().await {
|
||||||
|
Ok(ar) => {
|
||||||
|
if ar.status == "UP" {
|
||||||
|
CheckState::Up
|
||||||
|
} else {
|
||||||
|
CheckState::Warn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => CheckState::Warn,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CheckState::Warn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => CheckState::Down,
|
||||||
|
};
|
||||||
|
|
||||||
|
CheckResult {
|
||||||
|
name: self.check_config.name.to_string(),
|
||||||
|
state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/checker/http.rs
Normal file
30
src/checker/http.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::checker::{CheckResult, CheckState};
|
||||||
|
use crate::config::CheckConfig;
|
||||||
|
|
||||||
|
pub struct Checker<'a> {
|
||||||
|
check_config: &'a CheckConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Checker<'_> {
|
||||||
|
pub fn new(check_config: &CheckConfig) -> Checker {
|
||||||
|
Checker { check_config }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check(&self) -> CheckResult {
|
||||||
|
let state = match reqwest::get(self.check_config.url.as_str()).await {
|
||||||
|
Ok(r) => {
|
||||||
|
if r.status().is_success() {
|
||||||
|
CheckState::Up
|
||||||
|
} else {
|
||||||
|
CheckState::Warn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => CheckState::Down,
|
||||||
|
};
|
||||||
|
|
||||||
|
CheckResult {
|
||||||
|
name: self.check_config.name.to_string(),
|
||||||
|
state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
src/checker/mod.rs
Normal file
51
src/checker/mod.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
mod actuator;
|
||||||
|
mod http;
|
||||||
|
mod tcp;
|
||||||
|
|
||||||
|
pub use crate::checker::actuator::Checker as ActuatorChecker;
|
||||||
|
pub use crate::checker::http::Checker as HttpChecker;
|
||||||
|
pub use crate::checker::tcp::Checker as TcpChecker;
|
||||||
|
use crate::config;
|
||||||
|
use crate::config::get_config;
|
||||||
|
use serde_json::json;
|
||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
|
||||||
|
pub struct CheckResult {
|
||||||
|
pub name: String,
|
||||||
|
pub state: CheckState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CheckResult {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
|
let color_config = match get_config().colors {
|
||||||
|
Some(color_config) => color_config,
|
||||||
|
None => config::ColorConfig {
|
||||||
|
up: String::from("#00FF00"),
|
||||||
|
warn: String::from("#FFFF00"),
|
||||||
|
down: String::from("#FF0000"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let color = match &self.state {
|
||||||
|
CheckState::Up => color_config.up,
|
||||||
|
CheckState::Warn => color_config.warn,
|
||||||
|
CheckState::Down => color_config.down,
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
json!({
|
||||||
|
"full_text": self.name,
|
||||||
|
"name": self.name,
|
||||||
|
"separator_block_width": 16,
|
||||||
|
"color": color
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CheckState {
|
||||||
|
Up,
|
||||||
|
Warn,
|
||||||
|
Down,
|
||||||
|
}
|
43
src/checker/tcp.rs
Normal file
43
src/checker/tcp.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use reqwest::Url;
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
|
use crate::checker::{CheckResult, CheckState};
|
||||||
|
use crate::config::CheckConfig;
|
||||||
|
|
||||||
|
pub struct Checker<'a> {
|
||||||
|
check_config: &'a CheckConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Checker<'_> {
|
||||||
|
pub fn new(check_config: &CheckConfig) -> Checker {
|
||||||
|
Checker { check_config }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check(&self) -> CheckResult {
|
||||||
|
if let Ok(url) = Url::from_str(self.check_config.url.as_str()) {
|
||||||
|
if url.scheme() == "tcp" && url.host_str().is_some() && url.port().is_some() {
|
||||||
|
let state = match TcpStream::connect(format!(
|
||||||
|
"{}:{}",
|
||||||
|
url.host_str().unwrap(),
|
||||||
|
url.port().unwrap()
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => CheckState::Up,
|
||||||
|
_ => CheckState::Down,
|
||||||
|
};
|
||||||
|
return CheckResult {
|
||||||
|
name: self.check_config.name.to_string(),
|
||||||
|
state,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckResult {
|
||||||
|
name: self.check_config.name.to_string(),
|
||||||
|
state: CheckState::Down,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
src/config.rs
Normal file
59
src/config.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use std::{env, fs};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub interval: Option<u64>,
|
||||||
|
pub colors: Option<ColorConfig>,
|
||||||
|
pub checks: Vec<CheckConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ColorConfig {
|
||||||
|
pub up: String,
|
||||||
|
pub warn: String,
|
||||||
|
pub down: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct CheckConfig {
|
||||||
|
pub name: String,
|
||||||
|
pub url: String,
|
||||||
|
pub check_type: Option<CheckType>,
|
||||||
|
pub click_cmd: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum CheckType {
|
||||||
|
Http,
|
||||||
|
Actuator,
|
||||||
|
Tcp,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config_file() -> String {
|
||||||
|
match env::args().nth(1) {
|
||||||
|
Some(config_file) => config_file,
|
||||||
|
None => format!(
|
||||||
|
"{}/.checkbar.toml",
|
||||||
|
dirs::home_dir().unwrap().to_str().unwrap_or("")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_config() -> Config {
|
||||||
|
match fs::read_to_string(get_config_file()) {
|
||||||
|
Ok(config) => match toml::from_str(config.as_str()) {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(_e) => Config {
|
||||||
|
interval: None,
|
||||||
|
colors: None,
|
||||||
|
checks: vec![],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Err(_) => Config {
|
||||||
|
interval: None,
|
||||||
|
colors: None,
|
||||||
|
checks: vec![],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
173
src/main.rs
173
src/main.rs
@ -1,48 +1,15 @@
|
|||||||
use reqwest::Url;
|
mod checker;
|
||||||
|
mod config;
|
||||||
|
|
||||||
|
use std::process;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::env;
|
|
||||||
use std::fmt::{Display, Formatter, Result};
|
|
||||||
use std::fs;
|
|
||||||
use std::process;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
use crate::checker::{ActuatorChecker, CheckResult, HttpChecker, TcpChecker};
|
||||||
struct Config {
|
use crate::config::{get_config, CheckConfig, CheckType};
|
||||||
interval: Option<u64>,
|
|
||||||
colors: Option<ColorConfig>,
|
|
||||||
checks: Vec<CheckConfig>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct ColorConfig {
|
|
||||||
up: String,
|
|
||||||
warn: String,
|
|
||||||
down: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct CheckConfig {
|
|
||||||
name: String,
|
|
||||||
url: String,
|
|
||||||
check_type: Option<CheckType>,
|
|
||||||
click_cmd: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq)]
|
|
||||||
enum CheckType {
|
|
||||||
Http,
|
|
||||||
Actuator,
|
|
||||||
Tcp,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct ActuatorResponse {
|
|
||||||
status: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ClickEvent {
|
struct ClickEvent {
|
||||||
@ -50,101 +17,11 @@ struct ClickEvent {
|
|||||||
button: u8,
|
button: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CheckResult {
|
|
||||||
name: String,
|
|
||||||
state: CheckState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CheckResult {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
|
||||||
let color_config = match get_config().colors {
|
|
||||||
Some(color_config) => color_config,
|
|
||||||
None => ColorConfig {
|
|
||||||
up: String::from("#00FF00"),
|
|
||||||
warn: String::from("#FFFF00"),
|
|
||||||
down: String::from("#FF0000"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let color = match &self.state {
|
|
||||||
CheckState::Up => color_config.up,
|
|
||||||
CheckState::Warn => color_config.warn,
|
|
||||||
CheckState::Down => color_config.down,
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
json!({
|
|
||||||
"full_text": self.name,
|
|
||||||
"name": self.name,
|
|
||||||
"separator_block_width": 16,
|
|
||||||
"color": color
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CheckState {
|
|
||||||
Up,
|
|
||||||
Warn,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn check_host(check_config: &CheckConfig) -> CheckResult {
|
async fn check_host(check_config: &CheckConfig) -> CheckResult {
|
||||||
if check_config.check_type == Some(CheckType::Tcp) {
|
|
||||||
if let Ok(url) = Url::from_str(check_config.url.as_str()) {
|
|
||||||
if url.scheme() == "tcp" {
|
|
||||||
if url.host_str().is_some() && url.port().is_some() {
|
|
||||||
let state = match TcpStream::connect(format!(
|
|
||||||
"{}:{}",
|
|
||||||
url.host_str().unwrap(),
|
|
||||||
url.port().unwrap()
|
|
||||||
))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => CheckState::Up,
|
|
||||||
_ => CheckState::Down,
|
|
||||||
};
|
|
||||||
return CheckResult {
|
|
||||||
name: check_config.name.to_string(),
|
|
||||||
state,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CheckResult {
|
|
||||||
name: check_config.name.to_string(),
|
|
||||||
state: CheckState::Down,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let state = match reqwest::get(check_config.url.as_str()).await {
|
|
||||||
Ok(r) => {
|
|
||||||
if r.status().is_success() {
|
|
||||||
match check_config.check_type {
|
match check_config.check_type {
|
||||||
Some(CheckType::Actuator) => match r.json::<ActuatorResponse>().await {
|
Some(CheckType::Actuator) => ActuatorChecker::new(check_config).check().await,
|
||||||
Ok(ar) => {
|
Some(CheckType::Tcp) => TcpChecker::new(check_config).check().await,
|
||||||
if ar.status == "UP" {
|
_ => HttpChecker::new(check_config).check().await,
|
||||||
CheckState::Up
|
|
||||||
} else {
|
|
||||||
CheckState::Warn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => CheckState::Warn,
|
|
||||||
},
|
|
||||||
// Default: HTTP
|
|
||||||
_ => CheckState::Up,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CheckState::Warn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => CheckState::Down,
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult {
|
|
||||||
name: check_config.name.to_string(),
|
|
||||||
state,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,34 +40,6 @@ async fn print_states(check_configs: &[CheckConfig]) {
|
|||||||
println!("{}],", entries.join(","));
|
println!("{}],", entries.join(","));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config_file() -> String {
|
|
||||||
match env::args().nth(1) {
|
|
||||||
Some(config_file) => config_file,
|
|
||||||
None => format!(
|
|
||||||
"{}/.checkbar.toml",
|
|
||||||
dirs::home_dir().unwrap().to_str().unwrap_or("")
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_config() -> Config {
|
|
||||||
match fs::read_to_string(get_config_file()) {
|
|
||||||
Ok(config) => match toml::from_str(config.as_str()) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err(_e) => Config {
|
|
||||||
interval: None,
|
|
||||||
colors: None,
|
|
||||||
checks: vec![],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Err(_) => Config {
|
|
||||||
interval: None,
|
|
||||||
colors: None,
|
|
||||||
checks: vec![],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_click_cmd(name: String) -> Option<String> {
|
async fn get_click_cmd(name: String) -> Option<String> {
|
||||||
for check in get_config().checks {
|
for check in get_config().checks {
|
||||||
if check.name == name {
|
if check.name == name {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user