Compare commits
	
		
			No commits in common. "1f3796f50301b38746366c4d5e4909332db203dd" and "f073b7e5fb15bf7da0d4fb9fdcee60aa665c854c" have entirely different histories.
		
	
	
		
			1f3796f503
			...
			f073b7e5fb
		
	
		
| @ -3,7 +3,7 @@ use harmony::{ | ||||
|     modules::{ | ||||
|         application::{ | ||||
|             ApplicationScore, RustWebFramework, RustWebapp, | ||||
|             features::{Monitoring, PackagingDeployment}, | ||||
|             features::{PackagingDeployment, rhob_monitoring::Monitoring}, | ||||
|         }, | ||||
|         monitoring::alert_channel::discord_alert_channel::DiscordWebhook, | ||||
|     }, | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use std::{collections::BTreeMap, process::Command, sync::Arc}; | ||||
| use std::{process::Command, sync::Arc}; | ||||
| 
 | ||||
| use async_trait::async_trait; | ||||
| use kube::api::{GroupVersionKind, ObjectMeta}; | ||||
| use kube::api::GroupVersionKind; | ||||
| use log::{debug, info, warn}; | ||||
| use serde::Serialize; | ||||
| use tokio::sync::OnceCell; | ||||
| @ -12,25 +12,14 @@ use crate::{ | ||||
|     inventory::Inventory, | ||||
|     modules::{ | ||||
|         k3d::K3DInstallationScore, | ||||
|         k8s::ingress::{K8sIngressScore, PathType}, | ||||
|         monitoring::{ | ||||
|             grafana::{grafana::Grafana, helm::helm_grafana::grafana_helm_chart_score}, | ||||
|             kube_prometheus::crd::{ | ||||
|         monitoring::kube_prometheus::crd::{ | ||||
|             crd_alertmanager_config::CRDPrometheus, | ||||
|                 crd_grafana::{ | ||||
|                     Grafana as GrafanaCRD, GrafanaDashboard, GrafanaDashboardSpec, | ||||
|                     GrafanaDatasource, GrafanaDatasourceConfig, GrafanaDatasourceSpec, GrafanaSpec, | ||||
|                 }, | ||||
|                 crd_prometheuses::LabelSelector, | ||||
|                 grafana_default_dashboard::build_default_dashboard, | ||||
|             prometheus_operator::prometheus_operator_helm_chart_score, | ||||
|             rhob_alertmanager_config::RHOBObservability, | ||||
|                 service_monitor::ServiceMonitor, | ||||
|             }, | ||||
|         }, | ||||
|         prometheus::{ | ||||
|             k8s_prometheus_alerting_score::K8sPrometheusCRDAlertingScore, | ||||
|             prometheus::PrometheusMonitoring, rhob_alerting_score::RHOBAlertingScore, | ||||
|             prometheus::PrometheusApplicationMonitoring, rhob_alerting_score::RHOBAlertingScore, | ||||
|         }, | ||||
|     }, | ||||
|     score::Score, | ||||
| @ -97,120 +86,41 @@ impl K8sclient for K8sAnywhereTopology { | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl Grafana for K8sAnywhereTopology { | ||||
|     async fn ensure_grafana_operator( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|     ) -> Result<PreparationOutcome, PreparationError> { | ||||
|         debug!("ensure grafana operator"); | ||||
|         let client = self.k8s_client().await.unwrap(); | ||||
|         let grafana_gvk = GroupVersionKind { | ||||
|             group: "grafana.integreatly.org".to_string(), | ||||
|             version: "v1beta1".to_string(), | ||||
|             kind: "Grafana".to_string(), | ||||
|         }; | ||||
|         let name = "grafanas.grafana.integreatly.org"; | ||||
|         let ns = "grafana"; | ||||
| 
 | ||||
|         let grafana_crd = client | ||||
|             .get_resource_json_value(name, Some(ns), &grafana_gvk) | ||||
|             .await; | ||||
|         match grafana_crd { | ||||
|             Ok(_) => { | ||||
|                 return Ok(PreparationOutcome::Success { | ||||
|                     details: "Found grafana CRDs in cluster".to_string(), | ||||
|                 }); | ||||
|             } | ||||
| 
 | ||||
|             Err(_) => { | ||||
|                 return self | ||||
|                     .install_grafana_operator(inventory, Some("grafana")) | ||||
|                     .await; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|     async fn install_grafana(&self) -> Result<PreparationOutcome, PreparationError> { | ||||
|         debug!("install grafana"); | ||||
|         let ns = "grafana"; | ||||
| 
 | ||||
|         let mut label = BTreeMap::new(); | ||||
| 
 | ||||
|         label.insert("dashboards".to_string(), "grafana".to_string()); | ||||
|         let label_selector = LabelSelector { | ||||
|             match_labels: label.clone(), | ||||
|             match_expressions: vec![], | ||||
|         }; | ||||
| 
 | ||||
|         let client = self.k8s_client().await?; | ||||
| 
 | ||||
|         let datasource = self.build_grafana_datasource(ns, &label_selector); | ||||
| 
 | ||||
|         client.apply(&datasource, Some(ns)).await?; | ||||
| 
 | ||||
|         let dashboard = self.build_grafana_dashboard(ns, &label_selector); | ||||
| 
 | ||||
|         client.apply(&dashboard, Some(ns)).await?; | ||||
| 
 | ||||
|         let grafana = self.build_grafana(ns, &label); | ||||
| 
 | ||||
|         client.apply(&grafana, Some(ns)).await?; | ||||
| 
 | ||||
|         let grafana_ingress = self.build_grafana_ingress(ns).await; | ||||
| 
 | ||||
|         grafana_ingress | ||||
|             .interpret(&Inventory::empty(), self) | ||||
|             .await | ||||
|             .map_err(|e| PreparationError::new(e.to_string()))?; | ||||
| 
 | ||||
|         Ok(PreparationOutcome::Success { | ||||
|             details: "Installed grafana composants".to_string(), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl PrometheusMonitoring<CRDPrometheus> for K8sAnywhereTopology { | ||||
| impl PrometheusApplicationMonitoring<CRDPrometheus> for K8sAnywhereTopology { | ||||
|     async fn install_prometheus( | ||||
|         &self, | ||||
|         sender: &CRDPrometheus, | ||||
|         _inventory: &Inventory, | ||||
|         _receivers: Option<Vec<Box<dyn AlertReceiver<CRDPrometheus>>>>, | ||||
|     ) -> Result<PreparationOutcome, PreparationError> { | ||||
|         let client = self.k8s_client().await?; | ||||
| 
 | ||||
|         for monitor in sender.service_monitor.iter() { | ||||
|             client | ||||
|                 .apply(monitor, Some(&sender.namespace)) | ||||
|                 .await | ||||
|                 .map_err(|e| PreparationError::new(e.to_string()))?; | ||||
|         } | ||||
|         Ok(PreparationOutcome::Success { | ||||
|             details: "successfuly installed prometheus components".to_string(), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     async fn ensure_prometheus_operator( | ||||
|         &self, | ||||
|         sender: &CRDPrometheus, | ||||
|         _inventory: &Inventory, | ||||
|         inventory: &Inventory, | ||||
|         receivers: Option<Vec<Box<dyn AlertReceiver<CRDPrometheus>>>>, | ||||
|     ) -> Result<PreparationOutcome, PreparationError> { | ||||
|         let po_result = self.ensure_prometheus_operator(sender).await?; | ||||
| 
 | ||||
|         match po_result { | ||||
|             PreparationOutcome::Success { details: _ } => { | ||||
|                 debug!("Detected prometheus crds operator present in cluster."); | ||||
|                 return Ok(po_result); | ||||
|             } | ||||
|             PreparationOutcome::Noop => { | ||||
|         if po_result == PreparationOutcome::Noop { | ||||
|             debug!("Skipping Prometheus CR installation due to missing operator."); | ||||
|             return Ok(po_result); | ||||
|         } | ||||
| 
 | ||||
|         let result = self | ||||
|             .get_k8s_prometheus_application_score(sender.clone(), receivers) | ||||
|             .await | ||||
|             .interpret(inventory, self) | ||||
|             .await; | ||||
| 
 | ||||
|         match result { | ||||
|             Ok(outcome) => match outcome.status { | ||||
|                 InterpretStatus::SUCCESS => Ok(PreparationOutcome::Success { | ||||
|                     details: outcome.message, | ||||
|                 }), | ||||
|                 InterpretStatus::NOOP => Ok(PreparationOutcome::Noop), | ||||
|                 _ => Err(PreparationError::new(outcome.message)), | ||||
|             }, | ||||
|             Err(err) => Err(PreparationError::new(err.to_string())), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl PrometheusMonitoring<RHOBObservability> for K8sAnywhereTopology { | ||||
| impl PrometheusApplicationMonitoring<RHOBObservability> for K8sAnywhereTopology { | ||||
|     async fn install_prometheus( | ||||
|         &self, | ||||
|         sender: &RHOBObservability, | ||||
| @ -244,14 +154,6 @@ impl PrometheusMonitoring<RHOBObservability> for K8sAnywhereTopology { | ||||
|             Err(err) => Err(PreparationError::new(err.to_string())), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn ensure_prometheus_operator( | ||||
|         &self, | ||||
|         sender: &RHOBObservability, | ||||
|         inventory: &Inventory, | ||||
|     ) -> Result<PreparationOutcome, PreparationError> { | ||||
|         todo!() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Serialize for K8sAnywhereTopology { | ||||
| @ -334,95 +236,6 @@ impl K8sAnywhereTopology { | ||||
|             .clone() | ||||
|     } | ||||
| 
 | ||||
|     fn build_grafana_datasource( | ||||
|         &self, | ||||
|         ns: &str, | ||||
|         label_selector: &LabelSelector, | ||||
|     ) -> GrafanaDatasource { | ||||
|         let mut json_data = BTreeMap::new(); | ||||
|         json_data.insert("timeInterval".to_string(), "5s".to_string()); | ||||
| 
 | ||||
|         let graf_data_source = GrafanaDatasource { | ||||
|             metadata: ObjectMeta { | ||||
|                 name: Some(format!("grafana-datasource-{}", ns)), | ||||
|                 namespace: Some(ns.to_string()), | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             spec: GrafanaDatasourceSpec { | ||||
|                 instance_selector: label_selector.clone(), | ||||
|                 allow_cross_namespace_import: Some(false), | ||||
|                 datasource: GrafanaDatasourceConfig { | ||||
|                     access: "proxy".to_string(), | ||||
|                     database: Some("prometheus".to_string()), | ||||
|                     json_data: Some(json_data), | ||||
|                     //this is fragile
 | ||||
|                     name: format!("prometheus-{}-0", ns), | ||||
|                     r#type: "prometheus".to_string(), | ||||
|                     url: format!("http://prometheus-operated.{}.svc.cluster.local:9090", ns), | ||||
|                 }, | ||||
|             }, | ||||
|         }; | ||||
|         graf_data_source | ||||
|     } | ||||
| 
 | ||||
|     fn build_grafana_dashboard( | ||||
|         &self, | ||||
|         ns: &str, | ||||
|         label_selector: &LabelSelector, | ||||
|     ) -> GrafanaDashboard { | ||||
|         let json = build_default_dashboard(ns); | ||||
|         let graf_dashboard = GrafanaDashboard { | ||||
|             metadata: ObjectMeta { | ||||
|                 name: Some(format!("grafana-dashboard-{}", ns)), | ||||
|                 namespace: Some(ns.to_string()), | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             spec: GrafanaDashboardSpec { | ||||
|                 resync_period: Some("30s".to_string()), | ||||
|                 instance_selector: label_selector.clone(), | ||||
|                 json, | ||||
|             }, | ||||
|         }; | ||||
|         graf_dashboard | ||||
|     } | ||||
| 
 | ||||
|     fn build_grafana(&self, ns: &str, labels: &BTreeMap<String, String>) -> GrafanaCRD { | ||||
|         let grafana = GrafanaCRD { | ||||
|             metadata: ObjectMeta { | ||||
|                 name: Some(format!("grafana-{}", ns)), | ||||
|                 namespace: Some(ns.to_string()), | ||||
|                 labels: Some(labels.clone()), | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             spec: GrafanaSpec { | ||||
|                 config: None, | ||||
|                 admin_user: None, | ||||
|                 admin_password: None, | ||||
|                 ingress: None, | ||||
|                 persistence: None, | ||||
|                 resources: None, | ||||
|             }, | ||||
|         }; | ||||
|         grafana | ||||
|     } | ||||
| 
 | ||||
|     async fn build_grafana_ingress(&self, ns: &str) -> K8sIngressScore { | ||||
|         let domain = self.get_domain(&format!("grafana-{}", ns)).await.unwrap(); | ||||
|         let name = format!("{}-grafana", ns); | ||||
|         let backend_service = format!("grafana-{}-service", ns); | ||||
| 
 | ||||
|         K8sIngressScore { | ||||
|             name: fqdn::fqdn!(&name), | ||||
|             host: fqdn::fqdn!(&domain), | ||||
|             backend_service: fqdn::fqdn!(&backend_service), | ||||
|             port: 3000, | ||||
|             path: Some("/".to_string()), | ||||
|             path_type: Some(PathType::Prefix), | ||||
|             namespace: Some(fqdn::fqdn!(&ns)), | ||||
|             ingress_class_name: Some("openshift-default".to_string()), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn get_cluster_observability_operator_prometheus_application_score( | ||||
|         &self, | ||||
|         sender: RHOBObservability, | ||||
| @ -440,22 +253,12 @@ impl K8sAnywhereTopology { | ||||
|         &self, | ||||
|         sender: CRDPrometheus, | ||||
|         receivers: Option<Vec<Box<dyn AlertReceiver<CRDPrometheus>>>>, | ||||
|         service_monitors: Option<Vec<ServiceMonitor>>, | ||||
|     ) -> K8sPrometheusCRDAlertingScore { | ||||
|         if let Some(sm) = service_monitors { | ||||
|             return K8sPrometheusCRDAlertingScore { | ||||
|                 sender, | ||||
|                 receivers: receivers.unwrap_or_default(), | ||||
|                 service_monitors: sm, | ||||
|                 prometheus_rules: vec![], | ||||
|             }; | ||||
|         } else { | ||||
|             return K8sPrometheusCRDAlertingScore { | ||||
|         K8sPrometheusCRDAlertingScore { | ||||
|             sender, | ||||
|             receivers: receivers.unwrap_or_default(), | ||||
|             service_monitors: vec![], | ||||
|             prometheus_rules: vec![], | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -724,29 +527,6 @@ impl K8sAnywhereTopology { | ||||
|             details: "prometheus operator present in cluster".into(), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     async fn install_grafana_operator( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|         ns: Option<&str>, | ||||
|     ) -> Result<PreparationOutcome, PreparationError> { | ||||
|         let namespace = ns.unwrap_or("grafana"); | ||||
|         info!("installing grafana operator in ns {namespace}"); | ||||
|         let tenant = self.get_k8s_tenant_manager()?.get_tenant_config().await; | ||||
|         let mut namespace_scope = false; | ||||
|         if tenant.is_some() { | ||||
|             namespace_scope = true; | ||||
|         } | ||||
|         let _grafana_operator_score = grafana_helm_chart_score(namespace, namespace_scope) | ||||
|             .interpret(inventory, self) | ||||
|             .await; | ||||
|         Ok(PreparationOutcome::Success { | ||||
|             details: format!( | ||||
|                 "Successfully installed grafana operator in ns {}", | ||||
|                 ns.unwrap() | ||||
|             ), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
|  | ||||
| @ -30,7 +30,6 @@ impl<S: AlertSender + Installable<T>, T: Topology> Interpret<T> for AlertingInte | ||||
|         inventory: &Inventory, | ||||
|         topology: &T, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         debug!("hit sender configure for AlertingInterpret"); | ||||
|         self.sender.configure(inventory, topology).await?; | ||||
|         for receiver in self.receivers.iter() { | ||||
|             receiver.install(&self.sender).await?; | ||||
| @ -39,7 +38,6 @@ impl<S: AlertSender + Installable<T>, T: Topology> Interpret<T> for AlertingInte | ||||
|             debug!("installing rule: {:#?}", rule); | ||||
|             rule.install(&self.sender).await?; | ||||
|         } | ||||
|         debug!("hit sender ensure installed for AlertingInterpret"); | ||||
|         self.sender.ensure_installed(inventory, topology).await?; | ||||
|         Ok(Outcome::success(format!( | ||||
|             "successfully installed alert sender {}", | ||||
|  | ||||
| @ -2,11 +2,7 @@ use crate::modules::application::{ | ||||
|     Application, ApplicationFeature, InstallationError, InstallationOutcome, | ||||
| }; | ||||
| use crate::modules::monitoring::application_monitoring::application_monitoring_score::ApplicationMonitoringScore; | ||||
| use crate::modules::monitoring::grafana::grafana::Grafana; | ||||
| use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus; | ||||
| use crate::modules::monitoring::kube_prometheus::crd::service_monitor::{ | ||||
|     ServiceMonitor, ServiceMonitorSpec, | ||||
| }; | ||||
| use crate::topology::MultiTargetTopology; | ||||
| use crate::topology::ingress::Ingress; | ||||
| use crate::{ | ||||
| @ -18,7 +14,7 @@ use crate::{ | ||||
|     topology::{HelmCommand, K8sclient, Topology, tenant::TenantManager}, | ||||
| }; | ||||
| use crate::{ | ||||
|     modules::prometheus::prometheus::PrometheusMonitoring, | ||||
|     modules::prometheus::prometheus::PrometheusApplicationMonitoring, | ||||
|     topology::oberservability::monitoring::AlertReceiver, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| @ -26,7 +22,6 @@ use base64::{Engine as _, engine::general_purpose}; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_secret_derive::Secret; | ||||
| use harmony_types::net::Url; | ||||
| use kube::api::ObjectMeta; | ||||
| use log::{debug, info}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::sync::Arc; | ||||
| @ -45,8 +40,7 @@ impl< | ||||
|         + TenantManager | ||||
|         + K8sclient | ||||
|         + MultiTargetTopology | ||||
|         + PrometheusMonitoring<CRDPrometheus> | ||||
|         + Grafana | ||||
|         + PrometheusApplicationMonitoring<CRDPrometheus> | ||||
|         + Ingress | ||||
|         + std::fmt::Debug, | ||||
| > ApplicationFeature<T> for Monitoring | ||||
| @ -63,20 +57,10 @@ impl< | ||||
|             .unwrap_or_else(|| self.application.name()); | ||||
|         let domain = topology.get_domain("ntfy").await.unwrap(); | ||||
| 
 | ||||
|         let app_service_monitor = ServiceMonitor { | ||||
|             metadata: ObjectMeta { | ||||
|                 name: Some(self.application.name()), | ||||
|                 namespace: Some(namespace.clone()), | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             spec: ServiceMonitorSpec::default(), | ||||
|         }; | ||||
| 
 | ||||
|         let mut alerting_score = ApplicationMonitoringScore { | ||||
|             sender: CRDPrometheus { | ||||
|                 namespace: namespace.clone(), | ||||
|                 client: topology.k8s_client().await.unwrap(), | ||||
|                 service_monitor: vec![app_service_monitor], | ||||
|             }, | ||||
|             application: self.application.clone(), | ||||
|             receivers: self.alert_receiver.clone(), | ||||
|  | ||||
| @ -18,7 +18,7 @@ use crate::{ | ||||
|     topology::{HelmCommand, K8sclient, Topology, tenant::TenantManager}, | ||||
| }; | ||||
| use crate::{ | ||||
|     modules::prometheus::prometheus::PrometheusMonitoring, | ||||
|     modules::prometheus::prometheus::PrometheusApplicationMonitoring, | ||||
|     topology::oberservability::monitoring::AlertReceiver, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| @ -42,7 +42,7 @@ impl< | ||||
|         + MultiTargetTopology | ||||
|         + Ingress | ||||
|         + std::fmt::Debug | ||||
|         + PrometheusMonitoring<RHOBObservability>, | ||||
|         + PrometheusApplicationMonitoring<RHOBObservability>, | ||||
| > ApplicationFeature<T> for Monitoring | ||||
| { | ||||
|     async fn ensure_installed( | ||||
|  | ||||
| @ -1,23 +1,21 @@ | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| use log::debug; | ||||
| use async_trait::async_trait; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     interpret::Interpret, | ||||
|     data::Version, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::Inventory, | ||||
|     modules::{ | ||||
|         application::Application, | ||||
|         monitoring::{ | ||||
|             grafana::grafana::Grafana, kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus, | ||||
|         }, | ||||
|         prometheus::prometheus::PrometheusMonitoring, | ||||
|         monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus, | ||||
|         prometheus::prometheus::PrometheusApplicationMonitoring, | ||||
|     }, | ||||
|     score::Score, | ||||
|     topology::{ | ||||
|         K8sclient, Topology, | ||||
|         oberservability::monitoring::{AlertReceiver, AlertingInterpret}, | ||||
|     }, | ||||
|     topology::{PreparationOutcome, Topology, oberservability::monitoring::AlertReceiver}, | ||||
| }; | ||||
| use harmony_types::id::Id; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Serialize)] | ||||
| pub struct ApplicationMonitoringScore { | ||||
| @ -26,15 +24,12 @@ pub struct ApplicationMonitoringScore { | ||||
|     pub receivers: Vec<Box<dyn AlertReceiver<CRDPrometheus>>>, | ||||
| } | ||||
| 
 | ||||
| impl<T: Topology + PrometheusMonitoring<CRDPrometheus> + K8sclient + Grafana> Score<T> | ||||
| impl<T: Topology + PrometheusApplicationMonitoring<CRDPrometheus>> Score<T> | ||||
|     for ApplicationMonitoringScore | ||||
| { | ||||
|     fn create_interpret(&self) -> Box<dyn Interpret<T>> { | ||||
|         debug!("creating alerting interpret"); | ||||
|         Box::new(AlertingInterpret { | ||||
|             sender: self.sender.clone(), | ||||
|             receivers: self.receivers.clone(), | ||||
|             rules: vec![], | ||||
|         Box::new(ApplicationMonitoringInterpret { | ||||
|             score: self.clone(), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
| @ -45,3 +40,55 @@ impl<T: Topology + PrometheusMonitoring<CRDPrometheus> + K8sclient + Grafana> Sc | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ApplicationMonitoringInterpret { | ||||
|     score: ApplicationMonitoringScore, | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + PrometheusApplicationMonitoring<CRDPrometheus>> Interpret<T> | ||||
|     for ApplicationMonitoringInterpret | ||||
| { | ||||
|     async fn execute( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|         topology: &T, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         let result = topology | ||||
|             .install_prometheus( | ||||
|                 &self.score.sender, | ||||
|                 inventory, | ||||
|                 Some(self.score.receivers.clone()), | ||||
|             ) | ||||
|             .await; | ||||
| 
 | ||||
|         match result { | ||||
|             Ok(outcome) => match outcome { | ||||
|                 PreparationOutcome::Success { details: _ } => { | ||||
|                     Ok(Outcome::success("Prometheus installed".into())) | ||||
|                 } | ||||
|                 PreparationOutcome::Noop => { | ||||
|                     Ok(Outcome::noop("Prometheus installation skipped".into())) | ||||
|                 } | ||||
|             }, | ||||
|             Err(err) => Err(InterpretError::from(err)), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_name(&self) -> InterpretName { | ||||
|         InterpretName::ApplicationMonitoring | ||||
|     } | ||||
| 
 | ||||
|     fn get_version(&self) -> Version { | ||||
|         todo!() | ||||
|     } | ||||
| 
 | ||||
|     fn get_status(&self) -> InterpretStatus { | ||||
|         todo!() | ||||
|     } | ||||
| 
 | ||||
|     fn get_children(&self) -> Vec<Id> { | ||||
|         todo!() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -12,7 +12,7 @@ use crate::{ | ||||
|         monitoring::kube_prometheus::crd::{ | ||||
|             crd_alertmanager_config::CRDPrometheus, rhob_alertmanager_config::RHOBObservability, | ||||
|         }, | ||||
|         prometheus::prometheus::PrometheusMonitoring, | ||||
|         prometheus::prometheus::PrometheusApplicationMonitoring, | ||||
|     }, | ||||
|     score::Score, | ||||
|     topology::{PreparationOutcome, Topology, oberservability::monitoring::AlertReceiver}, | ||||
| @ -26,7 +26,7 @@ pub struct ApplicationRHOBMonitoringScore { | ||||
|     pub receivers: Vec<Box<dyn AlertReceiver<RHOBObservability>>>, | ||||
| } | ||||
| 
 | ||||
| impl<T: Topology + PrometheusMonitoring<RHOBObservability>> Score<T> | ||||
| impl<T: Topology + PrometheusApplicationMonitoring<RHOBObservability>> Score<T> | ||||
|     for ApplicationRHOBMonitoringScore | ||||
| { | ||||
|     fn create_interpret(&self) -> Box<dyn Interpret<T>> { | ||||
| @ -49,7 +49,7 @@ pub struct ApplicationRHOBMonitoringInterpret { | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + PrometheusMonitoring<RHOBObservability>> Interpret<T> | ||||
| impl<T: Topology + PrometheusApplicationMonitoring<RHOBObservability>> Interpret<T> | ||||
|     for ApplicationRHOBMonitoringInterpret | ||||
| { | ||||
|     async fn execute( | ||||
|  | ||||
| @ -1,17 +0,0 @@ | ||||
| use async_trait::async_trait; | ||||
| use k8s_openapi::Resource; | ||||
| 
 | ||||
| use crate::{ | ||||
|     inventory::Inventory, | ||||
|     topology::{PreparationError, PreparationOutcome}, | ||||
| }; | ||||
| 
 | ||||
| #[async_trait] | ||||
| pub trait Grafana { | ||||
|     async fn ensure_grafana_operator( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|     ) -> Result<PreparationOutcome, PreparationError>; | ||||
| 
 | ||||
|     async fn install_grafana(&self) -> Result<PreparationOutcome, PreparationError>; | ||||
| } | ||||
| @ -1,27 +1,27 @@ | ||||
| use non_blank_string_rs::NonBlankString; | ||||
| use std::{collections::HashMap, str::FromStr}; | ||||
| use std::str::FromStr; | ||||
| 
 | ||||
| use crate::modules::helm::chart::{HelmChartScore, HelmRepository}; | ||||
| use crate::modules::helm::chart::HelmChartScore; | ||||
| 
 | ||||
| pub fn grafana_helm_chart_score(ns: &str) -> HelmChartScore { | ||||
|     let values = r#" | ||||
| rbac: | ||||
|   namespaced: true | ||||
| sidecar: | ||||
|   dashboards: | ||||
|     enabled: true | ||||
|         "#
 | ||||
|     .to_string(); | ||||
| 
 | ||||
| pub fn grafana_helm_chart_score(ns: &str, namespace_scope: bool) -> HelmChartScore { | ||||
|     let mut values_overrides = HashMap::new(); | ||||
|     values_overrides.insert( | ||||
|         NonBlankString::from_str("namespaceScope").unwrap(), | ||||
|         namespace_scope.to_string(), | ||||
|     ); | ||||
|     HelmChartScore { | ||||
|         namespace: Some(NonBlankString::from_str(ns).unwrap()), | ||||
|         release_name: NonBlankString::from_str("grafana-operator").unwrap(), | ||||
|         chart_name: NonBlankString::from_str("grafana/grafana-operator").unwrap(), | ||||
|         release_name: NonBlankString::from_str("grafana").unwrap(), | ||||
|         chart_name: NonBlankString::from_str("oci://ghcr.io/grafana/helm-charts/grafana").unwrap(), | ||||
|         chart_version: None, | ||||
|         values_overrides: Some(values_overrides), | ||||
|         values_yaml: None, | ||||
|         values_overrides: None, | ||||
|         values_yaml: Some(values.to_string()), | ||||
|         create_namespace: true, | ||||
|         install_only: true, | ||||
|         repository: Some(HelmRepository::new( | ||||
|             "grafana".to_string(), | ||||
|             url::Url::parse("https://grafana.github.io/helm-charts").unwrap(), | ||||
|             true, | ||||
|         )), | ||||
|         repository: None, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,2 +1 @@ | ||||
| pub mod grafana; | ||||
| pub mod helm; | ||||
|  | ||||
| @ -1,25 +1,12 @@ | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| use async_trait::async_trait; | ||||
| use kube::CustomResource; | ||||
| use schemars::JsonSchema; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     interpret::{InterpretError, Outcome}, | ||||
|     inventory::Inventory, | ||||
|     modules::{ | ||||
|         monitoring::{ | ||||
|             grafana::grafana::Grafana, kube_prometheus::crd::service_monitor::ServiceMonitor, | ||||
|         }, | ||||
|         prometheus::prometheus::PrometheusMonitoring, | ||||
|     }, | ||||
|     topology::{ | ||||
|         K8sclient, Topology, | ||||
|         installable::Installable, | ||||
| use crate::topology::{ | ||||
|     k8s::K8sClient, | ||||
|     oberservability::monitoring::{AlertReceiver, AlertSender}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| #[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)] | ||||
| @ -39,7 +26,6 @@ pub struct AlertmanagerConfigSpec { | ||||
| pub struct CRDPrometheus { | ||||
|     pub namespace: String, | ||||
|     pub client: Arc<K8sClient>, | ||||
|     pub service_monitor: Vec<ServiceMonitor>, | ||||
| } | ||||
| 
 | ||||
| impl AlertSender for CRDPrometheus { | ||||
| @ -62,24 +48,3 @@ impl Serialize for Box<dyn AlertReceiver<CRDPrometheus>> { | ||||
|         todo!() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + K8sclient + PrometheusMonitoring<CRDPrometheus> + Grafana> Installable<T> | ||||
|     for CRDPrometheus | ||||
| { | ||||
|     async fn configure(&self, inventory: &Inventory, topology: &T) -> Result<(), InterpretError> { | ||||
|         topology.ensure_grafana_operator(inventory).await?; | ||||
|         topology.ensure_prometheus_operator(self, inventory).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn ensure_installed( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|         topology: &T, | ||||
|     ) -> Result<(), InterpretError> { | ||||
|         topology.install_grafana().await?; | ||||
|         topology.install_prometheus(&self, inventory, None).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -114,7 +114,7 @@ impl Prometheus { | ||||
|         }; | ||||
| 
 | ||||
|         if let Some(ns) = namespace.as_deref() { | ||||
|             grafana_helm_chart_score(ns, false) | ||||
|             grafana_helm_chart_score(ns) | ||||
|                 .interpret(inventory, topology) | ||||
|                 .await | ||||
|         } else { | ||||
|  | ||||
| @ -39,7 +39,7 @@ use crate::{ | ||||
| }; | ||||
| use harmony_types::id::Id; | ||||
| 
 | ||||
| use super::prometheus::PrometheusMonitoring; | ||||
| use super::prometheus::PrometheusApplicationMonitoring; | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize)] | ||||
| pub struct K8sPrometheusCRDAlertingScore { | ||||
| @ -49,7 +49,7 @@ pub struct K8sPrometheusCRDAlertingScore { | ||||
|     pub prometheus_rules: Vec<RuleGroup>, | ||||
| } | ||||
| 
 | ||||
| impl<T: Topology + K8sclient + PrometheusMonitoring<CRDPrometheus>> Score<T> | ||||
| impl<T: Topology + K8sclient + PrometheusApplicationMonitoring<CRDPrometheus>> Score<T> | ||||
|     for K8sPrometheusCRDAlertingScore | ||||
| { | ||||
|     fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> { | ||||
| @ -75,7 +75,7 @@ pub struct K8sPrometheusCRDAlertingInterpret { | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + K8sclient + PrometheusMonitoring<CRDPrometheus>> Interpret<T> | ||||
| impl<T: Topology + K8sclient + PrometheusApplicationMonitoring<CRDPrometheus>> Interpret<T> | ||||
|     for K8sPrometheusCRDAlertingInterpret | ||||
| { | ||||
|     async fn execute( | ||||
|  | ||||
| @ -9,17 +9,11 @@ use crate::{ | ||||
| }; | ||||
| 
 | ||||
| #[async_trait] | ||||
| pub trait PrometheusMonitoring<S: AlertSender> { | ||||
| pub trait PrometheusApplicationMonitoring<S: AlertSender> { | ||||
|     async fn install_prometheus( | ||||
|         &self, | ||||
|         sender: &S, | ||||
|         inventory: &Inventory, | ||||
|         receivers: Option<Vec<Box<dyn AlertReceiver<S>>>>, | ||||
|     ) -> Result<PreparationOutcome, PreparationError>; | ||||
| 
 | ||||
|     async fn ensure_prometheus_operator( | ||||
|         &self, | ||||
|         sender: &S, | ||||
|         inventory: &Inventory, | ||||
|     ) -> Result<PreparationOutcome, PreparationError>; | ||||
| } | ||||
|  | ||||
| @ -38,7 +38,7 @@ use crate::{ | ||||
| }; | ||||
| use harmony_types::id::Id; | ||||
| 
 | ||||
| use super::prometheus::PrometheusMonitoring; | ||||
| use super::prometheus::PrometheusApplicationMonitoring; | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize)] | ||||
| pub struct RHOBAlertingScore { | ||||
| @ -48,8 +48,8 @@ pub struct RHOBAlertingScore { | ||||
|     pub prometheus_rules: Vec<RuleGroup>, | ||||
| } | ||||
| 
 | ||||
| impl<T: Topology + K8sclient + Ingress + PrometheusMonitoring<RHOBObservability>> Score<T> | ||||
|     for RHOBAlertingScore | ||||
| impl<T: Topology + K8sclient + Ingress + PrometheusApplicationMonitoring<RHOBObservability>> | ||||
|     Score<T> for RHOBAlertingScore | ||||
| { | ||||
|     fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> { | ||||
|         Box::new(RHOBAlertingInterpret { | ||||
| @ -74,8 +74,8 @@ pub struct RHOBAlertingInterpret { | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + K8sclient + Ingress + PrometheusMonitoring<RHOBObservability>> Interpret<T> | ||||
|     for RHOBAlertingInterpret | ||||
| impl<T: Topology + K8sclient + Ingress + PrometheusApplicationMonitoring<RHOBObservability>> | ||||
|     Interpret<T> for RHOBAlertingInterpret | ||||
| { | ||||
|     async fn execute( | ||||
|         &self, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user