diff --git a/examples/monitoring/src/main.rs b/examples/monitoring/src/main.rs index de81303..d3eb3b8 100644 --- a/examples/monitoring/src/main.rs +++ b/examples/monitoring/src/main.rs @@ -1,6 +1,10 @@ use harmony::{ - inventory::Inventory, maestro::Maestro, - modules::monitoring::{alert_channel::discord_alert_channel::DiscordWebhook, kube_prometheus::helm_prometheus_alert_score::HelmPrometheusAlertingScore}, + inventory::Inventory, + maestro::Maestro, + modules::monitoring::{ + alert_channel::discord_alert_channel::DiscordWebhook, + kube_prometheus::helm_prometheus_alert_score::HelmPrometheusAlertingScore, + }, topology::{K8sAnywhereTopology, Url}, }; @@ -10,7 +14,9 @@ async fn main() { 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 alerting_score = HelmPrometheusAlertingScore { + receivers: vec![Box::new(discord_receiver)], + }; let mut maestro = Maestro::::initialize( Inventory::autoload(), K8sAnywhereTopology::from_env(), @@ -18,12 +24,6 @@ async fn main() { .await .unwrap(); - //let monitoring = MonitoringAlertingScore { - // alert_receivers: vec![], - // alert_rules: vec![], - // scrape_targets: vec![], - //}; - //maestro.register_all(vec![Box::new(monitoring)]); maestro.register_all(vec![Box::new(alerting_score)]); harmony_cli::init(maestro, None).await.unwrap(); } diff --git a/harmony/src/domain/topology/installable.rs b/harmony/src/domain/topology/installable.rs index 9b9054f..0092065 100644 --- a/harmony/src/domain/topology/installable.rs +++ b/harmony/src/domain/topology/installable.rs @@ -2,6 +2,8 @@ use async_trait::async_trait; use crate::interpret::InterpretError; +use super::oberservability::monitoring::AlertSender; + #[async_trait] pub trait Installable { async fn ensure_installed(&self) -> Result<(), InterpretError>; diff --git a/harmony/src/domain/topology/oberservability/monitoring.rs b/harmony/src/domain/topology/oberservability/monitoring.rs index ab71f5b..61e494a 100644 --- a/harmony/src/domain/topology/oberservability/monitoring.rs +++ b/harmony/src/domain/topology/oberservability/monitoring.rs @@ -7,7 +7,11 @@ use crate::{ topology::{Topology, installable::Installable}, }; -pub trait AlertSender: Send + Sync + std::fmt::Debug + Installable {} +#[async_trait] +pub trait AlertSender: Send + Sync + std::fmt::Debug + Installable { + fn name(&self) -> String; + async fn install(&self) -> Result; +} #[derive(Debug)] pub struct AlertingInterpret { @@ -16,7 +20,7 @@ pub struct AlertingInterpret { } #[async_trait] -impl Interpret for AlertingInterpret { +impl Interpret for AlertingInterpret { async fn execute( &self, inventory: &Inventory, @@ -25,7 +29,11 @@ impl Interpret for AlertingInterpret { for receiver in self.receivers.iter() { receiver.install(&self.sender).await?; } - todo!() + self.sender.ensure_installed(); + Ok(Outcome::success(format!( + "successfully installed alert sender {}", + self.sender.name() + ))) } fn get_name(&self) -> InterpretName { @@ -47,7 +55,7 @@ impl Interpret for AlertingInterpret { #[async_trait] pub trait AlertReceiver: std::fmt::Debug + Send + Sync { - async fn install(&self, sender: &S) -> Result<(), InterpretError>; + async fn install(&self, sender: &S) -> Result; fn clone_box(&self) -> Box>; } 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 72a95f5..8fa7523 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use serde_yaml::{Mapping, Value}; use crate::{ - interpret::InterpretError, + interpret::{InterpretError, Outcome}, modules::monitoring::kube_prometheus::{ prometheus::{Prometheus, PrometheusReceiver}, types::AlertChannelConfig, @@ -18,7 +18,7 @@ pub struct DiscordWebhook { #[async_trait] impl AlertReceiver for DiscordWebhook { - async fn install(&self, sender: &Prometheus) -> Result<(), InterpretError> { + async fn install(&self, sender: &Prometheus) -> Result { sender.install_receiver(self).await } fn clone_box(&self) -> Box> { @@ -29,8 +29,11 @@ impl AlertReceiver for DiscordWebhook { #[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) + fn name(&self) -> String { + self.name.clone() + } + async fn receiver_config(&self) -> Value { + self.alert_channel_receiver().await } } diff --git a/harmony/src/modules/monitoring/kube_prometheus/helm/kube_prometheus_helm_chart.rs b/harmony/src/modules/monitoring/kube_prometheus/helm/kube_prometheus_helm_chart.rs index 2377627..e8c2dfa 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/helm/kube_prometheus_helm_chart.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/helm/kube_prometheus_helm_chart.rs @@ -4,9 +4,7 @@ use std::str::FromStr; use crate::modules::helm::chart::HelmChartScore; -pub fn kube_prometheus_helm_chart_score() -> HelmChartScore { - let config = KubePrometheusConfig::new(); - +pub fn kube_prometheus_helm_chart_score(config: KubePrometheusConfig) -> HelmChartScore { //TODO this should be make into a rule with default formatting that can be easily passed as a vec //to the overrides or something leaving the user to deal with formatting here seems bad let default_rules = config.default_rules.to_string(); 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 284f8fb..04853fd 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,9 +1,12 @@ +use std::sync::Mutex; + use serde::Serialize; use crate::{ score::Score, topology::{ HelmCommand, Topology, + installable::Installable, oberservability::monitoring::{AlertReceiver, AlertingInterpret}, }, }; @@ -15,13 +18,16 @@ pub struct HelmPrometheusAlertingScore { pub receivers: Vec>>, } -impl Score for HelmPrometheusAlertingScore { +impl Score for HelmPrometheusAlertingScore { fn create_interpret(&self) -> Box> { Box::new(AlertingInterpret { - sender: Prometheus { config: KubePrometheusConfig::new() }, + sender: Prometheus { + config: Mutex::new(KubePrometheusConfig::new()), + }, receivers: self.receivers.clone(), }) - } fn name(&self) -> String { + } + fn name(&self) -> String { "HelmPrometheusAlertingScore".to_string() } } diff --git a/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs b/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs index de666e3..222245a 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/prometheus.rs @@ -1,15 +1,38 @@ +use std::sync::Mutex; + use async_trait::async_trait; use log::debug; use serde_yaml::Value; use crate::{ - interpret::InterpretError, - topology::{installable::Installable, oberservability::monitoring::AlertSender}, + interpret::{InterpretError, Outcome}, + inventory::Inventory, + score, + topology::{ + HelmCommand, K8sAnywhereTopology, Topology, installable::Installable, + oberservability::monitoring::AlertSender, + }, }; -use super::helm::config::KubePrometheusConfig; +use score::Score; -impl AlertSender for Prometheus {} +use super::helm::{ + config::KubePrometheusConfig, kube_prometheus_helm_chart::kube_prometheus_helm_chart_score, +}; + +#[async_trait] +impl AlertSender for Prometheus { + fn name(&self) -> String { + "HelmKubePrometheus".to_string() + } + async fn install(&self) -> Result { + self.install_prometheus(); + todo!() + } +} + +//im not totally sure what to do in the impl installable +//should we have a oncecell that checks insured is true? #[async_trait] impl Installable for Prometheus { @@ -18,32 +41,63 @@ impl Installable for Prometheus { } } +//before we talked about having a trait installable and a trait installer for the topology +// i feel like that might still be necessary to meet the requirement of inventory and topology on +// the score.create_interpret().execute(inventory, topology) method +#[async_trait] +trait Installer { + async fn install(&self, sender: Box<&dyn Installable>) -> Result<(), InterpretError>; +} + +#[async_trait] +impl Installer for K8sAnywhereTopology { + async fn install(&self, installable: Box<&dyn Installable>) -> Result<(), InterpretError> { + installable.install().await?; + Ok(()) + } +} + #[derive(Debug)] -pub struct Prometheus{ - pub config: KubePrometheusConfig, +pub struct Prometheus { + pub config: Mutex, } impl Prometheus { pub async fn install_receiver( &self, prometheus_receiver: &dyn PrometheusReceiver, - ) -> Result<(), InterpretError> { + ) -> Result { + let prom_receiver = prometheus_receiver.receiver_config().await; + debug!( + "adding alert receiver to prometheus config: {:#?}", + &prom_receiver + ); + let mut config = self.config.lock().unwrap(); - - debug!("adding alert receiver to prometheus config: {:#?}", prometheus_receiver.receiver_config()); - self.config.alert_receiver_configs.push(prometheus_receiver.receiver_config()); - todo!() + config.alert_receiver_configs.push(prom_receiver); + let prom_receiver_name = prometheus_receiver.name(); + debug!("installed alert receiver {}", &prom_receiver_name); + Ok(Outcome::success(format!( + "Sucessfully installed receiver {}", + prom_receiver_name + ))) + } + + pub async fn install_prometheus(&self) -> Result { + kube_prometheus_helm_chart_score(self.config.lock().unwrap().clone()) + .create_interpret() + .execute() + .await } } #[async_trait] -pub trait PrometheusReceiver: Send + Sync + std::fmt::Debug{ - async fn receiver_config(&self) -> (Option, Value, Value); +pub trait PrometheusReceiver: Send + Sync + std::fmt::Debug { + fn name(&self) -> String; + async fn receiver_config(&self) -> Value; //this probably needs to be a type - //that - //represents - //a - //promtheusreceiver + //that + //represents + //a + //promtheusreceiver } - -