use std::{collections::BTreeMap, path::Path}; use figment::{ Figment, Provider, providers::{Format, Serialized, Toml}, util::map, value::Map, }; use gethostname::gethostname; use serde_derive::{Deserialize, Serialize}; use serde_with::{DurationSeconds, serde_as}; #[derive(Serialize, Deserialize, Clone)] pub struct InfluxConfig { pub enabled: bool, pub url: String, pub org: String, pub bucket: String, pub token: String, pub tags: Map, } impl Default for InfluxConfig { fn default() -> Self { let host = gethostname().into_string().unwrap(); InfluxConfig { enabled: false, url: "http://localhost:8086".into(), org: "default".into(), bucket: "default".into(), token: "".into(), tags: map! { "host".into() => host }, } } } #[serde_as] #[derive(Serialize, Deserialize, Clone)] #[serde(default)] pub struct ChronyConfig { pub enabled: bool, #[serde_as(as = "DurationSeconds")] pub timeout: std::time::Duration, #[serde_as(as = "DurationSeconds")] pub tracking_interval: std::time::Duration, #[serde_as(as = "DurationSeconds")] pub sources_interval: std::time::Duration, pub measurement_prefix: String, pub tracking_measurement: String, pub sources_measurement: String, pub host: String, } impl Default for ChronyConfig { fn default() -> Self { ChronyConfig { enabled: false, timeout: std::time::Duration::from_secs(5), tracking_interval: std::time::Duration::from_secs(60), sources_interval: std::time::Duration::from_secs(300), measurement_prefix: "chrony.".into(), tracking_measurement: "tracking".into(), sources_measurement: "sources".into(), host: "127.0.0.1:323".into(), } } } #[derive(Serialize, Deserialize, Clone)] #[serde(default)] pub struct ChronySockConfig { pub enabled: bool, pub sock: String, } impl Default for ChronySockConfig { fn default() -> Self { ChronySockConfig { enabled: false, sock: "".into(), } } } #[derive(Serialize, Deserialize, Clone, Debug)] pub struct HwmonSensorConfig { pub device: String, pub sensor: String, } #[serde_as] #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(default)] pub struct HwmonConfig { pub enabled: bool, #[serde_as(as = "DurationSeconds")] pub interval: std::time::Duration, pub measurement: String, pub sensors: Map, } impl Default for HwmonConfig { fn default() -> Self { HwmonConfig { enabled: false, interval: std::time::Duration::from_secs(60), measurement: "hwmon".into(), sensors: map! {}, } } } #[serde_as] #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(default)] pub struct GpsdConfig { pub enabled: bool, #[serde_as(as = "DurationSeconds")] pub interval: std::time::Duration, pub host: String, } impl Default for GpsdConfig { fn default() -> Self { GpsdConfig { enabled: false, interval: std::time::Duration::from_secs(60), host: "localhost:2947".into(), } } } #[serde_as] #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(default)] pub struct Prs10Config { pub enabled: bool, pub port: String, pub baud: u32, #[serde_as(as = "DurationSeconds")] pub timeout: std::time::Duration, #[serde_as(as = "DurationSeconds")] pub status_interval: std::time::Duration, #[serde_as(as = "DurationSeconds")] pub stats_interval: std::time::Duration, } impl Default for Prs10Config { fn default() -> Self { Prs10Config { enabled: false, port: "/dev/ttyS0".into(), baud: 9600, timeout: std::time::Duration::from_secs(1), status_interval: std::time::Duration::from_secs(10), stats_interval: std::time::Duration::from_secs(30), } } } #[serde_as] #[derive(Serialize, Deserialize, Clone)] #[serde(default)] pub struct UCCMConfig { pub enabled: bool, pub port: String, pub baud: u32, #[serde_as(as = "DurationSeconds")] pub status_interval: std::time::Duration, #[serde_as(as = "DurationSeconds")] pub timeout: std::time::Duration, pub measurement: String, } impl Default for UCCMConfig { fn default() -> Self { UCCMConfig { enabled: false, port: "/dev/ttyS0".into(), baud: 57600, status_interval: std::time::Duration::from_secs(10), timeout: std::time::Duration::from_secs(1), measurement: "uccm_gpsdo".into(), } } } #[derive(Serialize, Deserialize, Clone)] #[serde(tag = "type", rename_all = "snake_case")] pub enum SourceConfig { Chrony(ChronyConfig), Hwmon(HwmonConfig), Uccm(UCCMConfig), Gpsd(GpsdConfig), Prs10(Prs10Config), } #[derive(Serialize, Deserialize, Clone)] #[serde(tag = "type", rename_all = "snake_case")] pub enum TargetConfig { ChronySock(ChronySockConfig), InfluxDb(InfluxConfig), } #[derive(Serialize, Deserialize, Clone, Default)] pub struct Config { pub influxdb: InfluxConfig, pub sources: BTreeMap, pub targets: BTreeMap, } impl Provider for Config { fn metadata(&self) -> figment::Metadata { figment::Metadata::named("Default config") } fn data(&self) -> Result, figment::Error> { Serialized::defaults(Config::default()).data() } }