controller/
configmap.rs

1use crate::{apis::coredb_types::CoreDB, Context, Error};
2use k8s_openapi::api::core::v1::ConfigMap;
3use kube::{
4    api::{Api, ObjectMeta, Patch, PatchParams},
5    runtime::controller::Action,
6    Client, ResourceExt,
7};
8use std::{collections::BTreeMap, sync::Arc};
9
10use tracing::{debug, error, instrument};
11
12#[instrument(skip(cdb, ctx) fields(trace_id, instance_name = %cdb.name_any()))]
13pub async fn reconcile_generic_metrics_configmap(
14    cdb: &CoreDB,
15    ctx: Arc<Context>,
16) -> Result<(), Action> {
17    let (custom_metrics_namespace, custom_metrics_name) = match custom_metrics_configmap_settings()
18    {
19        Some(value) => value,
20        _ => return Ok(()),
21    };
22
23    let namespace = cdb.namespace().unwrap();
24    let client = ctx.client.clone();
25    let configmap_api_dataplane_namespace: Api<ConfigMap> =
26        Api::namespaced(client.clone(), &custom_metrics_namespace);
27
28    let configmap_name = format!("{}-custom", cdb.name_any());
29
30    match configmap_api_dataplane_namespace
31        .get(&custom_metrics_name)
32        .await
33    {
34        Ok(original_configmap) => {
35            let data = original_configmap.data.clone().unwrap_or_default();
36            match apply_configmap(client, &namespace, &configmap_name, data).await {
37                Ok(_) => {
38                    debug!(
39                        "ConfigMap data applied successfully to namespace '{}'",
40                        namespace
41                    );
42                }
43                Err(e) => {
44                    error!(
45                        "Failed to apply ConfigMap in namespace '{}': {:?}",
46                        namespace, e
47                    );
48                    return Err(Action::requeue(std::time::Duration::from_secs(300)));
49                }
50            }
51        }
52        Err(e) => {
53            println!(
54                "Failed to get ConfigMap from '{}' namespace: {:?}",
55                &custom_metrics_namespace, e
56            );
57            return Err(Action::requeue(std::time::Duration::from_secs(300)));
58        }
59    }
60
61    Ok(())
62}
63
64pub fn custom_metrics_configmap_settings() -> Option<(String, String)> {
65    let custom_metrics_namespace = match std::env::var("CUSTOM_METRICS_CONFIGMAP_NAMESPACE") {
66        Ok(namespace) => namespace,
67        Err(_) => {
68            debug!("CUSTOM_METRICS_CONFIGMAP_NAMESPACE not set, skipping adding custom metrics");
69            return None;
70        }
71    };
72    let custom_metrics_name = match std::env::var("CUSTOM_METRICS_CONFIGMAP_NAME") {
73        Ok(name) => name,
74        Err(_) => {
75            debug!("CUSTOM_METRICS_CONFIGMAP_NAME not set, skipping adding custom metrics");
76            return None;
77        }
78    };
79    Some((custom_metrics_namespace, custom_metrics_name))
80}
81
82pub async fn apply_configmap(
83    client: Client,
84    namespace: &str,
85    cm_name: &str,
86    data: BTreeMap<String, String>,
87) -> Result<(), Error> {
88    let mut labels: BTreeMap<String, String> = BTreeMap::new();
89    labels.insert("cnpg.io/reload".to_owned(), "true".to_owned());
90    let cm_api: Api<ConfigMap> = Api::namespaced(client, namespace);
91    let cm = ConfigMap {
92        metadata: ObjectMeta {
93            name: Some(cm_name.to_string()),
94            labels: Some(labels),
95            ..Default::default()
96        },
97        data: Some(data),
98        ..Default::default()
99    };
100
101    let patch_params = PatchParams::apply("cntrlr");
102    let patch = Patch::Apply(&cm);
103
104    match cm_api.patch(cm_name, &patch_params, &patch).await {
105        Ok(o) => {
106            debug!("Set configmap: {}", o.metadata.name.unwrap());
107        }
108        Err(e) => {
109            error!("Failed to set configmap: {}", e);
110        }
111    };
112    Ok(())
113}