forked from NationTech/harmony
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			master
			...
			feat/multi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ec794f076e | 
| @ -50,6 +50,55 @@ pub struct ContinuousDelivery<A: OCICompliant + HelmPackage> { | ||||
| } | ||||
| 
 | ||||
| impl<A: OCICompliant + HelmPackage> ContinuousDelivery<A> { | ||||
|     pub async fn deploy<T>(&self, topology: &T, helm_chart: String, image: String) -> Result<(), String> | ||||
|     where | ||||
|         T: Topology + HelmCommand + MultiTargetTopology + K8sclient + 'static, | ||||
|     { | ||||
|         // TODO: this is a temporary hack for demo purposes, the deployment target should be driven
 | ||||
|         // by the topology only and we should not have to know how to perform tasks like this for
 | ||||
|         // which the topology should be responsible.
 | ||||
|         //
 | ||||
|         // That said, this will require some careful architectural decisions, since the concept of
 | ||||
|         // deployment targets / profiles is probably a layer of complexity that we won't be
 | ||||
|         // completely able to avoid
 | ||||
|         //
 | ||||
|         // I'll try something for now that must be thought through after : att a deployment_profile
 | ||||
|         // function to the topology trait that returns a profile, then anybody who needs it can
 | ||||
|         // access it. This forces every Topology to understand the concept of targets though... So
 | ||||
|         // instead I'll create a new Capability which is MultiTargetTopology and we'll see how it
 | ||||
|         // goes. It still does not feel right though.
 | ||||
|         //
 | ||||
|         // https://git.nationtech.io/NationTech/harmony/issues/106
 | ||||
|         match topology.current_target() { | ||||
|             DeploymentTarget::LocalDev => { | ||||
|                 info!("Deploying {} locally...", self.application.name()); | ||||
|                 self.deploy_to_local_k3d(self.application.name(), helm_chart, image) | ||||
|                     .await?; | ||||
|             } | ||||
|             target => { | ||||
|                 info!("Deploying {} to target {target:?}", self.application.name()); | ||||
| 
 | ||||
|                 let score = ArgoHelmScore { | ||||
|                     namespace: format!("{}", self.application.name()), | ||||
|                     openshift: true, | ||||
|                     argo_apps: vec![ArgoApplication::from(CDApplicationConfig { | ||||
|                         // helm pull oci://hub.nationtech.io/harmony/harmony-example-rust-webapp-chart --version 0.1.0
 | ||||
|                         version: Version::from("0.1.0").unwrap(), | ||||
|                         helm_chart_repo_url: "hub.nationtech.io/harmony".to_string(), | ||||
|                         helm_chart_name: format!("{}-chart", self.application.name()), | ||||
|                         values_overrides: None, | ||||
|                         name: format!("{}", self.application.name()), | ||||
|                         namespace: format!("{}", self.application.name()), | ||||
|                     })], | ||||
|                 }; | ||||
|                 score | ||||
|                     .interpret(&Inventory::empty(), topology) | ||||
|                     .await | ||||
|                     .unwrap(); | ||||
|             } | ||||
|         }; | ||||
|         Ok(()) | ||||
|     } | ||||
|     async fn deploy_to_local_k3d( | ||||
|         &self, | ||||
|         app_name: String, | ||||
| @ -153,50 +202,7 @@ impl< | ||||
|         // https://git.nationtech.io/NationTech/harmony/issues/104
 | ||||
|         let image = self.application.build_push_oci_image().await?; | ||||
| 
 | ||||
|         // TODO: this is a temporary hack for demo purposes, the deployment target should be driven
 | ||||
|         // by the topology only and we should not have to know how to perform tasks like this for
 | ||||
|         // which the topology should be responsible.
 | ||||
|         //
 | ||||
|         // That said, this will require some careful architectural decisions, since the concept of
 | ||||
|         // deployment targets / profiles is probably a layer of complexity that we won't be
 | ||||
|         // completely able to avoid
 | ||||
|         //
 | ||||
|         // I'll try something for now that must be thought through after : att a deployment_profile
 | ||||
|         // function to the topology trait that returns a profile, then anybody who needs it can
 | ||||
|         // access it. This forces every Topology to understand the concept of targets though... So
 | ||||
|         // instead I'll create a new Capability which is MultiTargetTopology and we'll see how it
 | ||||
|         // goes. It still does not feel right though.
 | ||||
|         //
 | ||||
|         // https://git.nationtech.io/NationTech/harmony/issues/106
 | ||||
|         match topology.current_target() { | ||||
|             DeploymentTarget::LocalDev => { | ||||
|                 info!("Deploying {} locally...", self.application.name()); | ||||
|                 self.deploy_to_local_k3d(self.application.name(), helm_chart, image) | ||||
|                     .await?; | ||||
|             } | ||||
|             target => { | ||||
|                 info!("Deploying {} to target {target:?}", self.application.name()); | ||||
| 
 | ||||
|                 let score = ArgoHelmScore { | ||||
|                     namespace: format!("{}", self.application.name()), | ||||
|                     openshift: true, | ||||
|                     argo_apps: vec![ArgoApplication::from(CDApplicationConfig { | ||||
|                         // helm pull oci://hub.nationtech.io/harmony/harmony-example-rust-webapp-chart --version 0.1.0
 | ||||
|                         version: Version::from("0.1.0").unwrap(), | ||||
|                         helm_chart_repo_url: "hub.nationtech.io/harmony".to_string(), | ||||
|                         helm_chart_name: format!("{}-chart", self.application.name()), | ||||
|                         values_overrides: None, | ||||
|                         name: format!("{}", self.application.name()), | ||||
|                         namespace: format!("{}", self.application.name()), | ||||
|                     })], | ||||
|                 }; | ||||
|                 score | ||||
|                     .interpret(&Inventory::empty(), topology) | ||||
|                     .await | ||||
|                     .unwrap(); | ||||
|             } | ||||
|         }; | ||||
|         Ok(()) | ||||
|         self.deploy(topology, helm_chart, image).await | ||||
|     } | ||||
|     fn name(&self) -> String { | ||||
|         "ContinuousDelivery".to_string() | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| mod endpoint; | ||||
| pub mod rhob_monitoring; | ||||
| mod multisite; | ||||
| pub use endpoint::*; | ||||
| 
 | ||||
| mod monitoring; | ||||
|  | ||||
							
								
								
									
										49
									
								
								harmony/src/modules/application/features/multisite.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								harmony/src/modules/application/features/multisite.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| use crate::modules::application::{Application, ApplicationFeature, StatelessApplication}; | ||||
| use crate::modules::monitoring::application_monitoring::application_monitoring_score::ApplicationMonitoringScore; | ||||
| use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus; | ||||
| 
 | ||||
| use crate::topology::{K8sAnywhereTopology, MultiTargetTopology}; | ||||
| use crate::{ | ||||
|     inventory::Inventory, | ||||
|     modules::monitoring::{ | ||||
|         alert_channel::webhook_receiver::WebhookReceiver, ntfy::ntfy::NtfyScore, | ||||
|     }, | ||||
|     score::Score, | ||||
|     topology::{HelmCommand, K8sclient, Topology, tenant::TenantManager}, | ||||
| }; | ||||
| use crate::{ | ||||
|     modules::prometheus::prometheus::PrometheusApplicationMonitoring, | ||||
|     topology::oberservability::monitoring::AlertReceiver, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use base64::{Engine as _, engine::general_purpose}; | ||||
| use harmony_types::net::Url; | ||||
| use log::{debug, info}; | ||||
| 
 | ||||
| trait DebugTopology: Topology + std::fmt::Debug {} | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct Multisite { | ||||
|     app: Arc<dyn StatelessApplication>, | ||||
|     secondary_site: Arc<K8sAnywhereTopology>, | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology> ApplicationFeature<T> for Multisite { | ||||
|     async fn ensure_installed(&self, topology: &T) -> Result<(), String> { | ||||
| 
 | ||||
|         todo!( | ||||
|             " | ||||
|         - Find a way to get pvs for this application | ||||
|         - find the pv csi volumes uuid | ||||
|         - run rbd mirror image enable --pool mirrored-pool csi-vol-<UUID_PV> snapshot | ||||
|         - enjoy | ||||
|         " | ||||
|         ) | ||||
|     } | ||||
|     fn name(&self) -> String { | ||||
|         "Multisite".to_string() | ||||
|     } | ||||
| } | ||||
| @ -2,6 +2,10 @@ mod feature; | ||||
| pub mod features; | ||||
| pub mod oci; | ||||
| mod rust; | ||||
| mod stateless; | ||||
| mod stateful; | ||||
| pub use stateless::*; | ||||
| pub use stateful::*; | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| pub use feature::*; | ||||
|  | ||||
| @ -206,7 +206,7 @@ impl RustWebapp { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ///normalizes timestamp and ignores files that will bust the docker cach
 | ||||
|     ///normalizes timestamp and ignores files that will bust the docker cache
 | ||||
|     async fn create_deterministic_tar( | ||||
|         &self, | ||||
|         project_root: &std::path::Path, | ||||
|  | ||||
							
								
								
									
										6
									
								
								harmony/src/modules/application/stateful.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								harmony/src/modules/application/stateful.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| use crate::modules::application::Application; | ||||
| 
 | ||||
| /// A StatefulApplication is an application bundle that writes persistent data.
 | ||||
| /// 
 | ||||
| /// This will enable backup features, stateful multisite replication, etc.
 | ||||
| pub trait StatefulApplication: Application {} | ||||
							
								
								
									
										26
									
								
								harmony/src/modules/application/stateless.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								harmony/src/modules/application/stateless.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| use crate::modules::application::{Application, features::ContinuousDeliveryApplication}; | ||||
| 
 | ||||
| /// Marker trait for stateless application that can be deployed anywhere without worrying about
 | ||||
| /// data.
 | ||||
| ///
 | ||||
| /// This includes Applications fitting these categories :
 | ||||
| ///
 | ||||
| ///  - Application with all files built into the docker image and never written to, can be mounted
 | ||||
| ///  read-only
 | ||||
| ///  - Application writing to hard drive on ephemeral volume that can be lost at anytime and does
 | ||||
| ///  not require any replication/backup logic to operate
 | ||||
| ///     - Not supported : an application that writes state to a volume that must be shared or kept
 | ||||
| ///     to maintain a quorum across various instances
 | ||||
| ///  - Application connecting to a database/datastore accessible from anywhere such as
 | ||||
| ///     - Public bucket endpoint
 | ||||
| ///     - Publicly accessible
 | ||||
| ///  - Application connecting to a private database external to this application, accessible from the
 | ||||
| ///  deployment target
 | ||||
| ///     - Ensuring the private database is reachable is out of scope of this trait (for now)
 | ||||
| ///
 | ||||
| ///  The entire application definition **must not** require any persistent volume or include a
 | ||||
| ///  deployment component depending on persistent data such as a transitive PostgreSQL helm chart.
 | ||||
| ///
 | ||||
| ///  Typically, applications that can be autoscaled without additional complexity fit the
 | ||||
| ///  StatelessApplication requirements.
 | ||||
| pub trait StatelessApplication: Application + ContinuousDeliveryApplication {} | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user