From 8d219c648ab33cff20ee5eebd36b1d19ffb68faf Mon Sep 17 00:00:00 2001 From: Willem Date: Wed, 11 Jun 2025 15:40:58 -0400 Subject: [PATCH] feat: deploys cluster monitoring from MonitoringAlertingScore --- examples/monitoring/Cargo.toml | 11 ++ examples/monitoring/src/main.rs | 23 +++ harmony/src/domain/topology/k8s_anywhere.rs | 56 +++++++- .../domain/topology/oberservability/k8s.rs | 71 ++++++++++ .../domain/topology/oberservability/mod.rs | 22 +++ .../topology/oberservability/monitoring.rs | 33 +++-- .../alert_channel/discord_alert_channel.rs | 8 ++ .../modules/monitoring/alert_channel/mod.rs | 1 + .../monitoring/discord_alert_manager.rs | 35 ----- .../monitoring/discord_webhook_sender.rs | 55 -------- .../{ => kube_prometheus}/config.rs | 6 +- .../kube_prometheus_helm_chart_score.rs} | 110 +-------------- .../modules/monitoring/kube_prometheus/mod.rs | 3 + .../monitoring/kube_prometheus/types.rs | 14 ++ harmony/src/modules/monitoring/mod.rs | 6 +- .../modules/monitoring/monitoring_alerting.rs | 132 +++--------------- 16 files changed, 256 insertions(+), 330 deletions(-) create mode 100644 examples/monitoring/Cargo.toml create mode 100644 examples/monitoring/src/main.rs create mode 100644 harmony/src/domain/topology/oberservability/k8s.rs create mode 100644 harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs create mode 100644 harmony/src/modules/monitoring/alert_channel/mod.rs delete mode 100644 harmony/src/modules/monitoring/discord_alert_manager.rs delete mode 100644 harmony/src/modules/monitoring/discord_webhook_sender.rs rename harmony/src/modules/monitoring/{ => kube_prometheus}/config.rs (90%) rename harmony/src/modules/monitoring/{kube_prometheus.rs => kube_prometheus/kube_prometheus_helm_chart_score.rs} (62%) create mode 100644 harmony/src/modules/monitoring/kube_prometheus/mod.rs create mode 100644 harmony/src/modules/monitoring/kube_prometheus/types.rs diff --git a/examples/monitoring/Cargo.toml b/examples/monitoring/Cargo.toml new file mode 100644 index 0000000..57f291c --- /dev/null +++ b/examples/monitoring/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "monitoring" +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 diff --git a/examples/monitoring/src/main.rs b/examples/monitoring/src/main.rs new file mode 100644 index 0000000..8b6eeb4 --- /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, +}; + +#[tokio::main] +async fn main() { + let mut maestro = Maestro::::initialize( + Inventory::autoload(), + K8sAnywhereTopology::from_env(), + ) + .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 044729f..87d47bd 100644 --- a/harmony/src/domain/topology/k8s_anywhere.rs +++ b/harmony/src/domain/topology/k8s_anywhere.rs @@ -6,7 +6,6 @@ use log::{debug, info, warn}; use tokio::sync::OnceCell; use crate::{ - data::Id, executors::ExecutorError, interpret::{InterpretError, Outcome}, inventory::Inventory, @@ -18,9 +17,12 @@ use crate::{ use super::{ HelmCommand, K8sclient, Topology, k8s::K8sClient, - tenant::{ - ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy, k8s::K8sTenantManager, + oberservability::{ + K8sMonitorConfig, + k8s::K8sMonitor, + monitoring::{AlertChannelConfig, Monitor}, }, + tenant::{TenantConfig, TenantManager, k8s::K8sTenantManager}, }; struct K8sState { @@ -38,6 +40,7 @@ enum K8sSource { pub struct K8sAnywhereTopology { k8s_state: OnceCell>, tenant_manager: OnceCell, + k8s_monitor: OnceCell, config: K8sAnywhereConfig, } @@ -63,6 +66,7 @@ impl K8sAnywhereTopology { Self { k8s_state: OnceCell::new(), tenant_manager: OnceCell::new(), + k8s_monitor: OnceCell::new(), config: K8sAnywhereConfig::from_env(), } } @@ -71,6 +75,7 @@ impl K8sAnywhereTopology { Self { k8s_state: OnceCell::new(), tenant_manager: OnceCell::new(), + k8s_monitor: OnceCell::new(), config, } } @@ -201,6 +206,30 @@ impl K8sAnywhereTopology { )), } } + + async fn ensure_k8s_monitor(&self) -> Result<(), String> { + if let Some(_) = self.k8s_monitor.get() { + return Ok(()); + } + + self.k8s_monitor + .get_or_try_init(async || -> Result { + let config = K8sMonitorConfig::cluster_monitor(); + Ok(K8sMonitor { config }) + }) + .await + .unwrap(); + Ok(()) + } + + fn get_k8s_monitor(&self) -> Result<&K8sMonitor, ExecutorError> { + match self.k8s_monitor.get() { + Some(k) => Ok(k), + None => Err(ExecutorError::UnexpectedError( + "K8sMonitor not available".to_string(), + )), + } + } } pub struct K8sAnywhereConfig { @@ -252,6 +281,10 @@ impl Topology for K8sAnywhereTopology { "No K8s client could be found or installed".to_string(), ))?; + self.ensure_k8s_monitor() + .await + .map_err(|e| InterpretError::new(e))?; + self.ensure_k8s_tenant_manager() .await .map_err(|e| InterpretError::new(e))?; @@ -276,3 +309,20 @@ impl TenantManager for K8sAnywhereTopology { .await } } +#[async_trait] +impl Monitor for K8sAnywhereTopology { + async fn provision_monitor( + &self, + inventory: &Inventory, + topology: &T, + alert_receivers: Option>>, + ) -> Result { + self.get_k8s_monitor()? + .provision_monitor(inventory, topology, alert_receivers) + .await + } + + fn delete_monitor(&self) -> Result { + todo!() + } +} diff --git a/harmony/src/domain/topology/oberservability/k8s.rs b/harmony/src/domain/topology/oberservability/k8s.rs new file mode 100644 index 0000000..004f9ec --- /dev/null +++ b/harmony/src/domain/topology/oberservability/k8s.rs @@ -0,0 +1,71 @@ +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, + topology::Topology, +}; + +use super::{ + K8sMonitorConfig, + monitoring::{AlertChannel, AlertChannelConfig, Monitor}, +}; + +#[derive(Debug, Clone, Serialize)] +pub struct K8sMonitor { + pub config: K8sMonitorConfig, +} + +#[async_trait] +impl Monitor for K8sMonitor { + async fn provision_monitor( + &self, + inventory: &Inventory, + topology: &T, + alert_channels: Option>>, + ) -> Result { + 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() + .execute(inventory, topology) + .await?; + Ok(Outcome::success("installed monitor".to_string())) + } + + fn delete_monitor(&self) -> Result { + todo!() + } +} + +#[async_trait] +impl AlertChannelConfig for K8sMonitor { + async fn build_alert_channel(&self) -> Result, InterpretError> { + todo!() + } +} + +impl K8sMonitor { + pub async fn build_alert_channels( + &self, + alert_channel_configs: Vec>, + ) -> Result>, InterpretError> { + let mut alert_channels = Vec::new(); + for config in alert_channel_configs { + let channel = config.build_alert_channel().await?; + alert_channels.push(channel) + } + Ok(alert_channels) + } +} diff --git a/harmony/src/domain/topology/oberservability/mod.rs b/harmony/src/domain/topology/oberservability/mod.rs index 7f2ac95..387709a 100644 --- a/harmony/src/domain/topology/oberservability/mod.rs +++ b/harmony/src/domain/topology/oberservability/mod.rs @@ -1 +1,23 @@ +use serde::Serialize; + +use crate::modules::{ + helm::chart::HelmChartScore, + monitoring::kube_prometheus::kube_prometheus_helm_chart_score::kube_prometheus_helm_chart_score, +}; + +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 51ec38e..1d6a159 100644 --- a/harmony/src/domain/topology/oberservability/monitoring.rs +++ b/harmony/src/domain/topology/oberservability/monitoring.rs @@ -1,30 +1,39 @@ use async_trait::async_trait; - +use dyn_clone::DynClone; use std::fmt::Debug; +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 -/// from various telemetry sources +/// from various telemetry sources such as Prometheus or Datadog /// A `Monitor` abstracts the logic required to scrape, aggregate, and structure /// monitoring data, enabling consistent processing regardless of the underlying data source. #[async_trait] -pub trait Monitor: Debug + Send + Sync { - async fn deploy_monitor( +pub trait Monitor { + async fn provision_monitor( &self, + inventory: &Inventory, topology: &T, - alert_receivers: Vec, + alert_receivers: Option>>, ) -> Result; - async fn delete_monitor( - &self, - topolgy: &T, - alert_receivers: Vec, - ) -> Result; + fn delete_monitor(&self) -> Result; } -pub struct AlertReceiver { - pub receiver_id: String, +#[async_trait] +pub trait AlertChannel: Debug + Send + Sync { + async fn register_alert_channel(&self) -> Result; + //async fn get_channel_id(&self) -> String; } + +#[async_trait] +pub trait AlertChannelConfig: Debug + Send + Sync + DynClone { + async fn build_alert_channel(&self) -> Result, InterpretError>; +} + +dyn_clone::clone_trait_object!(AlertChannelConfig); diff --git a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs new file mode 100644 index 0000000..9dc11f3 --- /dev/null +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -0,0 +1,8 @@ +use url::Url; + +#[derive(Debug, Clone)] +pub struct DiscordWebhookAlertChannel { + pub webhook_url: Url, + pub name: String, + pub send_resolved_notifications: bool, +} diff --git a/harmony/src/modules/monitoring/alert_channel/mod.rs b/harmony/src/modules/monitoring/alert_channel/mod.rs new file mode 100644 index 0000000..fabc6dd --- /dev/null +++ b/harmony/src/modules/monitoring/alert_channel/mod.rs @@ -0,0 +1 @@ +pub mod discord_alert_channel; diff --git a/harmony/src/modules/monitoring/discord_alert_manager.rs b/harmony/src/modules/monitoring/discord_alert_manager.rs deleted file mode 100644 index 7765505..0000000 --- a/harmony/src/modules/monitoring/discord_alert_manager.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::str::FromStr; - -use non_blank_string_rs::NonBlankString; -use url::Url; - -use crate::modules::helm::chart::HelmChartScore; - -pub fn discord_alert_manager_score( - webhook_url: Url, - namespace: String, - name: String, -) -> HelmChartScore { - let values = format!( - r#" -environment: - - name: "DISCORD_WEBHOOK" - value: "{webhook_url}" -"#, - ); - - HelmChartScore { - namespace: Some(NonBlankString::from_str(&namespace).unwrap()), - release_name: NonBlankString::from_str(&name).unwrap(), - chart_name: NonBlankString::from_str( - "oci://hub.nationtech.io/library/alertmanager-discord", - ) - .unwrap(), - chart_version: None, - values_overrides: None, - values_yaml: Some(values.to_string()), - create_namespace: true, - install_only: true, - repository: None, - } -} diff --git a/harmony/src/modules/monitoring/discord_webhook_sender.rs b/harmony/src/modules/monitoring/discord_webhook_sender.rs deleted file mode 100644 index bad6402..0000000 --- a/harmony/src/modules/monitoring/discord_webhook_sender.rs +++ /dev/null @@ -1,55 +0,0 @@ -use async_trait::async_trait; -use serde_json::Value; -use url::Url; - -use crate::{ - interpret::{InterpretError, Outcome}, - topology::K8sAnywhereTopology, -}; - -#[derive(Debug, Clone)] -pub struct DiscordWebhookConfig { - pub webhook_url: Url, - pub name: String, - pub send_resolved_notifications: bool, -} - -pub trait DiscordWebhookReceiver { - fn deploy_discord_webhook_receiver( - &self, - _notification_adapter_id: &str, - ) -> Result; - - fn delete_discord_webhook_receiver( - &self, - _notification_adapter_id: &str, - ) -> Result; -} - -// trait used to generate alert manager config values impl Monitor for KubePrometheus -pub trait AlertManagerConfig { - fn get_alert_manager_config(&self) -> Result; -} - -#[async_trait] -impl AlertManagerConfig for DiscordWebhookConfig { - fn get_alert_manager_config(&self) -> Result { - todo!() - } -} - -#[async_trait] -impl DiscordWebhookReceiver for K8sAnywhereTopology { - fn deploy_discord_webhook_receiver( - &self, - _notification_adapter_id: &str, - ) -> Result { - todo!() - } - fn delete_discord_webhook_receiver( - &self, - _notification_adapter_id: &str, - ) -> Result { - todo!() - } -} diff --git a/harmony/src/modules/monitoring/config.rs b/harmony/src/modules/monitoring/kube_prometheus/config.rs similarity index 90% rename from harmony/src/modules/monitoring/config.rs rename to harmony/src/modules/monitoring/kube_prometheus/config.rs index 1477905..74fdf6f 100644 --- a/harmony/src/modules/monitoring/config.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/config.rs @@ -1,6 +1,6 @@ use serde::Serialize; -use super::monitoring_alerting::AlertChannel; +use super::types::AlertManagerChannelConfig; #[derive(Debug, Clone, Serialize)] pub struct KubePrometheusConfig { @@ -21,7 +21,7 @@ pub struct KubePrometheusConfig { pub kube_proxy: bool, pub kube_state_metrics: bool, pub prometheus_operator: bool, - pub alert_channel: Vec, + pub alert_channels: Vec, } impl KubePrometheusConfig { pub fn new() -> Self { @@ -30,7 +30,6 @@ impl KubePrometheusConfig { default_rules: true, windows_monitoring: false, alert_manager: true, - alert_channel: Vec::new(), grafana: true, node_exporter: false, prometheus: true, @@ -44,6 +43,7 @@ impl KubePrometheusConfig { prometheus_operator: true, core_dns: false, kube_scheduler: false, + alert_channels: Vec::new(), } } } diff --git a/harmony/src/modules/monitoring/kube_prometheus.rs b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs similarity index 62% rename from harmony/src/modules/monitoring/kube_prometheus.rs rename to harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs index b694f51..14680d9 100644 --- a/harmony/src/modules/monitoring/kube_prometheus.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs @@ -1,12 +1,13 @@ -use super::{config::KubePrometheusConfig, monitoring_alerting::AlertChannel}; +use super::config::KubePrometheusConfig; use log::info; use non_blank_string_rs::NonBlankString; -use std::{collections::HashMap, str::FromStr}; -use url::Url; +use std::str::FromStr; use crate::modules::helm::chart::HelmChartScore; -pub fn kube_prometheus_helm_chart_score(config: &KubePrometheusConfig) -> HelmChartScore { +pub fn kube_prometheus_helm_chart_score() -> HelmChartScore { + let config = KubePrometheusConfig::new(); + //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(); @@ -144,67 +145,6 @@ prometheus: enabled: {prometheus} "#, ); - - 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 - } - HelmChartScore { namespace: Some(NonBlankString::from_str(&config.namespace).unwrap()), release_name: NonBlankString::from_str("kube-prometheus").unwrap(), @@ -220,43 +160,3 @@ alertmanager: repository: None, } } - -fn discord_alert_builder(release_name: &String) -> (String, String) { - let discord_receiver_name = format!("Discord-{}", release_name); - let receiver = format!( - r#" - - name: '{discord_receiver_name}' - webhook_configs: - - url: 'http://{release_name}-alertmanager-discord:9094' - send_resolved: true"#, - ); - let route = format!( - r#" - - receiver: '{discord_receiver_name}' - matchers: - - alertname!=Watchdog - continue: true"#, - ); - (receiver, route) -} - -fn slack_alert_builder(slack_channel: &String) -> (String, String) { - let slack_receiver_name = format!("Slack-{}", slack_channel); - let receiver = format!( - r#" - - name: '{slack_receiver_name}' - slack_configs: - - channel: '{slack_channel}' - send_resolved: true - title: '{{{{ .CommonAnnotations.title }}}}' - text: '{{{{ .CommonAnnotations.description }}}}'"#, - ); - let route = format!( - r#" - - receiver: '{slack_receiver_name}' - matchers: - - alertname!=Watchdog - continue: true"#, - ); - (receiver, route) -} diff --git a/harmony/src/modules/monitoring/kube_prometheus/mod.rs b/harmony/src/modules/monitoring/kube_prometheus/mod.rs new file mode 100644 index 0000000..8ad49f0 --- /dev/null +++ b/harmony/src/modules/monitoring/kube_prometheus/mod.rs @@ -0,0 +1,3 @@ +pub mod config; +pub mod kube_prometheus_helm_chart_score; +pub mod types; diff --git a/harmony/src/modules/monitoring/kube_prometheus/types.rs b/harmony/src/modules/monitoring/kube_prometheus/types.rs new file mode 100644 index 0000000..fa66f99 --- /dev/null +++ b/harmony/src/modules/monitoring/kube_prometheus/types.rs @@ -0,0 +1,14 @@ +use serde::Serialize; + +#[derive(Debug, Clone, Serialize)] +pub struct AlertManagerChannelConfig { + pub global_configs: AlertManagerChannelGlobalConfigs, + pub route: AlertManagerChannelRoute, + pub receiver: AlertManagerChannelReceiver, +} +#[derive(Debug, Clone, Serialize)] +pub struct AlertManagerChannelGlobalConfigs {} +#[derive(Debug, Clone, Serialize)] +pub struct AlertManagerChannelReceiver {} +#[derive(Debug, Clone, Serialize)] +pub struct AlertManagerChannelRoute {} diff --git a/harmony/src/modules/monitoring/mod.rs b/harmony/src/modules/monitoring/mod.rs index d3eb288..a84bd9f 100644 --- a/harmony/src/modules/monitoring/mod.rs +++ b/harmony/src/modules/monitoring/mod.rs @@ -1,5 +1,3 @@ -mod config; -mod discord_alert_manager; -pub mod discord_webhook_sender; -mod kube_prometheus; +pub mod alert_channel; +pub mod kube_prometheus; pub mod monitoring_alerting; diff --git a/harmony/src/modules/monitoring/monitoring_alerting.rs b/harmony/src/modules/monitoring/monitoring_alerting.rs index 6d2db38..df1c8a2 100644 --- a/harmony/src/modules/monitoring/monitoring_alerting.rs +++ b/harmony/src/modules/monitoring/monitoring_alerting.rs @@ -1,10 +1,7 @@ use async_trait::async_trait; -use email_address::EmailAddress; - -use log::info; use serde::Serialize; -use url::Url; +use crate::topology::oberservability::monitoring::{AlertChannelConfig, Monitor}; use crate::{ data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, @@ -13,134 +10,43 @@ use crate::{ topology::{HelmCommand, Topology}, }; -use super::{ - config::KubePrometheusConfig, discord_alert_manager::discord_alert_manager_score, - kube_prometheus::kube_prometheus_helm_chart_score, -}; - #[derive(Debug, Clone, Serialize)] -pub enum AlertChannel { - Discord { - name: String, - webhook_url: Url, - }, - Slack { - slack_channel: String, - webhook_url: Url, - }, - //TODO test and implement in helm chart - //currently does not work - Smpt { - email_address: EmailAddress, - service_name: String, - }, +pub struct MonitoringAlertingScore { + #[serde(skip)] + pub alert_channel_configs: Option>>, } -#[derive(Debug, Clone, Serialize)] -pub struct MonitoringAlertingStackScore { - pub alert_channel: Vec, - pub namespace: Option, -} - -impl MonitoringAlertingStackScore { - pub fn new() -> Self { - Self { - alert_channel: Vec::new(), - namespace: None, - } - } -} - -impl Score for MonitoringAlertingStackScore { +impl Score for MonitoringAlertingScore { fn create_interpret(&self) -> Box> { - Box::new(MonitoringAlertingStackInterpret { + Box::new(MonitoringAlertingInterpret { score: self.clone(), }) } + fn name(&self) -> String { - format!("MonitoringAlertingStackScore") + "MonitoringAlertingScore".to_string() } } -#[derive(Debug, Clone, Serialize)] -struct MonitoringAlertingStackInterpret { - score: MonitoringAlertingStackScore, -} - -impl MonitoringAlertingStackInterpret { - async fn build_kube_prometheus_helm_chart_config(&self) -> KubePrometheusConfig { - let mut config = KubePrometheusConfig::new(); - if let Some(ns) = &self.score.namespace { - config.namespace = ns.clone(); - } - config.alert_channel = self.score.alert_channel.clone(); - config - } - - async fn deploy_kube_prometheus_helm_chart_score( - &self, - inventory: &Inventory, - topology: &T, - config: &KubePrometheusConfig, - ) -> Result { - let helm_chart = kube_prometheus_helm_chart_score(config); - helm_chart - .create_interpret() - .execute(inventory, topology) - .await - } - - async fn deploy_alert_channel_service( - &self, - inventory: &Inventory, - topology: &T, - config: &KubePrometheusConfig, - ) -> Result { - //let mut outcomes = vec![]; - - //for channel in &self.score.alert_channel { - // let outcome = match channel { - // AlertChannel::Discord { .. } => { - // discord_alert_manager_score(config) - // .create_interpret() - // .execute(inventory, topology) - // .await - // } - // AlertChannel::Slack { .. } => Ok(Outcome::success( - // "No extra configs for slack alerting".to_string(), - // )), - // AlertChannel::Smpt { .. } => { - // todo!() - // } - // }; - // outcomes.push(outcome); - //} - //for result in outcomes { - // result?; - //} - - Ok(Outcome::success("All alert channels deployed".to_string())) - } +#[derive(Debug)] +struct MonitoringAlertingInterpret { + score: MonitoringAlertingScore, } #[async_trait] -impl Interpret for MonitoringAlertingStackInterpret { +impl Interpret for MonitoringAlertingInterpret { async fn execute( &self, inventory: &Inventory, topology: &T, ) -> Result { - let config = self.build_kube_prometheus_helm_chart_config().await; - info!("Built kube prometheus config"); - info!("Installing kube prometheus chart"); - self.deploy_kube_prometheus_helm_chart_score(inventory, topology, &config) - .await?; - info!("Installing alert channel service"); - self.deploy_alert_channel_service(inventory, topology, &config) - .await?; - Ok(Outcome::success(format!( - "succesfully deployed monitoring and alerting stack" - ))) + topology + .provision_monitor( + inventory, + topology, + self.score.alert_channel_configs.clone(), + ) + .await } fn get_name(&self) -> InterpretName {