wip: trying to install the helm chart for HelmKubePrometheus

This commit is contained in:
Willem 2025-06-19 16:40:00 -04:00 committed by tahahawa
parent 50e38fed0a
commit a41230ac7b
7 changed files with 113 additions and 42 deletions

View File

@ -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::<K8sAnywhereTopology>::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();
}

View File

@ -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>;

View File

@ -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<Outcome, InterpretError>;
}
#[derive(Debug)]
pub struct AlertingInterpret<S: AlertSender> {
@ -16,7 +20,7 @@ pub struct AlertingInterpret<S: AlertSender> {
}
#[async_trait]
impl<S: AlertSender, T: Topology> Interpret<T> for AlertingInterpret<S> {
impl<S: AlertSender + Installable, T: Topology> Interpret<T> for AlertingInterpret<S> {
async fn execute(
&self,
inventory: &Inventory,
@ -25,7 +29,11 @@ impl<S: AlertSender, T: Topology> Interpret<T> for AlertingInterpret<S> {
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<S: AlertSender, T: Topology> Interpret<T> for AlertingInterpret<S> {
#[async_trait]
pub trait AlertReceiver<S: AlertSender>: std::fmt::Debug + Send + Sync {
async fn install(&self, sender: &S) -> Result<(), InterpretError>;
async fn install(&self, sender: &S) -> Result<Outcome, InterpretError>;
fn clone_box(&self) -> Box<dyn AlertReceiver<S>>;
}

View File

@ -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<Prometheus> for DiscordWebhook {
async fn install(&self, sender: &Prometheus) -> Result<(), InterpretError> {
async fn install(&self, sender: &Prometheus) -> Result<Outcome, InterpretError> {
sender.install_receiver(self).await
}
fn clone_box(&self) -> Box<dyn AlertReceiver<Prometheus>> {
@ -29,8 +29,11 @@ impl AlertReceiver<Prometheus> for DiscordWebhook {
#[async_trait]
impl PrometheusReceiver for DiscordWebhook {
//TODO not return a tuple
async fn receiver_config(&self) -> (Option<Value>, 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
}
}

View File

@ -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();

View File

@ -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<Box<dyn AlertReceiver<Prometheus>>>,
}
impl<T: Topology + HelmCommand> Score<T> for HelmPrometheusAlertingScore {
impl<T: Topology + HelmCommand + Installable> Score<T> for HelmPrometheusAlertingScore {
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
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()
}
}

View File

@ -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<Outcome, InterpretError> {
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<KubePrometheusConfig>,
}
impl Prometheus {
pub async fn install_receiver(
&self,
prometheus_receiver: &dyn PrometheusReceiver,
) -> Result<(), InterpretError> {
) -> Result<Outcome, InterpretError> {
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<Outcome, InterpretError> {
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, 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
}