From c74c51090a550567bfbd8b8b7ed3459eef28a1ac Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Wed, 2 Jul 2025 07:53:14 -0400 Subject: [PATCH 1/2] feat: Introduce Application trait, not too sure how it will evolve but it makes sense, at the very least to identify the Application, also some minor refactoring --- .../features/continuous_delivery.rs | 3 + .../modules/application/features/endpoint.rs | 3 + .../application/features/monitoring.rs | 3 + harmony/src/modules/application/mod.rs | 59 +++++++------------ harmony/src/modules/application/rust.rs | 16 ++++- 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/harmony/src/modules/application/features/continuous_delivery.rs b/harmony/src/modules/application/features/continuous_delivery.rs index 14ce255..cbfdbe7 100644 --- a/harmony/src/modules/application/features/continuous_delivery.rs +++ b/harmony/src/modules/application/features/continuous_delivery.rs @@ -39,4 +39,7 @@ impl ApplicationFeature for ContinuousDelivery { info!("Installing ContinuousDelivery feature"); todo!() } + fn name(&self) -> String { + "ContinuousDelivery".to_string() + } } diff --git a/harmony/src/modules/application/features/endpoint.rs b/harmony/src/modules/application/features/endpoint.rs index 83cc215..042f0dd 100644 --- a/harmony/src/modules/application/features/endpoint.rs +++ b/harmony/src/modules/application/features/endpoint.rs @@ -36,4 +36,7 @@ impl ApplicationFeature for PublicEndpoint ); todo!() } + fn name(&self) -> String { + "PublicEndpoint".to_string() + } } diff --git a/harmony/src/modules/application/features/monitoring.rs b/harmony/src/modules/application/features/monitoring.rs index a343e44..33717a4 100644 --- a/harmony/src/modules/application/features/monitoring.rs +++ b/harmony/src/modules/application/features/monitoring.rs @@ -15,4 +15,7 @@ impl ApplicationFeature for Monitoring { info!("Ensuring monitoring is available for application"); todo!("create and execute k8s prometheus score, depends on Will's work") } + fn name(&self) -> String { + "Monitoring".to_string() + } } diff --git a/harmony/src/modules/application/mod.rs b/harmony/src/modules/application/mod.rs index ddbfe49..663835f 100644 --- a/harmony/src/modules/application/mod.rs +++ b/harmony/src/modules/application/mod.rs @@ -1,9 +1,11 @@ +mod feature; pub mod features; mod rust; +pub use feature::*; +use log::info; pub use rust::*; use async_trait::async_trait; -use serde::Serialize; use crate::{ data::{Id, Version}, @@ -12,9 +14,14 @@ use crate::{ topology::Topology, }; +pub trait Application: std::fmt::Debug + Send + Sync { + fn name(&self) -> String; +} + #[derive(Debug)] pub struct ApplicationInterpret { features: Vec>>, + application: Box, } #[async_trait] @@ -24,7 +31,20 @@ impl Interpret for ApplicationInterpret { _inventory: &Inventory, topology: &T, ) -> Result { + let app_name = self.application.name(); + info!( + "Preparing features {} for application {app_name}", + self.features + .iter() + .map(|f| f.name()) + .collect::>() + .join(", ") + ); for feature in self.features.iter() { + info!( + "Installing feature {} for application {app_name}", + feature.name() + ); let _ = match feature.ensure_installed(topology).await { Ok(()) => (), Err(msg) => { @@ -53,40 +73,3 @@ impl Interpret for ApplicationInterpret { todo!() } } - -/// An ApplicationFeature provided by harmony, such as Backups, Monitoring, MultisiteAvailability, -/// ContinuousIntegration, ContinuousDelivery -#[async_trait] -pub trait ApplicationFeature: - std::fmt::Debug + Send + Sync + ApplicationFeatureClone -{ - async fn ensure_installed(&self, topology: &T) -> Result<(), String>; -} - -trait ApplicationFeatureClone { - fn clone_box(&self) -> Box>; -} - -impl ApplicationFeatureClone for A -where - A: ApplicationFeature + Clone + 'static, -{ - fn clone_box(&self) -> Box> { - Box::new(self.clone()) - } -} - -impl Serialize for Box> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - todo!() - } -} - -impl Clone for Box> { - fn clone(&self) -> Self { - self.clone_box() - } -} diff --git a/harmony/src/modules/application/rust.rs b/harmony/src/modules/application/rust.rs index 231b821..43a4907 100644 --- a/harmony/src/modules/application/rust.rs +++ b/harmony/src/modules/application/rust.rs @@ -5,7 +5,7 @@ use crate::{ topology::{Topology, Url}, }; -use super::{ApplicationFeature, ApplicationInterpret, features::ContinuousDelivery}; +use super::{Application, ApplicationFeature, ApplicationInterpret}; #[derive(Debug, Serialize, Clone)] pub struct RustWebappScore { @@ -18,6 +18,9 @@ impl Score for R fn create_interpret(&self) -> Box> { Box::new(ApplicationInterpret { features: self.features.clone(), + application: Box::new(RustWebapp { + name: self.name.clone(), + }), }) } @@ -25,3 +28,14 @@ impl Score for R format!("{}-RustWebapp", self.name) } } + +#[derive(Debug)] +struct RustWebapp { + name: String, +} + +impl Application for RustWebapp { + fn name(&self) -> String { + self.name.clone() + } +} -- 2.39.5 From 6e884cff3a862c675032a356635277b2c4476ec9 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Wed, 2 Jul 2025 11:14:24 -0400 Subject: [PATCH 2/2] feat: Start default implementation to ArgoCD for ContinuousDelivery feature --- harmony/src/domain/interpret/mod.rs | 2 + harmony/src/domain/inventory/mod.rs | 11 +++++ .../features/continuous_delivery.rs | 47 +++++++++++++++++-- harmony/src/modules/application/mod.rs | 11 +++-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/harmony/src/domain/interpret/mod.rs b/harmony/src/domain/interpret/mod.rs index 5e928cb..9a0c26b 100644 --- a/harmony/src/domain/interpret/mod.rs +++ b/harmony/src/domain/interpret/mod.rs @@ -21,6 +21,7 @@ pub enum InterpretName { OPNSense, K3dInstallation, TenantInterpret, + Application, } impl std::fmt::Display for InterpretName { @@ -37,6 +38,7 @@ impl std::fmt::Display for InterpretName { InterpretName::OPNSense => f.write_str("OPNSense"), InterpretName::K3dInstallation => f.write_str("K3dInstallation"), InterpretName::TenantInterpret => f.write_str("Tenant"), + InterpretName::Application => f.write_str("Application"), } } } diff --git a/harmony/src/domain/inventory/mod.rs b/harmony/src/domain/inventory/mod.rs index d566f18..851a150 100644 --- a/harmony/src/domain/inventory/mod.rs +++ b/harmony/src/domain/inventory/mod.rs @@ -34,6 +34,17 @@ pub struct Inventory { } impl Inventory { + pub fn empty() -> Self { + Self { + location: Location::new("Empty".to_string(), "location".to_string()), + switch: vec![], + firewall: vec![], + worker_host: vec![], + storage_host: vec![], + control_plane_host: vec![], + } + } + pub fn autoload() -> Self { Self { location: Location::test_building(), diff --git a/harmony/src/modules/application/features/continuous_delivery.rs b/harmony/src/modules/application/features/continuous_delivery.rs index cbfdbe7..e7dd968 100644 --- a/harmony/src/modules/application/features/continuous_delivery.rs +++ b/harmony/src/modules/application/features/continuous_delivery.rs @@ -1,7 +1,14 @@ use async_trait::async_trait; use log::info; +use serde_json::Value; -use crate::{modules::application::ApplicationFeature, topology::Topology}; +use crate::{ + data::Version, + inventory::Inventory, + modules::{application::ApplicationFeature, helm::chart::HelmChartScore}, + score::Score, + topology::{HelmCommand, Topology, Url}, +}; /// ContinuousDelivery in Harmony provides this functionality : /// @@ -34,12 +41,44 @@ use crate::{modules::application::ApplicationFeature, topology::Topology}; pub struct ContinuousDelivery {} #[async_trait] -impl ApplicationFeature for ContinuousDelivery { - async fn ensure_installed(&self, _topology: &T) -> Result<(), String> { +impl ApplicationFeature for ContinuousDelivery { + async fn ensure_installed(&self, topology: &T) -> Result<(), String> { info!("Installing ContinuousDelivery feature"); - todo!() + let cd_server = HelmChartScore { + namespace: todo!( + "ArgoCD Helm chart with proper understanding of Tenant, see how Will did it for Monitoring for now" + ), + release_name: todo!("argocd helm chart whatever"), + chart_name: todo!(), + chart_version: todo!(), + values_overrides: todo!(), + values_yaml: todo!(), + create_namespace: todo!(), + install_only: todo!(), + repository: todo!(), + }; + let interpret = cd_server.create_interpret(); + interpret.execute(&Inventory::empty(), topology); + + todo!("1. Create ArgoCD score that installs argo using helm chart, see if Taha's already done it + 2. Package app (docker image, helm chart) + 3. Push to registry if staging or prod + 4. Poke Argo + 5. Ensure app is up") } fn name(&self) -> String { "ContinuousDelivery".to_string() } } + +/// For now this is entirely bound to K8s / ArgoCD, will have to be revisited when we support +/// more CD systems +pub struct CDApplicationConfig { + version: Version, + helm_chart_url: Url, + values_overrides: Value, +} + +pub trait ContinuousDeliveryApplication { + fn get_config(&self) -> CDApplicationConfig; +} diff --git a/harmony/src/modules/application/mod.rs b/harmony/src/modules/application/mod.rs index 663835f..92669c0 100644 --- a/harmony/src/modules/application/mod.rs +++ b/harmony/src/modules/application/mod.rs @@ -33,7 +33,8 @@ impl Interpret for ApplicationInterpret { ) -> Result { let app_name = self.application.name(); info!( - "Preparing features {} for application {app_name}", + "Preparing {} features [{}] for application {app_name}", + self.features.len(), self.features .iter() .map(|f| f.name()) @@ -54,15 +55,17 @@ impl Interpret for ApplicationInterpret { } }; } - todo!("Do I need to do anything more than this here??") + todo!( + "Do I need to do anything more than this here?? I feel like the Application trait itself should expose something like ensure_ready but its becoming redundant. We'll see as this evolves." + ) } fn get_name(&self) -> InterpretName { - todo!() + InterpretName::Application } fn get_version(&self) -> Version { - todo!() + Version::from("1.0.0").unwrap() } fn get_status(&self) -> InterpretStatus { -- 2.39.5