From 415488ba39012cfc7ff665cad065bfb4d0475893 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Mon, 9 Jun 2025 20:19:54 +0000 Subject: [PATCH] feat: K8s apply function now correctly emulates kubectl apply behavior by either creating or updating resources (#55) Reviewed-on: https://git.nationtech.io/NationTech/harmony/pulls/55 Co-authored-by: Jean-Gabriel Gill-Couture Co-committed-by: Jean-Gabriel Gill-Couture --- examples/lamp/src/main.rs | 5 +---- harmony/src/domain/topology/k8s.rs | 22 ++++++++++++++----- harmony/src/domain/topology/k8s_anywhere.rs | 8 +++---- .../topology/oberservability/monitoring.rs | 1 - harmony/src/domain/topology/tenant/k8s.rs | 9 +++----- harmony/src/modules/helm/command.rs | 4 ++-- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/examples/lamp/src/main.rs b/examples/lamp/src/main.rs index 74df0d8..14180cc 100644 --- a/examples/lamp/src/main.rs +++ b/examples/lamp/src/main.rs @@ -4,7 +4,7 @@ use harmony::{ maestro::Maestro, modules::{ lamp::{LAMPConfig, LAMPScore}, - monitoring::monitoring_alerting::{AlertChannel, MonitoringAlertingStackScore}, + monitoring::monitoring_alerting::MonitoringAlertingStackScore, }, topology::{K8sAnywhereTopology, Url}, }; @@ -43,9 +43,6 @@ async fn main() { .await .unwrap(); - let url = url::Url::parse("https://discord.com/api/webhooks/dummy_channel/dummy_token") - .expect("invalid URL"); - let mut monitoring_stack_score = MonitoringAlertingStackScore::new(); monitoring_stack_score.namespace = Some(lamp_stack.config.namespace.clone()); diff --git a/harmony/src/domain/topology/k8s.rs b/harmony/src/domain/topology/k8s.rs index cfaae1f..4a001c4 100644 --- a/harmony/src/domain/topology/k8s.rs +++ b/harmony/src/domain/topology/k8s.rs @@ -2,7 +2,7 @@ use derive_new::new; use k8s_openapi::{ClusterResourceScope, NamespaceResourceScope}; use kube::{ Api, Client, Config, Error, Resource, - api::PostParams, + api::{Patch, PatchParams}, config::{KubeConfigOptions, Kubeconfig}, }; use log::{debug, error, trace}; @@ -20,7 +20,10 @@ impl K8sClient { }) } - pub async fn apply(&self, resource: &K, ns: Option<&str>) -> Result + /// Apply a resource in namespace + /// + /// See `kubectl apply` for more information on the expected behavior of this function + pub async fn apply(&self, resource: &K, namespace: Option<&str>) -> Result where K: Resource + Clone + std::fmt::Debug + DeserializeOwned + serde::Serialize, ::Scope: ApplyStrategy, @@ -29,12 +32,21 @@ impl K8sClient { debug!( "Applying resource {:?} with ns {:?}", resource.meta().name, - ns + namespace ); trace!("{:#?}", serde_json::to_string(resource)); - let api: Api = <::Scope as ApplyStrategy>::get_api(&self.client, ns); - api.create(&PostParams::default(), &resource).await + let api: Api = + <::Scope as ApplyStrategy>::get_api(&self.client, namespace); + // api.create(&PostParams::default(), &resource).await + let patch_params = PatchParams::apply("harmony"); + let name = resource + .meta() + .name + .as_ref() + .expect("K8s Resource should have a name"); + api.patch(name, &patch_params, &Patch::Apply(resource)) + .await } pub async fn apply_many(&self, resource: &Vec, ns: Option<&str>) -> Result, Error> diff --git a/harmony/src/domain/topology/k8s_anywhere.rs b/harmony/src/domain/topology/k8s_anywhere.rs index fd0685d..f1d5a27 100644 --- a/harmony/src/domain/topology/k8s_anywhere.rs +++ b/harmony/src/domain/topology/k8s_anywhere.rs @@ -1,4 +1,4 @@ -use std::{io::Error, process::Command, sync::Arc}; +use std::{process::Command, sync::Arc}; use async_trait::async_trait; use inquire::Confirm; @@ -25,7 +25,7 @@ use super::{ struct K8sState { client: Arc, - source: K8sSource, + _source: K8sSource, message: String, } @@ -122,7 +122,7 @@ impl K8sAnywhereTopology { Some(client) => { return Ok(Some(K8sState { client: Arc::new(client), - source: K8sSource::Kubeconfig, + _source: K8sSource::Kubeconfig, message: format!("Loaded k8s client from kubeconfig {kubeconfig}"), })); } @@ -162,7 +162,7 @@ impl K8sAnywhereTopology { let state = match k3d.get_client().await { Ok(client) => K8sState { client: Arc::new(K8sClient::new(client)), - source: K8sSource::LocalK3d, + _source: K8sSource::LocalK3d, message: "Successfully installed K3D cluster and acquired client".to_string(), }, Err(_) => todo!(), diff --git a/harmony/src/domain/topology/oberservability/monitoring.rs b/harmony/src/domain/topology/oberservability/monitoring.rs index 4603eba..51ec38e 100644 --- a/harmony/src/domain/topology/oberservability/monitoring.rs +++ b/harmony/src/domain/topology/oberservability/monitoring.rs @@ -1,7 +1,6 @@ use async_trait::async_trait; use std::fmt::Debug; -use url::Url; use crate::interpret::InterpretError; diff --git a/harmony/src/domain/topology/tenant/k8s.rs b/harmony/src/domain/topology/tenant/k8s.rs index ed51d96..6bef378 100644 --- a/harmony/src/domain/topology/tenant/k8s.rs +++ b/harmony/src/domain/topology/tenant/k8s.rs @@ -3,12 +3,9 @@ use std::sync::Arc; use crate::{data::Id, executors::ExecutorError, topology::k8s::K8sClient}; use async_trait::async_trait; use derive_new::new; -use k8s_openapi::{ - NamespaceResourceScope, - api::{ - core::v1::{Namespace, ResourceQuota}, - networking::v1::NetworkPolicy, - }, +use k8s_openapi::api::{ + core::v1::{Namespace, ResourceQuota}, + networking::v1::NetworkPolicy, }; use kube::Resource; use serde::de::DeserializeOwned; diff --git a/harmony/src/modules/helm/command.rs b/harmony/src/modules/helm/command.rs index 41db685..14d2fc1 100644 --- a/harmony/src/modules/helm/command.rs +++ b/harmony/src/modules/helm/command.rs @@ -311,7 +311,7 @@ impl Interpret for HelmChartInterpretV _inventory: &Inventory, _topology: &T, ) -> Result { - let ns = self + let _ns = self .score .chart .namespace @@ -339,7 +339,7 @@ impl Interpret for HelmChartInterpretV let res = helm_executor.generate(); - let output = match res { + let _output = match res { Ok(output) => output, Err(err) => return Err(InterpretError::new(err.to_string())), };