wip: cluster_monitoring almost there, a kink to fix in the yaml handling
All checks were successful
Run Check Script / check (pull_request) Successful in 1m15s
All checks were successful
Run Check Script / check (pull_request) Successful in 1m15s
This commit is contained in:
@@ -77,7 +77,7 @@ pub trait AlertReceiver<S: AlertSender>: std::fmt::Debug + Send + Sync {
|
|||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn clone_box(&self) -> Box<dyn AlertReceiver<S>>;
|
fn clone_box(&self) -> Box<dyn AlertReceiver<S>>;
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver;
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use serde::Serialize;
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_yaml::{Mapping, Value};
|
use serde_yaml::{Mapping, Value};
|
||||||
|
|
||||||
|
use crate::infra::kube::kube_resource_to_dynamic;
|
||||||
use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::{
|
use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::{
|
||||||
AlertmanagerConfig, AlertmanagerConfigSpec, CRDPrometheus,
|
AlertmanagerConfig, AlertmanagerConfigSpec, CRDPrometheus,
|
||||||
};
|
};
|
||||||
@@ -36,7 +37,7 @@ pub struct DiscordWebhook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiscordWebhook {
|
impl DiscordWebhook {
|
||||||
fn get_receiver_config(&self) -> AlertManagerReceiver {
|
fn get_receiver_config(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
let secret_name = format!("{}-secret", self.name.clone());
|
let secret_name = format!("{}-secret", self.name.clone());
|
||||||
let webhook_key = format!("{}", self.url.clone());
|
let webhook_key = format!("{}", self.url.clone());
|
||||||
|
|
||||||
@@ -53,8 +54,8 @@ impl DiscordWebhook {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
AlertManagerReceiver {
|
Ok(AlertManagerReceiver {
|
||||||
additional_ressources: vec![],
|
additional_ressources: vec![kube_resource_to_dynamic(&secret)?],
|
||||||
|
|
||||||
receiver_config: json!({
|
receiver_config: json!({
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
@@ -69,7 +70,7 @@ impl DiscordWebhook {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,21 +95,21 @@ impl AlertReceiver<OpenshiftClusterAlertSender> for DiscordWebhook {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
self.get_receiver_config()
|
self.get_receiver_config()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<RHOBObservability> for DiscordWebhook {
|
impl AlertReceiver<RHOBObservability> for DiscordWebhook {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn install(&self, sender: &RHOBObservability) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &RHOBObservability) -> Result<Outcome, InterpretError> {
|
||||||
let ns = sender.namespace.clone();
|
let ns = sender.namespace.clone();
|
||||||
|
|
||||||
let config = self.get_receiver_config();
|
let config = self.get_receiver_config()?;
|
||||||
for resource in config.additional_ressources.iter() {
|
for resource in config.additional_ressources.iter() {
|
||||||
todo!("can I apply a dynamicresource");
|
todo!("can I apply a dynamicresource");
|
||||||
// sender.client.apply(resource, Some(&ns)).await;
|
// sender.client.apply(resource, Some(&ns)).await;
|
||||||
@@ -171,7 +172,7 @@ impl AlertReceiver<RHOBObservability> for DiscordWebhook {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<CRDPrometheus> for DiscordWebhook {
|
impl AlertReceiver<CRDPrometheus> for DiscordWebhook {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &CRDPrometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &CRDPrometheus) -> Result<Outcome, InterpretError> {
|
||||||
@@ -252,7 +253,7 @@ impl AlertReceiver<CRDPrometheus> for DiscordWebhook {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<Prometheus> for DiscordWebhook {
|
impl AlertReceiver<Prometheus> for DiscordWebhook {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &Prometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &Prometheus) -> Result<Outcome, InterpretError> {
|
||||||
@@ -281,7 +282,7 @@ impl PrometheusReceiver for DiscordWebhook {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<KubePrometheus> for DiscordWebhook {
|
impl AlertReceiver<KubePrometheus> for DiscordWebhook {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &KubePrometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &KubePrometheus) -> Result<Outcome, InterpretError> {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pub struct WebhookReceiver {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<RHOBObservability> for WebhookReceiver {
|
impl AlertReceiver<RHOBObservability> for WebhookReceiver {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &RHOBObservability) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &RHOBObservability) -> Result<Outcome, InterpretError> {
|
||||||
@@ -100,7 +100,7 @@ impl AlertReceiver<RHOBObservability> for WebhookReceiver {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<CRDPrometheus> for WebhookReceiver {
|
impl AlertReceiver<CRDPrometheus> for WebhookReceiver {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &CRDPrometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &CRDPrometheus) -> Result<Outcome, InterpretError> {
|
||||||
@@ -164,7 +164,7 @@ impl AlertReceiver<CRDPrometheus> for WebhookReceiver {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<Prometheus> for WebhookReceiver {
|
impl AlertReceiver<Prometheus> for WebhookReceiver {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &Prometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &Prometheus) -> Result<Outcome, InterpretError> {
|
||||||
@@ -193,7 +193,7 @@ impl PrometheusReceiver for WebhookReceiver {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AlertReceiver<KubePrometheus> for WebhookReceiver {
|
impl AlertReceiver<KubePrometheus> for WebhookReceiver {
|
||||||
fn as_alertmanager_receiver(&self) -> AlertManagerReceiver {
|
fn as_alertmanager_receiver(&self) -> Result<AlertManagerReceiver, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
async fn install(&self, sender: &KubePrometheus) -> Result<Outcome, InterpretError> {
|
async fn install(&self, sender: &KubePrometheus) -> Result<Outcome, InterpretError> {
|
||||||
|
|||||||
@@ -81,43 +81,76 @@ impl<T: Topology + K8sclient> Interpret<T> for OpenshiftClusterAlertInterpret {
|
|||||||
trace!("Got secret {secret:?}");
|
trace!("Got secret {secret:?}");
|
||||||
|
|
||||||
let data: serde_json::Value = secret.data;
|
let data: serde_json::Value = secret.data;
|
||||||
|
trace!("Alertmanager-main secret data {data:#?}");
|
||||||
|
|
||||||
// TODO : get config in base64 by drilling into the value
|
// TODO fix this unwrap, handle the option gracefully
|
||||||
let config_b64 = match data.get("alertmanager.yaml") {
|
let config_b64 = match data.get("data") {
|
||||||
Some(value) => value.as_str().unwrap_or(""),
|
Some(data_value) => match data_value.get("alertmanager.yaml") {
|
||||||
None => "",
|
Some(value) => value.as_str().unwrap_or(""),
|
||||||
|
None => {
|
||||||
|
return Err(InterpretError::new(
|
||||||
|
"Missing 'alertmanager.yaml' in alertmanager-main secret".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Err(InterpretError::new(
|
||||||
|
"Missing 'data' field in alertmanager-main secret.".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
trace!("Config base64 {config_b64}");
|
||||||
|
|
||||||
// TODO : base64 decode it
|
|
||||||
let config_bytes = BASE64_STANDARD.decode(config_b64).unwrap_or_default();
|
let config_bytes = BASE64_STANDARD.decode(config_b64).unwrap_or_default();
|
||||||
|
|
||||||
// TODO : use serde_yaml to deserialize the string
|
let mut am_config: serde_yaml::Value =
|
||||||
let am_config: serde_yaml::Value =
|
|
||||||
serde_yaml::from_str(&String::from_utf8(config_bytes).unwrap_or_default())
|
serde_yaml::from_str(&String::from_utf8(config_bytes).unwrap_or_default())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Merge current alert receivers from this config with self.receivers
|
debug!("Current alertmanager config {am_config:#?}");
|
||||||
if let Some(existing_receivers) = am_config.get("receivers") {
|
|
||||||
for receiver in existing_receivers.as_sequence().unwrap_or(&vec![]) {
|
let existing_receivers = if let Some(receivers) = am_config.get_mut("receivers") {
|
||||||
match serde_json::to_string(receiver) {
|
match receivers.as_mapping_mut() {
|
||||||
Ok(yaml_str) => {
|
Some(recv) => recv,
|
||||||
// TODO: validate that each receiver implements to_alertmanager_yaml()
|
None => {
|
||||||
// and compare with our receivers
|
return Err(InterpretError::new(format!(
|
||||||
info!("Found existing receiver config: {}", yaml_str);
|
"Expected alertmanager config receivers to be a mapping, got {receivers:?}"
|
||||||
}
|
)));
|
||||||
Err(e) => debug!("Failed to serialize receiver: {}", e),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
&mut serde_yaml::mapping::Mapping::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
trace!("Existing receivers : {existing_receivers:#?}");
|
||||||
|
|
||||||
for custom_receiver in &self.receivers {
|
for custom_receiver in &self.receivers {
|
||||||
trace!("Processing custom receiver");
|
let name = &custom_receiver.name();
|
||||||
|
if let Some(recv) = existing_receivers.get(name) {
|
||||||
|
info!(
|
||||||
|
"AlertManager receiver {name} already exists and will be overwritten : {recv:#?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"Custom receiver YAML output: {:?}",
|
"Custom receiver YAML output: {:?}",
|
||||||
custom_receiver.as_alertmanager_receiver()
|
custom_receiver.as_alertmanager_receiver()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let json_value = custom_receiver.as_alertmanager_receiver()?.receiver_config;
|
||||||
|
let yaml_string = serde_json::to_string(&json_value).map_err(|e| {
|
||||||
|
InterpretError::new(format!("Failed to serialize receiver config: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let yaml_value: serde_yaml::Value =
|
||||||
|
serde_yaml::from_str(&yaml_string).map_err(|e| {
|
||||||
|
InterpretError::new(format!("Failed to parse receiver config as YAML: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
existing_receivers.insert(serde_yaml::Value::from(name.as_str()), yaml_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Current alertmanager config {am_config:#?}");
|
||||||
|
|
||||||
Ok(Outcome::success(todo!("whats up")))
|
Ok(Outcome::success(todo!("whats up")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user