From ec1df0413af59dbe73fb37bdec7579c784d2b724 Mon Sep 17 00:00:00 2001 From: Willem Date: Thu, 19 Jun 2025 11:06:20 -0400 Subject: [PATCH] wip: implentation for kube prometheus monitoring alert sender --- examples/lamp/php/Dockerfile | 18 ++++ examples/lamp/php/docker-php.ini | 16 ++++ examples/lamp/src/main.rs | 5 +- .../alert_channel/discord_alert_channel.rs | 87 ++++++++++++++++++- .../helm_prometheus_alert_score.rs | 5 +- .../monitoring/kube_prometheus/types.rs | 15 ++-- 6 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 examples/lamp/php/Dockerfile create mode 100644 examples/lamp/php/docker-php.ini diff --git a/examples/lamp/php/Dockerfile b/examples/lamp/php/Dockerfile new file mode 100644 index 0000000..df5f4fa --- /dev/null +++ b/examples/lamp/php/Dockerfile @@ -0,0 +1,18 @@ +FROM php:8.4-apache +ENV PHP_MEMORY_LIMIT=256M +ENV PHP_MAX_EXECUTION_TIME=30 +ENV PHP_ERROR_REPORTING="E_ERROR | E_WARNING | E_PARSE" +RUN apt-get update && apt-get install -y --no-install-recommends libfreetype6-dev libjpeg62-turbo-dev libpng-dev libzip-dev unzip && apt-get clean && rm -rf /var/lib/apt/lists/* +RUN docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install -j$(nproc) gd mysqli pdo_mysql zip opcache +RUN sed -i 's/VirtualHost \*:80/VirtualHost *:8080/' /etc/apache2/sites-available/000-default.conf && \ + sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.conf +RUN mkdir -p /usr/local/etc/php/conf.d/ +COPY docker-php.ini /usr/local/etc/php/conf.d/docker-php.ini +RUN a2enmod headers && a2enmod rewrite && sed -i 's/ServerTokens OS/ServerTokens Prod/' /etc/apache2/conf-enabled/security.conf && sed -i 's/ServerSignature On/ServerSignature Off/' /etc/apache2/conf-enabled/security.conf +RUN echo 'PassEnv MYSQL_PASSWORD' >> /etc/apache2/sites-available/000-default.conf && echo 'PassEnv MYSQL_USER' >> /etc/apache2/sites-available/000-default.conf && echo 'PassEnv MYSQL_HOST' >> /etc/apache2/sites-available/000-default.conf +RUN groupadd -g 1000 appuser && useradd -u 1000 -g appuser -m -s /bin/bash appuser && chown -R appuser:appuser /var/www/html +WORKDIR /var/www/html +COPY . /var/www/html +RUN chown -R appuser:appuser /var/www/html +EXPOSE 8080/tcp +CMD apache2-foreground \ No newline at end of file diff --git a/examples/lamp/php/docker-php.ini b/examples/lamp/php/docker-php.ini new file mode 100644 index 0000000..3745ad5 --- /dev/null +++ b/examples/lamp/php/docker-php.ini @@ -0,0 +1,16 @@ + +memory_limit = ${PHP_MEMORY_LIMIT} +max_execution_time = ${PHP_MAX_EXECUTION_TIME} +error_reporting = ${PHP_ERROR_REPORTING} +display_errors = Off +log_errors = On +error_log = /dev/stderr +date.timezone = UTC + +; Opcache configuration for production +opcache.enable=1 +opcache.memory_consumption=128 +opcache.interned_strings_buffer=8 +opcache.max_accelerated_files=4000 +opcache.revalidate_freq=2 +opcache.fast_shutdown=1 diff --git a/examples/lamp/src/main.rs b/examples/lamp/src/main.rs index 0b1f93c..4518165 100644 --- a/examples/lamp/src/main.rs +++ b/examples/lamp/src/main.rs @@ -2,10 +2,7 @@ use harmony::{ data::Version, inventory::Inventory, maestro::Maestro, - modules::{ - lamp::{LAMPConfig, LAMPScore}, - monitoring::alert_channel::discord_alert_channel::DiscordWebhook, - }, + modules::lamp::{LAMPConfig, LAMPScore}, topology::{K8sAnywhereTopology, Url}, }; 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 42f4450..10f4d72 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -1,8 +1,12 @@ use async_trait::async_trait; +use serde_yaml::{Mapping, Value}; use crate::{ interpret::InterpretError, - modules::monitoring::kube_prometheus::prometheus::{Prometheus, PrometheusReceiver}, + modules::monitoring::kube_prometheus::{ + prometheus::{Prometheus, PrometheusReceiver}, + types::AlertChannelConfig, + }, topology::{Url, oberservability::monitoring::AlertReceiver}, }; @@ -18,3 +22,84 @@ impl AlertReceiver for DiscordWebhook { sender.install_receiver(PrometheusReceiver {}).await } } + +impl AlertChannelConfig for DiscordWebhook { + fn alert_channel_global_config(&self) -> Option { + None + } + + fn alert_channel_route(&self) -> serde_yaml::Value { + let mut route = Mapping::new(); + route.insert( + Value::String("receiver".to_string()), + Value::String(self.name.clone()), + ); + route.insert( + Value::String("matchers".to_string()), + Value::Sequence(vec![Value::String("alertname!=Watchdog".to_string())]), + ); + route.insert(Value::String("continue".to_string()), Value::Bool(true)); + Value::Mapping(route) + } + + fn alert_channel_receiver(&self) -> serde_yaml::Value { + let mut receiver = Mapping::new(); + receiver.insert( + Value::String("name".to_string()), + Value::String(self.name.clone()), + ); + + let mut discord_config = Mapping::new(); + discord_config.insert( + Value::String("webhook_url".to_string()), + Value::String(self.url.to_string()), + ); + + receiver.insert( + Value::String("discord_configs".to_string()), + Value::Sequence(vec![Value::Mapping(discord_config)]), + ); + + Value::Mapping(receiver) + } +} + +#[cfg(test)] +mod tests { + use log::debug; + + use super::*; + + #[test] + fn discord_serialize_should_match() { + let discord_receiver = DiscordWebhook { + name: "test-discord".to_string(), + url: Url::Url(url::Url::parse("https://discord.i.dont.exist.com").unwrap()), + }; + + let discord_receiver_global = + serde_yaml::to_string(&discord_receiver.alert_channel_global_config()).unwrap(); + println!("global receiver \n{:#}", discord_receiver_global); + let discord_receiver_global_yaml = "".to_string(); + + let discord_receiver_receiver = + serde_yaml::to_string(&discord_receiver.alert_channel_receiver()).unwrap(); + println!("receiver \n{:#}", discord_receiver_receiver); + let discord_receiver_receiver_yaml = r#"name: test-discord +discord_configs: +- webhook_url: https://discord.i.dont.exist.com/"# + .to_string(); + + let discord_receiver_route = + serde_yaml::to_string(&discord_receiver.alert_channel_route()).unwrap(); + println!("route \n{:#}", discord_receiver_route); + let discord_receiver_route_yaml = r#"receiver: test-discord +matchers: +- alertname!=Watchdog +continue: true"# + .to_string(); + + assert_eq!(discord_receiver_receiver, discord_receiver_receiver_yaml); + assert_eq!(discord_receiver_route, discord_receiver_route_yaml); + } +} diff --git a/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs b/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs index c090f13..3cfd447 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/helm_prometheus_alert_score.rs @@ -20,10 +20,7 @@ impl Score for HelmPrometheusAlertingScore { fn create_interpret(&self) -> Box> { Box::new(AlertingInterpret { sender: Prometheus {}, - receivers: vec![Box::new(DiscordWebhook { - url: todo!(), - name: todo!(), - })], + receivers: self.receivers.clone(), }) } diff --git a/harmony/src/modules/monitoring/kube_prometheus/types.rs b/harmony/src/modules/monitoring/kube_prometheus/types.rs index 224b125..08d1b7d 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/types.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/types.rs @@ -1,12 +1,7 @@ -use serde::Serialize; +use serde_yaml::Value; -#[derive(Serialize)] -pub struct AlertReceiverRoute { - pub receiver: String, - pub matchers: Vec, - #[serde(default)] - pub r#continue: bool, -} -pub struct AlertChannelReceiver { - pub name: String, +pub trait AlertChannelConfig { + fn alert_channel_global_config(&self) -> Option; + fn alert_channel_route(&self) -> Value; + fn alert_channel_receiver(&self) -> Value; }