diff --git a/examples/monitoring/Cargo.toml b/examples/monitoring/Cargo.toml index af42491..d188b78 100644 --- a/examples/monitoring/Cargo.toml +++ b/examples/monitoring/Cargo.toml @@ -9,3 +9,4 @@ license.workspace = true harmony = { version = "0.1.0", path = "../../harmony" } harmony_cli = { version = "0.1.0", path = "../../harmony_cli" } tokio.workspace = true +url.workspace = true diff --git a/examples/monitoring/src/main.rs b/examples/monitoring/src/main.rs index d52c649..de81303 100644 --- a/examples/monitoring/src/main.rs +++ b/examples/monitoring/src/main.rs @@ -1,12 +1,16 @@ use harmony::{ inventory::Inventory, maestro::Maestro, - modules::monitoring::kube_prometheus::helm_prometheus_alert_score::HelmPrometheusAlertingScore, - topology::K8sAnywhereTopology, + modules::monitoring::{alert_channel::discord_alert_channel::DiscordWebhook, kube_prometheus::helm_prometheus_alert_score::HelmPrometheusAlertingScore}, + topology::{K8sAnywhereTopology, Url}, }; #[tokio::main] async fn main() { - let alerting_score = HelmPrometheusAlertingScore { receivers: vec![] }; + let discord_receiver = DiscordWebhook { + name: "test-discord".to_string(), + url: Url::Url(url::Url::parse("https://discord.i.dont.exist.com").unwrap()), + }; + let alerting_score = HelmPrometheusAlertingScore { receivers: vec![Box::new(discord_receiver)] }; let mut maestro = Maestro::::initialize( Inventory::autoload(), K8sAnywhereTopology::from_env(), diff --git a/harmony/src/domain/topology/oberservability/monitoring.rs b/harmony/src/domain/topology/oberservability/monitoring.rs index a3a6164..ab71f5b 100644 --- a/harmony/src/domain/topology/oberservability/monitoring.rs +++ b/harmony/src/domain/topology/oberservability/monitoring.rs @@ -48,6 +48,7 @@ impl Interpret for AlertingInterpret { #[async_trait] pub trait AlertReceiver: std::fmt::Debug + Send + Sync { async fn install(&self, sender: &S) -> Result<(), InterpretError>; + fn clone_box(&self) -> Box>; } #[async_trait] diff --git a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs index 10f4d72..72a95f5 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -10,7 +10,7 @@ use crate::{ topology::{Url, oberservability::monitoring::AlertReceiver}, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct DiscordWebhook { pub name: String, pub url: Url, @@ -19,16 +19,28 @@ pub struct DiscordWebhook { #[async_trait] impl AlertReceiver for DiscordWebhook { async fn install(&self, sender: &Prometheus) -> Result<(), InterpretError> { - sender.install_receiver(PrometheusReceiver {}).await + sender.install_receiver(self).await + } + fn clone_box(&self) -> Box> { + Box::new(self.clone()) } } +#[async_trait] +impl PrometheusReceiver for DiscordWebhook { + //TODO not return a tuple + async fn receiver_config(&self) -> (Option, Value, Value) { + (self.alert_channel_global_config().await, self.alert_channel_receiver().await, self.alert_channel_route().await) + } +} + +#[async_trait] impl AlertChannelConfig for DiscordWebhook { - fn alert_channel_global_config(&self) -> Option { + async fn alert_channel_global_config(&self) -> Option { None } - fn alert_channel_route(&self) -> serde_yaml::Value { + async fn alert_channel_route(&self) -> serde_yaml::Value { let mut route = Mapping::new(); route.insert( Value::String("receiver".to_string()), @@ -42,7 +54,7 @@ impl AlertChannelConfig for DiscordWebhook { Value::Mapping(route) } - fn alert_channel_receiver(&self) -> serde_yaml::Value { + async fn alert_channel_receiver(&self) -> serde_yaml::Value { let mut receiver = Mapping::new(); receiver.insert( Value::String("name".to_string()), @@ -66,8 +78,6 @@ impl AlertChannelConfig for DiscordWebhook { #[cfg(test)] mod tests { - use log::debug; - use super::*; #[test] @@ -77,18 +87,14 @@ mod tests { url: Url::Url(url::Url::parse("https://discord.i.dont.exist.com").unwrap()), }; - let discord_receiver_global = - serde_yaml::to_string(&discord_receiver.alert_channel_global_config()).unwrap(); - println!("global receiver \n{:#}", discord_receiver_global); - let discord_receiver_global_yaml = "".to_string(); - let discord_receiver_receiver = serde_yaml::to_string(&discord_receiver.alert_channel_receiver()).unwrap(); println!("receiver \n{:#}", discord_receiver_receiver); let discord_receiver_receiver_yaml = r#"name: test-discord discord_configs: -- webhook_url: https://discord.i.dont.exist.com/"# - .to_string(); +- webhook_url: https://discord.i.dont.exist.com/ +"# + .to_string(); let discord_receiver_route = serde_yaml::to_string(&discord_receiver.alert_channel_route()).unwrap(); @@ -96,8 +102,9 @@ discord_configs: let discord_receiver_route_yaml = r#"receiver: test-discord matchers: - alertname!=Watchdog -continue: true"# - .to_string(); +continue: true +"# + .to_string(); assert_eq!(discord_receiver_receiver, discord_receiver_receiver_yaml); assert_eq!(discord_receiver_route, discord_receiver_route_yaml); diff --git a/harmony/src/modules/monitoring/kube_prometheus/helm/config.rs b/harmony/src/modules/monitoring/kube_prometheus/helm/config.rs index 0e62c0f..39d449f 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/helm/config.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/helm/config.rs @@ -1,4 +1,7 @@ use serde::Serialize; +use serde_yaml::Value; + +use crate::modules::monitoring::kube_prometheus::prometheus::PrometheusReceiver; #[derive(Debug, Clone, Serialize)] pub struct KubePrometheusConfig { @@ -19,6 +22,7 @@ pub struct KubePrometheusConfig { pub kube_proxy: bool, pub kube_state_metrics: bool, pub prometheus_operator: bool, + pub alert_receiver_configs: Vec, } impl KubePrometheusConfig { pub fn new() -> Self { @@ -40,6 +44,7 @@ impl KubePrometheusConfig { prometheus_operator: true, core_dns: false, kube_scheduler: false, + alert_receiver_configs: vec![], } } } diff --git a/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs b/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs index 3cfd447..284f8fb 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs @@ -1,7 +1,6 @@ use serde::Serialize; use crate::{ - modules::monitoring::alert_channel::discord_alert_channel::DiscordWebhook, score::Score, topology::{ HelmCommand, Topology, @@ -9,7 +8,7 @@ use crate::{ }, }; -use super::prometheus::Prometheus; +use super::{helm::config::KubePrometheusConfig, prometheus::Prometheus}; #[derive(Clone, Debug, Serialize)] pub struct HelmPrometheusAlertingScore { @@ -19,12 +18,10 @@ pub struct HelmPrometheusAlertingScore { impl Score for HelmPrometheusAlertingScore { fn create_interpret(&self) -> Box> { Box::new(AlertingInterpret { - sender: Prometheus {}, + sender: Prometheus { config: KubePrometheusConfig::new() }, receivers: self.receivers.clone(), }) - } - - fn name(&self) -> String { + } fn name(&self) -> String { "HelmPrometheusAlertingScore".to_string() } } @@ -37,8 +34,9 @@ impl Serialize for Box> { todo!() } } + impl Clone for Box> { fn clone(&self) -> Self { - todo!() + self.clone_box() } } diff --git a/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs b/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs index c5be07e..de666e3 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs @@ -1,10 +1,14 @@ use async_trait::async_trait; +use log::debug; +use serde_yaml::Value; use crate::{ interpret::InterpretError, topology::{installable::Installable, oberservability::monitoring::AlertSender}, }; +use super::helm::config::KubePrometheusConfig; + impl AlertSender for Prometheus {} #[async_trait] @@ -13,22 +17,33 @@ impl Installable for Prometheus { todo!() } } + #[derive(Debug)] -pub struct Prometheus; +pub struct Prometheus{ + pub config: KubePrometheusConfig, +} impl Prometheus { pub async fn install_receiver( &self, - prometheus_receiver: PrometheusReceiver, + prometheus_receiver: &dyn PrometheusReceiver, ) -> Result<(), InterpretError> { + + + debug!("adding alert receiver to prometheus config: {:#?}", prometheus_receiver.receiver_config()); + self.config.alert_receiver_configs.push(prometheus_receiver.receiver_config()); todo!() } } -pub struct PrometheusReceiver {} - -impl PrometheusReceiver { - fn get_prometheus_receiver_config(&self) {} +#[async_trait] +pub trait PrometheusReceiver: Send + Sync + std::fmt::Debug{ + async fn receiver_config(&self) -> (Option, Value, Value); + //this probably needs to be a type + //that + //represents + //a + //promtheusreceiver } -pub struct AlertChannelGlobalConfig {} + diff --git a/harmony/src/modules/monitoring/kube_prometheus/types.rs b/harmony/src/modules/monitoring/kube_prometheus/types.rs index 08d1b7d..d6f28d2 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/types.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/types.rs @@ -1,7 +1,9 @@ +use async_trait::async_trait; use serde_yaml::Value; +#[async_trait] pub trait AlertChannelConfig { - fn alert_channel_global_config(&self) -> Option; - fn alert_channel_route(&self) -> Value; - fn alert_channel_receiver(&self) -> Value; + async fn alert_channel_global_config(&self) -> Option; + async fn alert_channel_route(&self) -> Value; + async fn alert_channel_receiver(&self) -> Value; }