Demo now kinda works
This commit is contained in:
parent
9452cf5616
commit
6de889aa0f
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:
|
||||||
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