diff --git a/examples/monitoring/Cargo.toml b/examples/monitoring/Cargo.toml new file mode 100644 index 0000000..5eee2fe --- /dev/null +++ b/examples/monitoring/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "webhook_sender" +edition = "2024" +version.workspace = true +readme.workspace = true +license.workspace = true + +[dependencies] +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 new file mode 100644 index 0000000..1f553fa --- /dev/null +++ b/examples/monitoring/src/main.rs @@ -0,0 +1,23 @@ +use harmony::{ + inventory::Inventory, + maestro::Maestro, + modules::monitoring::monitoring_alerting::MonitoringAlertingScore, + topology::{K8sAnywhereTopology, oberservability::K8sMonitorConfig}, +}; + +#[tokio::main] +async fn main() { + let mut maestro = Maestro::::initialize( + Inventory::autoload(), + K8sAnywhereTopology::new(), + ) + .await + .unwrap(); + + let monitoring = MonitoringAlertingScore { + alert_channel_configs: None, + }; + + maestro.register_all(vec![Box::new(monitoring)]); + harmony_cli::init(maestro, None).await.unwrap(); +} diff --git a/harmony/src/domain/topology/k8s_anywhere.rs b/harmony/src/domain/topology/k8s_anywhere.rs index 785a606..8888dd9 100644 --- a/harmony/src/domain/topology/k8s_anywhere.rs +++ b/harmony/src/domain/topology/k8s_anywhere.rs @@ -10,7 +10,10 @@ use crate::{ interpret::{InterpretError, Outcome}, inventory::Inventory, maestro::Maestro, - modules::{k3d::K3DInstallationScore, monitoring::kube_prometheus::kube_prometheus_helm_chart_score::kube_prometheus_helm_chart_score}, + modules::{ + k3d::K3DInstallationScore, + monitoring::kube_prometheus::kube_prometheus_helm_chart_score::kube_prometheus_helm_chart_score, + }, topology::LocalhostTopology, }; @@ -193,9 +196,7 @@ impl K8sAnywhereTopology { self.k8s_monitor .get_or_try_init(async || -> Result { - let config = K8sMonitorConfig { - chart: kube_prometheus_helm_chart_score(), - }; + let config = K8sMonitorConfig::cluster_monitor(); Ok(K8sMonitor { config }) }) .await @@ -302,12 +303,14 @@ impl TenantManager for K8sAnywhereTopology { } #[async_trait] impl Monitor for K8sAnywhereTopology { - async fn provision_monitor( + async fn provision_monitor( &self, + inventory: &Inventory, + topology: &T, alert_receivers: Option>>, ) -> Result { self.get_k8s_monitor()? - .provision_monitor(alert_receivers) + .provision_monitor(inventory, topology, alert_receivers) .await } diff --git a/harmony/src/domain/topology/oberservability/k8s.rs b/harmony/src/domain/topology/oberservability/k8s.rs index 2640358..004f9ec 100644 --- a/harmony/src/domain/topology/oberservability/k8s.rs +++ b/harmony/src/domain/topology/oberservability/k8s.rs @@ -3,14 +3,13 @@ use std::sync::Arc; use async_trait::async_trait; use serde::Serialize; +use crate::score::Score; + +use crate::topology::HelmCommand; use crate::{ interpret::{InterpretError, Outcome}, inventory::Inventory, - modules::{helm::chart::HelmChartInterpret, monitoring::kube_prometheus::{ - config::KubePrometheusConfig, - kube_prometheus_helm_chart_score::kube_prometheus_helm_chart_score, - }}, - topology::{K8sAnywhereTopology, Topology}, + topology::Topology, }; use super::{ @@ -25,19 +24,23 @@ pub struct K8sMonitor { #[async_trait] impl Monitor for K8sMonitor { - async fn provision_monitor( + async fn provision_monitor( &self, - alert_receivers: Option>>, + inventory: &Inventory, + topology: &T, + alert_channels: Option>>, ) -> Result { - if let Some(receivers) = alert_receivers { - let alert_channels = self.build_alert_channels(receivers).await?; + if let Some(channels) = alert_channels { + let alert_channels = self.build_alert_channels(channels).await?; for channel in alert_channels { channel.register_alert_channel().await?; } } let chart = self.config.chart.clone(); - // - chart.create_interpret(); + chart + .create_interpret() + .execute(inventory, topology) + .await?; Ok(Outcome::success("installed monitor".to_string())) } diff --git a/harmony/src/domain/topology/oberservability/mod.rs b/harmony/src/domain/topology/oberservability/mod.rs index 05c7f20..387709a 100644 --- a/harmony/src/domain/topology/oberservability/mod.rs +++ b/harmony/src/domain/topology/oberservability/mod.rs @@ -1,12 +1,23 @@ use serde::Serialize; -use crate::modules::helm::chart::HelmChartScore; +use crate::modules::{ + helm::chart::HelmChartScore, + monitoring::kube_prometheus::kube_prometheus_helm_chart_score::kube_prometheus_helm_chart_score, +}; -pub mod monitoring; pub mod k8s; +pub mod monitoring; #[derive(Debug, Clone, Serialize)] pub struct K8sMonitorConfig { //probably need to do something better here pub chart: HelmChartScore, } + +impl K8sMonitorConfig { + pub fn cluster_monitor() -> Self { + Self { + chart: kube_prometheus_helm_chart_score(), + } + } +} diff --git a/harmony/src/domain/topology/oberservability/monitoring.rs b/harmony/src/domain/topology/oberservability/monitoring.rs index d8b81d0..1d6a159 100644 --- a/harmony/src/domain/topology/oberservability/monitoring.rs +++ b/harmony/src/domain/topology/oberservability/monitoring.rs @@ -1,13 +1,12 @@ use async_trait::async_trait; use dyn_clone::DynClone; -use serde::Serialize; use std::fmt::Debug; -use std::sync::Arc; use crate::executors::ExecutorError; use crate::interpret::InterpretError; use crate::inventory::Inventory; +use crate::topology::HelmCommand; use crate::{interpret::Outcome, topology::Topology}; /// Represents an entity responsible for collecting and organizing observability data @@ -16,8 +15,10 @@ use crate::{interpret::Outcome, topology::Topology}; /// monitoring data, enabling consistent processing regardless of the underlying data source. #[async_trait] pub trait Monitor { - async fn provision_monitor( + async fn provision_monitor( &self, + inventory: &Inventory, + topology: &T, alert_receivers: Option>>, ) -> Result; 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 397cab9..76a6498 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -1,7 +1,5 @@ use url::Url; - - #[derive(Debug, Clone)] pub struct DiscordWebhookAlertChannel { pub webhook_url: Url, diff --git a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs index ac24c4a..fa9eb47 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs @@ -160,67 +160,65 @@ prometheus: repository: None, } } - // let alertmanager_config = alert_manager_yaml_builder(&config); - // values.push_str(&alertmanager_config); - // - // fn alert_manager_yaml_builder(config: &KubePrometheusConfig) -> String { - // let mut receivers = String::new(); - // let mut routes = String::new(); - // let mut global_configs = String::new(); - // let alert_manager = config.alert_manager; - // for alert_channel in &config.alert_channel { - // match alert_channel { - // AlertChannel::Discord { name, .. } => { - // let (receiver, route) = discord_alert_builder(name); - // info!("discord receiver: {} \nroute: {}", receiver, route); - // receivers.push_str(&receiver); - // routes.push_str(&route); - // } - // AlertChannel::Slack { - // slack_channel, - // webhook_url, - // } => { - // let (receiver, route) = slack_alert_builder(slack_channel); - // info!("slack receiver: {} \nroute: {}", receiver, route); - // receivers.push_str(&receiver); - // - // routes.push_str(&route); - // let global_config = format!( - // r#" - // global: - // slack_api_url: {webhook_url}"# - // ); - // - // global_configs.push_str(&global_config); - // } - // AlertChannel::Smpt { .. } => todo!(), - // } - // } - // info!("after alert receiver: {}", receivers); - // info!("after alert routes: {}", routes); - // - // let alertmanager_config = format!( - // r#" - //alertmanager: - // enabled: {alert_manager} - // config: {global_configs} - // route: - // group_by: ['job'] - // group_wait: 30s - // group_interval: 5m - // repeat_interval: 12h - // routes: - //{routes} - // receivers: - // - name: 'null' - //{receivers}"# - // ); - // - // info!("alert manager config: {}", alertmanager_config); - // alertmanager_config - // } - - +// let alertmanager_config = alert_manager_yaml_builder(&config); +// values.push_str(&alertmanager_config); +// +// fn alert_manager_yaml_builder(config: &KubePrometheusConfig) -> String { +// let mut receivers = String::new(); +// let mut routes = String::new(); +// let mut global_configs = String::new(); +// let alert_manager = config.alert_manager; +// for alert_channel in &config.alert_channel { +// match alert_channel { +// AlertChannel::Discord { name, .. } => { +// let (receiver, route) = discord_alert_builder(name); +// info!("discord receiver: {} \nroute: {}", receiver, route); +// receivers.push_str(&receiver); +// routes.push_str(&route); +// } +// AlertChannel::Slack { +// slack_channel, +// webhook_url, +// } => { +// let (receiver, route) = slack_alert_builder(slack_channel); +// info!("slack receiver: {} \nroute: {}", receiver, route); +// receivers.push_str(&receiver); +// +// routes.push_str(&route); +// let global_config = format!( +// r#" +// global: +// slack_api_url: {webhook_url}"# +// ); +// +// global_configs.push_str(&global_config); +// } +// AlertChannel::Smpt { .. } => todo!(), +// } +// } +// info!("after alert receiver: {}", receivers); +// info!("after alert routes: {}", routes); +// +// let alertmanager_config = format!( +// r#" +//alertmanager: +// enabled: {alert_manager} +// config: {global_configs} +// route: +// group_by: ['job'] +// group_wait: 30s +// group_interval: 5m +// repeat_interval: 12h +// routes: +//{routes} +// receivers: +// - name: 'null' +//{receivers}"# +// ); +// +// info!("alert manager config: {}", alertmanager_config); +// alertmanager_config +// } //fn discord_alert_builder(release_name: &String) -> (String, String) { // let discord_receiver_name = format!("Discord-{}", release_name); @@ -234,7 +232,7 @@ prometheus: // let route = format!( // r#" // - receiver: '{discord_receiver_name}' -// matchers: +// matchers: // - alertname!=Watchdog // continue: true"#, // ); @@ -255,7 +253,7 @@ prometheus: // let route = format!( // r#" // - receiver: '{slack_receiver_name}' -// matchers: +// matchers: // - alertname!=Watchdog // continue: true"#, // ); diff --git a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_monitor.rs b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_monitor.rs index 4cd2c8c..f66ab8a 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_monitor.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_monitor.rs @@ -77,11 +77,9 @@ // } //} - //#[async_trait] //pub trait PrometheusAlertChannel { // fn get_alert_channel_global_settings(&self) -> Option; // fn get_alert_channel_route(&self) -> AlertManagerChannelRoute; // fn get_alert_channel_receiver(&self) -> AlertManagerChannelReceiver; //} - diff --git a/harmony/src/modules/monitoring/monitoring_alerting.rs b/harmony/src/modules/monitoring/monitoring_alerting.rs index 5fe18a0..d4fcecb 100644 --- a/harmony/src/modules/monitoring/monitoring_alerting.rs +++ b/harmony/src/modules/monitoring/monitoring_alerting.rs @@ -1,11 +1,16 @@ use async_trait::async_trait; -use serde::{Serialize, Serializer, ser::SerializeStruct}; -use std::{fmt::Debug, sync::Arc}; - -use crate::{data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::Inventory, score::Score, topology::{ - oberservability::monitoring::{AlertChannelConfig, Monitor},HelmCommand, Topology - }}; +use serde::Serialize; +use crate::{ + data::{Id, Version}, + interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + inventory::Inventory, + score::Score, + topology::{ + HelmCommand, Topology, + oberservability::monitoring::{AlertChannelConfig, Monitor}, + }, +}; #[derive(Debug, Clone, Serialize)] pub struct MonitoringAlertingScore { @@ -37,7 +42,13 @@ impl Interpret for MonitoringAlertingInt inventory: &Inventory, topology: &T, ) -> Result { - topology.provision_monitor(self.score.alert_channel_configs.clone()).await + topology + .provision_monitor( + inventory, + topology, + self.score.alert_channel_configs.clone(), + ) + .await } fn get_name(&self) -> InterpretName { @@ -56,5 +67,3 @@ impl Interpret for MonitoringAlertingInt todo!() } } - -