chore!: refactor config file format

There are substructs for the different parts of the config now, as a
preparation of a larger refactor coming in.

BREAKING CHANGE: config file format changed
This commit is contained in:
Jan Christian Grünhage 2022-03-17 00:12:51 +01:00
parent 576f5728a4
commit 1c1a31dbec
5 changed files with 49 additions and 15 deletions

3
Cargo.lock generated
View file

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ansi_term"
version = "0.11.0"
@ -352,6 +354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
"serde",
]
[[package]]

View file

@ -17,7 +17,7 @@ futures = "0.3"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "time"] }
clap = "2"
fern = "0.6"
log = "0.4"
log = { version = "0.4", features = ["serde"] }
chrono = "0.4"
serde = { version = "1", features = ["derive"] }
tokio-icmp-echo = "0.4"

View file

@ -6,6 +6,11 @@ listener = "[::]:9898"
# The format here is `"host" = interval in milliseconds`, so these examples
# will ping the primary and secondary IP of cloudflare's 1.1.1.1 DNS service
# every 500ms, or twice per second.
[hosts]
[ping.hosts]
"1.1.1.1" = 500
"1.0.0.1" = 500
# Configure logging is also possible here instead of using the CLI. If both are
# specified, the more verbose of the two will be used.
# [log]
# level = "ERROR"

View file

@ -20,15 +20,35 @@
use anyhow::{Context, Result};
use clap::{clap_app, crate_authors, crate_description, crate_name, crate_version};
use log::info;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Clone)]
#[derive(Deserialize, Clone)]
pub(crate) struct Config {
pub(crate) listener: std::net::SocketAddr,
pub(crate) ping: PingConfig,
#[serde(default)]
pub(crate) log: LogConfig,
}
#[derive(Deserialize, Clone)]
pub(crate) struct PingConfig {
pub(crate) hosts: HashMap<std::net::IpAddr, u64>,
}
#[derive(Deserialize, Clone)]
pub(crate) struct LogConfig {
pub(crate) level: log::LevelFilter,
}
impl Default for LogConfig {
fn default() -> Self {
Self {
level: log::LevelFilter::Error,
}
}
}
fn setup_clap() -> clap::ArgMatches<'static> {
clap_app!(myapp =>
(name: crate_name!())
@ -42,14 +62,7 @@ fn setup_clap() -> clap::ArgMatches<'static> {
.get_matches()
}
fn setup_fern(level: u64) {
let level = match level {
0 => log::LevelFilter::Error,
1 => log::LevelFilter::Warn,
2 => log::LevelFilter::Info,
3 => log::LevelFilter::Debug,
_ => log::LevelFilter::Trace,
};
fn setup_fern(level: log::LevelFilter) {
match fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
@ -77,9 +90,22 @@ fn read_config(path: &str) -> Result<Config> {
pub(crate) fn setup_app() -> Result<Config> {
let clap = setup_clap();
setup_fern(clap.occurrences_of("v"));
let config_path = clap
.value_of("config")
.context("Got no config file. clap should've catched this")?;
Ok(read_config(config_path).context("Couldn't read config file!")?)
let config = read_config(config_path).context("Couldn't read config file!")?;
setup_fern(determine_level(clap.occurrences_of("v"), config.log.level));
Ok(config)
}
fn determine_level(verbose_occurrences: u64, config_level: log::LevelFilter) -> log::LevelFilter {
let cli_level = match verbose_occurrences {
0 => log::LevelFilter::Error,
1 => log::LevelFilter::Warn,
2 => log::LevelFilter::Info,
3 => log::LevelFilter::Debug,
_ => log::LevelFilter::Trace,
};
Ord::max(cli_level, config_level)
}

View file

@ -44,7 +44,7 @@ lazy_static! {
pub(crate) async fn start_pinging_hosts(config: &Config) -> Result<()> {
let pinger = Pinger::new().await.context("Couldn't create pinger")?;
let mut handles = vec![];
for (host, interval) in config.hosts.clone() {
for (host, interval) in config.ping.hosts.clone() {
info!("Spawn ping task for {}", host);
handles.push(tokio::spawn(ping_host(pinger.clone(), host, interval)));
}