fix: unjank the demo #85
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -2,3 +2,7 @@ target | |||||||
| private_repos | private_repos | ||||||
| log/ | log/ | ||||||
| *.tgz | *.tgz | ||||||
|  | examples/rust/examples/rust/webapp/helm/ | ||||||
|  | |||||||
|  | examples/rust/examples/rust/webapp/Dockerfile.harmony | ||||||
|  | examples/rust/webapp/helm/harmony-example-rust-webapp-chart/ | ||||||
|  | .gitignore | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1726,6 +1726,7 @@ name = "harmony" | |||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "async-trait", |  "async-trait", | ||||||
|  |  "bollard", | ||||||
|  "chrono", |  "chrono", | ||||||
|  "cidr", |  "cidr", | ||||||
|  "convert_case", |  "convert_case", | ||||||
|  | |||||||
| @ -53,3 +53,4 @@ chrono = "0.4" | |||||||
| similar = "2" | similar = "2" | ||||||
| uuid = { version = "1.11", features = ["v4", "fast-rng", "macro-diagnostics"] } | uuid = { version = "1.11", features = ["v4", "fast-rng", "macro-diagnostics"] } | ||||||
| pretty_assertions = "1.4.1" | pretty_assertions = "1.4.1" | ||||||
|  | bollard = "0.19.1" | ||||||
|  | |||||||
| @ -1,18 +1,41 @@ | |||||||
| use std::{path::PathBuf, sync::Arc}; | use std::{path::PathBuf, sync::Arc}; | ||||||
| 
 | 
 | ||||||
| use harmony::{ | use harmony::{ | ||||||
|  |     data::Id, | ||||||
|     inventory::Inventory, |     inventory::Inventory, | ||||||
|     maestro::Maestro, |     maestro::Maestro, | ||||||
|     modules::application::{ |     modules::{ | ||||||
|         ApplicationScore, RustWebFramework, RustWebapp, |         application::{ | ||||||
|         features::{ContinuousDelivery, Monitoring}, |             ApplicationScore, RustWebFramework, RustWebapp, | ||||||
|  |             features::{ContinuousDelivery, Monitoring}, | ||||||
|  |         }, | ||||||
|  |         tenant::TenantScore, | ||||||
|  |     }, | ||||||
|  |     topology::{ | ||||||
|  |         K8sAnywhereTopology, Url, | ||||||
|  |         tenant::{ResourceLimits, TenantConfig, TenantNetworkPolicy}, | ||||||
|     }, |     }, | ||||||
|     topology::{K8sAnywhereTopology, Url}, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[tokio::main] | #[tokio::main] | ||||||
| async fn main() { | async fn main() { | ||||||
|     env_logger::init(); |     env_logger::init(); | ||||||
|  | 
 | ||||||
|  |     let tenant = TenantScore { | ||||||
|  |         config: TenantConfig { | ||||||
|  |             id: Id::from_string("1234".to_string()), | ||||||
|  |             name: "harmonydemo-staging".to_string(), | ||||||
|  |             resource_limits: ResourceLimits { | ||||||
|  |                 cpu_request_cores: 6.0, | ||||||
|  |                 cpu_limit_cores: 4.0, | ||||||
|  |                 memory_request_gb: 4.0, | ||||||
|  |                 memory_limit_gb: 4.0, | ||||||
|  |                 storage_total_gb: 10.0, | ||||||
|  |             }, | ||||||
|  |             network_policy: TenantNetworkPolicy::default(), | ||||||
|  |         }, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     let application = Arc::new(RustWebapp { |     let application = Arc::new(RustWebapp { | ||||||
|         name: "harmony-example-rust-webapp".to_string(), |         name: "harmony-example-rust-webapp".to_string(), | ||||||
|         domain: Url::Url(url::Url::parse("https://rustapp.harmony.example.com").unwrap()), |         domain: Url::Url(url::Url::parse("https://rustapp.harmony.example.com").unwrap()), | ||||||
| @ -35,6 +58,6 @@ async fn main() { | |||||||
|     let mut maestro = Maestro::initialize(Inventory::autoload(), topology) |     let mut maestro = Maestro::initialize(Inventory::autoload(), topology) | ||||||
|         .await |         .await | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|     maestro.register_all(vec![Box::new(app)]); |     maestro.register_all(vec![Box::new(tenant), Box::new(app)]); | ||||||
|     harmony_cli::init(maestro, None).await.unwrap(); |     harmony_cli::init(maestro, None).await.unwrap(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -59,6 +59,7 @@ tokio-util = "0.7.15" | |||||||
| strum = { version = "0.27.1", features = ["derive"] } | strum = { version = "0.27.1", features = ["derive"] } | ||||||
| tempfile = "3.20.0" | tempfile = "3.20.0" | ||||||
| serde_with = "3.14.0" | serde_with = "3.14.0" | ||||||
|  | bollard.workspace = true | ||||||
| 
 | 
 | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
| pretty_assertions.workspace = true | pretty_assertions.workspace = true | ||||||
|  | |||||||
| @ -1,6 +1,3 @@ | |||||||
| use std::{backtrace, collections::HashMap}; |  | ||||||
| 
 |  | ||||||
| use k8s_openapi::{Metadata, NamespaceResourceScope, Resource}; |  | ||||||
| use log::debug; | use log::debug; | ||||||
| use serde::Serialize; | use serde::Serialize; | ||||||
| use serde_with::skip_serializing_none; | use serde_with::skip_serializing_none; | ||||||
| @ -34,10 +31,11 @@ pub struct Helm { | |||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct Source { | pub struct Source { | ||||||
|     #[serde(rename = "repoURL")] |     #[serde(rename = "repoURL")] | ||||||
|     pub repo_url: Url, |     pub repo_url: String, | ||||||
|     pub target_revision: Option<String>, |     pub target_revision: Option<String>, | ||||||
|     pub chart: String, |     pub chart: String, | ||||||
|     pub helm: Helm, |     pub helm: Helm, | ||||||
|  |     pub path: String, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, Serialize)] | #[derive(Clone, Debug, Serialize)] | ||||||
| @ -90,7 +88,7 @@ impl Default for ArgoApplication { | |||||||
|             namespace: Default::default(), |             namespace: Default::default(), | ||||||
|             project: Default::default(), |             project: Default::default(), | ||||||
|             source: Source { |             source: Source { | ||||||
|                 repo_url: Url::parse("http://asdf").expect("Couldn't parse to URL"), |                 repo_url: "http://asdf".to_string(), | ||||||
|                 target_revision: None, |                 target_revision: None, | ||||||
|                 chart: "".to_string(), |                 chart: "".to_string(), | ||||||
|                 helm: Helm { |                 helm: Helm { | ||||||
| @ -109,6 +107,7 @@ impl Default for ArgoApplication { | |||||||
|                     api_versions: vec![], |                     api_versions: vec![], | ||||||
|                     namespace: None, |                     namespace: None, | ||||||
|                 }, |                 }, | ||||||
|  |                 path: "".to_string(), | ||||||
|             }, |             }, | ||||||
|             sync_policy: SyncPolicy { |             sync_policy: SyncPolicy { | ||||||
|                 automated: Automated { |                 automated: Automated { | ||||||
| @ -138,10 +137,10 @@ impl From<CDApplicationConfig> for ArgoApplication { | |||||||
|             namespace: Some(value.namespace), |             namespace: Some(value.namespace), | ||||||
|             project: "default".to_string(), |             project: "default".to_string(), | ||||||
|             source: Source { |             source: Source { | ||||||
|                 repo_url: Url::parse(value.helm_chart_repo_url.to_string().as_str()) |                 repo_url: value.helm_chart_repo_url, | ||||||
|                     .expect("couldn't convert to URL"), |  | ||||||
|                 target_revision: Some(value.version.to_string()), |                 target_revision: Some(value.version.to_string()), | ||||||
|                 chart: value.helm_chart_name, |                 chart: value.helm_chart_name.clone(), | ||||||
|  |                 path: value.helm_chart_name, | ||||||
|                 helm: Helm { |                 helm: Helm { | ||||||
|                     pass_credentials: None, |                     pass_credentials: None, | ||||||
|                     parameters: vec![], |                     parameters: vec![], | ||||||
| @ -218,7 +217,7 @@ spec: | |||||||
|         let mut yaml_value: Value = |         let mut yaml_value: Value = | ||||||
|             serde_yaml::from_str(yaml_str.as_str()).expect("couldn't parse string to YAML"); |             serde_yaml::from_str(yaml_str.as_str()).expect("couldn't parse string to YAML"); | ||||||
| 
 | 
 | ||||||
|         let mut spec = yaml_value |         let spec = yaml_value | ||||||
|             .get_mut("spec") |             .get_mut("spec") | ||||||
|             .expect("couldn't get spec from yaml") |             .expect("couldn't get spec from yaml") | ||||||
|             .as_mapping_mut() |             .as_mapping_mut() | ||||||
| @ -271,7 +270,7 @@ mod tests { | |||||||
|             namespace: Some("test-ns".to_string()), |             namespace: Some("test-ns".to_string()), | ||||||
|             project: "test-project".to_string(), |             project: "test-project".to_string(), | ||||||
|             source: Source { |             source: Source { | ||||||
|                 repo_url: Url::parse("http://test").unwrap(), |                 repo_url: "http://test".to_string(), | ||||||
|                 target_revision: None, |                 target_revision: None, | ||||||
|                 chart: "test-chart".to_string(), |                 chart: "test-chart".to_string(), | ||||||
|                 helm: Helm { |                 helm: Helm { | ||||||
| @ -290,6 +289,7 @@ mod tests { | |||||||
|                     api_versions: vec![], |                     api_versions: vec![], | ||||||
|                     namespace: None, |                     namespace: None, | ||||||
|                 }, |                 }, | ||||||
|  |                 path: "".to_string(), | ||||||
|             }, |             }, | ||||||
|             sync_policy: SyncPolicy { |             sync_policy: SyncPolicy { | ||||||
|                 automated: Automated { |                 automated: Automated { | ||||||
|  | |||||||
| @ -9,12 +9,9 @@ use crate::{ | |||||||
|     config::HARMONY_DATA_DIR, |     config::HARMONY_DATA_DIR, | ||||||
|     data::Version, |     data::Version, | ||||||
|     inventory::Inventory, |     inventory::Inventory, | ||||||
|     modules::{ |     modules::application::{ | ||||||
|         application::{ |         Application, ApplicationFeature, HelmPackage, OCICompliant, | ||||||
|             Application, ApplicationFeature, HelmPackage, OCICompliant, |         features::{ArgoApplication, ArgoHelmScore}, | ||||||
|             features::{ArgoApplication, ArgoHelmScore}, |  | ||||||
|         }, |  | ||||||
|         helm::chart::HelmChartScore, |  | ||||||
|     }, |     }, | ||||||
|     score::Score, |     score::Score, | ||||||
|     topology::{DeploymentTarget, HelmCommand, K8sclient, MultiTargetTopology, Topology, Url}, |     topology::{DeploymentTarget, HelmCommand, K8sclient, MultiTargetTopology, Topology, Url}, | ||||||
| @ -162,7 +159,7 @@ impl< | |||||||
|         info!("Pushed new helm chart {helm_chart}"); |         info!("Pushed new helm chart {helm_chart}"); | ||||||
| 
 | 
 | ||||||
|         error!("TODO Make building image configurable/skippable"); |         error!("TODO Make building image configurable/skippable"); | ||||||
|         let image = self.application.build_push_oci_image().await?; |         // let image = self.application.build_push_oci_image().await?;
 | ||||||
|         info!("Pushed new docker image {image}"); |         info!("Pushed new docker image {image}"); | ||||||
| 
 | 
 | ||||||
|         info!("Installing ContinuousDelivery feature"); |         info!("Installing ContinuousDelivery feature"); | ||||||
| @ -188,12 +185,12 @@ impl< | |||||||
|                 info!("Deploying to target {target:?}"); |                 info!("Deploying to target {target:?}"); | ||||||
|                 let score = ArgoHelmScore { |                 let score = ArgoHelmScore { | ||||||
|                     namespace: "harmonydemo-staging".to_string(), |                     namespace: "harmonydemo-staging".to_string(), | ||||||
|                     openshift: true, |                     openshift: false, | ||||||
|                     domain: "argo.harmonydemo.apps.st.mcd".to_string(), |                     domain: "argo.harmonydemo.apps.st.mcd".to_string(), | ||||||
|                     argo_apps: vec![ArgoApplication::from(CDApplicationConfig { |                     argo_apps: vec![ArgoApplication::from(CDApplicationConfig { | ||||||
|                         // helm pull oci://hub.nationtech.io/harmony/harmony-example-rust-webapp-chart/harmony-example-rust-webapp-chart --version 0.1.0
 |                         // helm pull oci://hub.nationtech.io/harmony/harmony-example-rust-webapp-chart --version 0.1.0
 | ||||||
|                         version: Version::from("0.1.0").unwrap(), |                         version: Version::from("0.1.0").unwrap(), | ||||||
|                         helm_chart_repo_url: Url::Url(url::Url::parse("oci://hub.nationtech.io/harmony/harmony-example-rust-webapp-chart/harmony-example-rust-webapp-chart").unwrap()), |                         helm_chart_repo_url: "hub.nationtech.io/harmony".to_string(), | ||||||
|                         helm_chart_name: "harmony-example-rust-webapp-chart".to_string(), |                         helm_chart_name: "harmony-example-rust-webapp-chart".to_string(), | ||||||
|                         values_overrides: None, |                         values_overrides: None, | ||||||
|                         name: "harmony-demo-rust-webapp".to_string(), |                         name: "harmony-demo-rust-webapp".to_string(), | ||||||
| @ -225,7 +222,7 @@ impl< | |||||||
| /// more CD systems
 | /// more CD systems
 | ||||||
| pub struct CDApplicationConfig { | pub struct CDApplicationConfig { | ||||||
|     pub version: Version, |     pub version: Version, | ||||||
|     pub helm_chart_repo_url: Url, |     pub helm_chart_repo_url: String, | ||||||
|     pub helm_chart_name: String, |     pub helm_chart_name: String, | ||||||
|     pub values_overrides: Option<Value>, |     pub values_overrides: Option<Value>, | ||||||
|     pub name: String, |     pub name: String, | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| use async_trait::async_trait; | use async_trait::async_trait; | ||||||
| use k8s_openapi::Resource; |  | ||||||
| use log::error; | use log::error; | ||||||
| use non_blank_string_rs::NonBlankString; | use non_blank_string_rs::NonBlankString; | ||||||
| use serde::Serialize; | use serde::Serialize; | ||||||
| @ -647,7 +646,7 @@ server: | |||||||
|   # Argo CD server ingress configuration |   # Argo CD server ingress configuration | ||||||
|   ingress: |   ingress: | ||||||
|     # -- Enable an ingress resource for the Argo CD server |     # -- Enable an ingress resource for the Argo CD server | ||||||
|     enabled: false |     enabled: true | ||||||
|     # -- Specific implementation for ingress controller. One of `generic`, `aws` or `gke` |     # -- Specific implementation for ingress controller. One of `generic`, `aws` or `gke` | ||||||
|     ## Additional configuration might be required in related configuration sections |     ## Additional configuration might be required in related configuration sections | ||||||
|     controller: generic |     controller: generic | ||||||
|  | |||||||
| @ -4,13 +4,10 @@ use log::info; | |||||||
| use crate::{ | use crate::{ | ||||||
|     inventory::Inventory, |     inventory::Inventory, | ||||||
|     modules::{ |     modules::{ | ||||||
|         application::{Application, ApplicationFeature}, |         application::ApplicationFeature, | ||||||
|         monitoring::{ |         monitoring::{ | ||||||
|             application_monitoring::k8s_application_monitoring_score::ApplicationPrometheusMonitoringScore, |             application_monitoring::k8s_application_monitoring_score::ApplicationPrometheusMonitoringScore, | ||||||
|             kube_prometheus::{ |             kube_prometheus::types::{NamespaceSelector, ServiceMonitor}, | ||||||
|                 helm_prometheus_alert_score::HelmPrometheusAlertingScore, |  | ||||||
|                 types::{NamespaceSelector, ServiceMonitor}, |  | ||||||
|             }, |  | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|     score::Score, |     score::Score, | ||||||
|  | |||||||
| @ -416,7 +416,7 @@ ingress: | |||||||
| Expand the name of the chart. | Expand the name of the chart. | ||||||
| */}} | */}} | ||||||
| {{- define "chart.name" -}} | {{- define "chart.name" -}} | ||||||
| {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} | {{- default .Chart.Name $.Values.nameOverride | trunc 63 | trimSuffix "-" }} | ||||||
| {{- end }} | {{- end }} | ||||||
| 
 | 
 | ||||||
| {{/* | {{/* | ||||||
| @ -424,7 +424,7 @@ Create a default fully qualified app name. | |||||||
| We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). | ||||||
| */}} | */}} | ||||||
| {{- define "chart.fullname" -}} | {{- define "chart.fullname" -}} | ||||||
| {{- $name := default .Chart.Name .Values.nameOverride }} | {{- $name := default .Chart.Name $.Values.nameOverride }} | ||||||
| {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} | ||||||
| {{- end }} | {{- end }} | ||||||
| "#;
 | "#;
 | ||||||
| @ -437,12 +437,12 @@ kind: Service | |||||||
| metadata: | metadata: | ||||||
|   name: {{ include "chart.fullname" . }} |   name: {{ include "chart.fullname" . }} | ||||||
| spec: | spec: | ||||||
|   type: {{ .Values.service.type }} |   type: {{ $.Values.service.type }} | ||||||
|   ports: |   ports: | ||||||
|     - port: {{ .Values.service.port }} |     - name: main | ||||||
|       targetPort: 3000 |       port: {{ $.Values.service.port | default 3000 }} | ||||||
|  |       targetPort: {{ $.Values.service.port | default 3000 }} | ||||||
|       protocol: TCP |       protocol: TCP | ||||||
|       name: http |  | ||||||
|   selector: |   selector: | ||||||
|     app: {{ include "chart.name" . }} |     app: {{ include "chart.name" . }} | ||||||
| "#;
 | "#;
 | ||||||
| @ -455,7 +455,7 @@ kind: Deployment | |||||||
| metadata: | metadata: | ||||||
| 
				
					
						johnride
						commented  Thanks for fixing my demo hardcoding crap 😅 Thanks for fixing my demo hardcoding crap 😅 | |||||||
|   name: {{ include "chart.fullname" . }} |   name: {{ include "chart.fullname" . }} | ||||||
| spec: | spec: | ||||||
|   replicas: {{ .Values.replicaCount }} |   replicas: {{ $.Values.replicaCount }} | ||||||
|   selector: |   selector: | ||||||
|     matchLabels: |     matchLabels: | ||||||
|       app: {{ include "chart.name" . }} |       app: {{ include "chart.name" . }} | ||||||
| @ -466,28 +466,28 @@ spec: | |||||||
|     spec: |     spec: | ||||||
|       containers: |       containers: | ||||||
|         - name: {{ .Chart.Name }} |         - name: {{ .Chart.Name }} | ||||||
|           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" |           image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag | default .Chart.AppVersion }}" | ||||||
|           imagePullPolicy: {{ .Values.image.pullPolicy }} |           imagePullPolicy: {{ $.Values.image.pullPolicy }} | ||||||
|           ports: |           ports: | ||||||
|             - name: http |             - name: main | ||||||
|               containerPort: 3000 |               containerPort: {{ $.Values.service.port | default 3000 }} | ||||||
|               protocol: TCP |               protocol: TCP | ||||||
| "#;
 | "#;
 | ||||||
|         fs::write(templates_dir.join("deployment.yaml"), deployment_yaml)?; |         fs::write(templates_dir.join("deployment.yaml"), deployment_yaml)?; | ||||||
| 
 | 
 | ||||||
|         // Create templates/ingress.yaml
 |         // Create templates/ingress.yaml
 | ||||||
|         let ingress_yaml = r#" |         let ingress_yaml = r#" | ||||||
| {{- if .Values.ingress.enabled -}} | {{- if $.Values.ingress.enabled -}} | ||||||
| apiVersion: networking.k8s.io/v1 | apiVersion: networking.k8s.io/v1 | ||||||
| kind: Ingress | kind: Ingress | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "chart.fullname" . }} |   name: {{ include "chart.fullname" . }} | ||||||
|   annotations: |   annotations: | ||||||
|     {{- toYaml .Values.ingress.annotations | nindent 4 }} |     {{- toYaml $.Values.ingress.annotations | nindent 4 }} | ||||||
| spec: | spec: | ||||||
|   {{- if .Values.ingress.tls }} |   {{- if $.Values.ingress.tls }} | ||||||
|   tls: |   tls: | ||||||
|     {{- range .Values.ingress.tls }} |     {{- range $.Values.ingress.tls }} | ||||||
|     - hosts: |     - hosts: | ||||||
|         {{- range .hosts }} |         {{- range .hosts }} | ||||||
|         - {{ . | quote }} |         - {{ . | quote }} | ||||||
| @ -496,7 +496,7 @@ spec: | |||||||
|     {{- end }} |     {{- end }} | ||||||
|   {{- end }} |   {{- end }} | ||||||
|   rules: |   rules: | ||||||
|     {{- range .Values.ingress.hosts }} |     {{- range $.Values.ingress.hosts }} | ||||||
|     - host: {{ .host | quote }} |     - host: {{ .host | quote }} | ||||||
|       http: |       http: | ||||||
|         paths: |         paths: | ||||||
| @ -507,7 +507,7 @@ spec: | |||||||
|               service: |               service: | ||||||
|                 name: {{ include "chart.fullname" $ }} |                 name: {{ include "chart.fullname" $ }} | ||||||
|                 port: |                 port: | ||||||
|                   number: 3000 |                   number: {{ $.Values.service.port | default 3000 }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|     {{- end }} |     {{- end }} | ||||||
| {{- end }} | {{- end }} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	
These would be better in the examples's own gitignore file
examples/rust/.gitignore. Eventually we may have hundreds of examples, we don't want thousands of lines in this file.But thinking a bit further, this points towards a problem on the way we manage these generated files. They should probably end up in a harmony specific directory that we can then ignore in a single line for all examples. Maybe
harmony_generatedorharmony_build?