wip: applied comments in pr, changed naming of AlertChannel to AlertReceiver and added rust doc to Monitor for clarity
All checks were successful
Run Check Script / check (push) Successful in 1m49s
Run Check Script / check (pull_request) Successful in 1m47s

This commit is contained in:
Willem 2025-06-02 14:44:43 -04:00
parent 56dc1e93c1
commit 0d56fbc09d
4 changed files with 61 additions and 68 deletions

View File

@ -8,26 +8,32 @@ use crate::interpret::InterpretError;
use crate::{interpret::Outcome, topology::Topology}; use crate::{interpret::Outcome, topology::Topology};
/// Represents an entity responsible for collecting and organizing observability data
/// from various telemetry sources
/// A `Monitor` abstracts the logic required to scrape, aggregate, and structure
/// monitoring data, enabling consistent processing regardless of the underlying data source.
#[async_trait] #[async_trait]
pub trait Monitor<T: Topology>: Debug + Send + Sync { pub trait Monitor<T: Topology>: Debug + Send + Sync {
async fn deploy_monitor( async fn deploy_monitor(
&self, &self,
topology: &T, topology: &T,
config: Vec<Box<dyn AlertChannelConfig<T>>>, alert_receivers: Vec<Box<dyn AlertReceiver<T>>>,
) -> Result<Outcome, InterpretError>; ) -> Result<Outcome, InterpretError>;
async fn delete_monitor( async fn delete_monitor(
&self, &self,
topolgy: &T, topolgy: &T,
config: Vec<Box<dyn AlertChannelConfig<T>>>, alert_receivers: Vec<Box<dyn AlertReceiver<T>>>,
) -> Result<Outcome, InterpretError>; ) -> Result<Outcome, InterpretError>;
} }
#[async_trait] #[async_trait]
pub trait AlertChannelConfig<T>: Debug + DynClone + Send + Sync { pub trait AlertReceiver<T>: Debug + DynClone + Send + Sync {
fn channel_identifier(&self) -> String; fn get_alert_receiver_config(&self) -> AlertReceiverConfig;
}
fn webhook_url(&self) -> Option<Url>;
pub struct AlertReceiverConfig {
fn send_resolved_notifications(&self) -> bool; pub receiver_id: String,
pub receiver_webhook_url: Option<Url>,
pub send_resolved: bool,
} }

View File

@ -1,30 +1,25 @@
use std::str::FromStr; use std::str::FromStr;
use non_blank_string_rs::NonBlankString; use non_blank_string_rs::NonBlankString;
use url::Url;
use crate::modules::helm::chart::HelmChartScore; use crate::modules::helm::chart::HelmChartScore;
use super::{config::KubePrometheusConfig, monitoring_alerting::AlertChannel}; pub fn discord_alert_manager_score(
webhook_url: Url,
fn get_discord_alert_manager_score(config: &KubePrometheusConfig) -> Option<HelmChartScore> { namespace: String,
let (url, name) = config.alert_channel.iter().find_map(|channel| { name: String,
if let AlertChannel::Discord { webhook_url, name } = channel { ) -> HelmChartScore {
Some((webhook_url, name))
} else {
None
}
})?;
let values = format!( let values = format!(
r#" r#"
environment: environment:
- name: "DISCORD_WEBHOOK" - name: "DISCORD_WEBHOOK"
value: "{url}" value: "{webhook_url}"
"#, "#,
); );
Some(HelmChartScore { HelmChartScore {
namespace: Some(NonBlankString::from_str(&config.namespace).unwrap()), namespace: Some(NonBlankString::from_str(&namespace).unwrap()),
release_name: NonBlankString::from_str(&name).unwrap(), release_name: NonBlankString::from_str(&name).unwrap(),
chart_name: NonBlankString::from_str( chart_name: NonBlankString::from_str(
"oci://hub.nationtech.io/library/alertmanager-discord", "oci://hub.nationtech.io/library/alertmanager-discord",
@ -36,13 +31,5 @@ environment:
create_namespace: true, create_namespace: true,
install_only: true, install_only: true,
repository: None, repository: None,
})
}
pub fn discord_alert_manager_score(config: &KubePrometheusConfig) -> HelmChartScore {
if let Some(chart) = get_discord_alert_manager_score(config) {
chart
} else {
panic!("Expected discord alert manager helm chart");
} }
} }

View File

@ -3,7 +3,10 @@ use url::Url;
use crate::{ use crate::{
interpret::{InterpretError, Outcome}, interpret::{InterpretError, Outcome},
topology::{K8sAnywhereTopology, Topology, oberservability::monitoring::AlertChannelConfig}, topology::{
K8sAnywhereTopology, Topology,
oberservability::monitoring::{AlertReceiver, AlertReceiverConfig},
},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -13,41 +16,38 @@ pub struct DiscordWebhookConfig {
pub send_resolved_notifications: bool, pub send_resolved_notifications: bool,
} }
pub trait DiscordWebhookSender { pub trait DiscordWebhookReceiver {
fn deploy_discord_webhook_sender( fn deploy_discord_webhook_receiver(
&self, &self,
_notification_adapter_id: &str, _notification_adapter_id: &str,
) -> Result<Outcome, InterpretError>; ) -> Result<Outcome, InterpretError>;
fn delete_discord_webhook_sender( fn delete_discord_webhook_receiver(
&self, &self,
_notification_adapter_id: &str, _notification_adapter_id: &str,
) -> Result<Outcome, InterpretError>; ) -> Result<Outcome, InterpretError>;
} }
#[async_trait] #[async_trait]
impl<T: Topology + DiscordWebhookSender> AlertChannelConfig<T> for DiscordWebhookConfig { impl<T: DiscordWebhookReceiver> AlertReceiver<T> for DiscordWebhookConfig {
fn channel_identifier(&self) -> String { fn get_alert_receiver_config(&self) -> AlertReceiverConfig {
self.name.clone() AlertReceiverConfig {
receiver_id: self.name.clone(),
receiver_webhook_url: Some(self.webhook_url.clone()),
send_resolved: self.send_resolved_notifications.clone(),
} }
fn webhook_url(&self) -> Option<Url> {
Some(self.webhook_url.clone())
}
fn send_resolved_notifications(&self) -> bool {
self.send_resolved_notifications.clone()
} }
} }
#[async_trait] #[async_trait]
impl DiscordWebhookSender for K8sAnywhereTopology { impl DiscordWebhookReceiver for K8sAnywhereTopology {
fn deploy_discord_webhook_sender( fn deploy_discord_webhook_receiver(
&self, &self,
_notification_adapter_id: &str, _notification_adapter_id: &str,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {
todo!() todo!()
} }
fn delete_discord_webhook_sender( fn delete_discord_webhook_receiver(
&self, &self,
_notification_adapter_id: &str, _notification_adapter_id: &str,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {

View File

@ -96,28 +96,28 @@ impl MonitoringAlertingStackInterpret {
topology: &T, topology: &T,
config: &KubePrometheusConfig, config: &KubePrometheusConfig,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {
let mut outcomes = vec![]; //let mut outcomes = vec![];
for channel in &self.score.alert_channel { //for channel in &self.score.alert_channel {
let outcome = match channel { // let outcome = match channel {
AlertChannel::Discord { .. } => { // AlertChannel::Discord { .. } => {
discord_alert_manager_score(config) // discord_alert_manager_score(config)
.create_interpret() // .create_interpret()
.execute(inventory, topology) // .execute(inventory, topology)
.await // .await
} // }
AlertChannel::Slack { .. } => Ok(Outcome::success( // AlertChannel::Slack { .. } => Ok(Outcome::success(
"No extra configs for slack alerting".to_string(), // "No extra configs for slack alerting".to_string(),
)), // )),
AlertChannel::Smpt { .. } => { // AlertChannel::Smpt { .. } => {
todo!() // todo!()
} // }
}; // };
outcomes.push(outcome); // outcomes.push(outcome);
} //}
for result in outcomes { //for result in outcomes {
result?; // result?;
} //}
Ok(Outcome::success("All alert channels deployed".to_string())) Ok(Outcome::success("All alert channels deployed".to_string()))
} }