Merge pull request 'fix/argoApplication' (#84) from fix/argoApplication into master
All checks were successful
Run Check Script / check (push) Successful in 1m41s
Compile and package harmony_composer / package_harmony_composer (push) Successful in 4m4s

Reviewed-on: https://git.nationtech.io/NationTech/harmony/pulls/84
This commit is contained in:
johnride 2025-07-05 01:19:05 +00:00
commit 9452cf5616
10 changed files with 72 additions and 29 deletions

34
Cargo.lock generated
View File

@ -1752,6 +1752,7 @@ dependencies = [
"non-blank-string-rs",
"opnsense-config",
"opnsense-config-xml",
"pretty_assertions",
"rand 0.9.1",
"reqwest 0.11.27",
"russh",
@ -1760,6 +1761,7 @@ dependencies = [
"serde",
"serde-value",
"serde_json",
"serde_with",
"serde_yaml",
"similar",
"strum 0.27.1",
@ -4080,6 +4082,18 @@ dependencies = [
"serde_json",
]
[[package]]
name = "schemars"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d"
dependencies = [
"dyn-clone",
"ref-cast",
"serde",
"serde_json",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -4280,22 +4294,36 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.13.0"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf65a400f8f66fb7b0552869ad70157166676db75ed8181f8104ea91cf9d0b42"
checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
dependencies = [
"base64 0.22.1",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.10.0",
"schemars",
"schemars 0.9.0",
"schemars 1.0.3",
"serde",
"serde_derive",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"

View File

@ -52,3 +52,4 @@ convert_case = "0.8"
chrono = "0.4"
similar = "2"
uuid = { version = "1.11", features = ["v4", "fast-rng", "macro-diagnostics"] }
pretty_assertions = "1.4.1"

View File

@ -10,7 +10,7 @@ use harmony::{
inventory::Inventory,
maestro::Maestro,
modules::{
http::HttpScore,
http::StaticFilesHttpScore,
ipxe::IpxeScore,
okd::{
bootstrap_dhcp::OKDBootstrapDhcpScore,
@ -126,7 +126,7 @@ async fn main() {
harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
let http_score = HttpScore::new(Url::LocalFolder(
let http_score = StaticFilesHttpScore::new(Url::LocalFolder(
"./data/watchguard/pxe-http-files".to_string(),
));
let ipxe_score = IpxeScore::new();

View File

@ -11,7 +11,7 @@ use harmony::{
maestro::Maestro,
modules::{
dummy::{ErrorScore, PanicScore, SuccessScore},
http::HttpScore,
http::StaticFilesHttpScore,
okd::{dhcp::OKDDhcpScore, dns::OKDDnsScore, load_balancer::OKDLoadBalancerScore},
opnsense::OPNsenseShellCommandScore,
tftp::TftpScore,
@ -81,7 +81,7 @@ async fn main() {
let load_balancer_score = OKDLoadBalancerScore::new(&topology);
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
let http_score = HttpScore::new(Url::LocalFolder(
let http_score = StaticFilesHttpScore::new(Url::LocalFolder(
"./data/watchguard/pxe-http-files".to_string(),
));
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();

View File

@ -58,3 +58,7 @@ futures-util = "0.3.31"
tokio-util = "0.7.15"
strum = { version = "0.27.1", features = ["derive"] }
tempfile = "3.20.0"
serde_with = "3.14.0"
[dev-dependencies]
pretty_assertions.workspace = true

View File

@ -3,11 +3,13 @@ use std::{backtrace, collections::HashMap};
use k8s_openapi::{Metadata, NamespaceResourceScope, Resource};
use log::debug;
use serde::Serialize;
use serde_with::skip_serializing_none;
use serde_yaml::Value;
use url::Url;
use crate::modules::application::features::CDApplicationConfig;
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Helm {
@ -27,9 +29,11 @@ pub struct Helm {
pub namespace: Option<String>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Source {
#[serde(rename = "repoURL")]
pub repo_url: Url,
pub target_revision: Option<String>,
pub chart: String,
@ -67,6 +71,7 @@ pub struct SyncPolicy {
pub retry: Retry,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ArgoApplication {
@ -135,7 +140,7 @@ impl From<CDApplicationConfig> for ArgoApplication {
source: Source {
repo_url: Url::parse(value.helm_chart_repo_url.to_string().as_str())
.expect("couldn't convert to URL"),
target_revision: None,
target_revision: Some(value.version.to_string()),
chart: value.helm_chart_name,
helm: Helm {
pass_credentials: None,
@ -145,7 +150,7 @@ impl From<CDApplicationConfig> for ArgoApplication {
value_files: vec![],
ignore_missing_value_files: None,
values: None,
values_object: Some(value.values_overrides),
values_object: value.values_overrides,
skip_crds: None,
skip_schema_validation: None,
version: None,
@ -252,6 +257,7 @@ spec:
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use url::Url;
use crate::modules::application::features::{
@ -315,24 +321,14 @@ spec:
server: https://kubernetes.default.svc
namespace: test-ns
source:
repoUrl: http://test/
targetRevision: null
repoURL: http://test/
chart: test-chart
helm:
passCredentials: null
parameters: []
fileParameters: []
releaseName: test-release-neame
valueFiles: []
ignoreMissingValueFiles: null
values: null
valuesObject: null
skipCrds: null
skipSchemaValidation: null
version: null
kubeVersion: null
apiVersions: []
namespace: null
syncPolicy:
automated:
prune: false

View File

@ -161,6 +161,7 @@ impl<
let helm_chart = self.application.build_push_helm_package(&image).await?;
info!("Pushed new helm chart {helm_chart}");
error!("TODO Make building image configurable/skippable");
let image = self.application.build_push_oci_image().await?;
info!("Pushed new docker image {image}");
@ -194,7 +195,7 @@ impl<
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_name: "harmony-example-rust-webapp-chart".to_string(),
values_overrides: Value::Null,
values_overrides: None,
name: "harmony-demo-rust-webapp".to_string(),
namespace: "harmonydemo-staging".to_string(),
})],
@ -226,7 +227,7 @@ pub struct CDApplicationConfig {
pub version: Version,
pub helm_chart_repo_url: Url,
pub helm_chart_name: String,
pub values_overrides: Value,
pub values_overrides: Option<Value>,
pub name: String,
pub namespace: String,
}

View File

@ -1,5 +1,6 @@
use async_trait::async_trait;
use k8s_openapi::Resource;
use log::error;
use non_blank_string_rs::NonBlankString;
use serde::Serialize;
use std::str::FromStr;
@ -50,6 +51,7 @@ impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for ArgoInterpret {
inventory: &Inventory,
topology: &T,
) -> Result<Outcome, InterpretError> {
error!("Uncomment below, only disabled for debugging");
self.score
.create_interpret()
.execute(inventory, topology)

View File

@ -10,14 +10,25 @@ use crate::{
topology::{HttpServer, Topology, Url},
};
/// Configure an HTTP server that is provided by the Topology
///
/// This Score will let you easily specify a file path to be served by the HTTP server
///
/// For example, if you have a folder of assets at `/var/www/assets` simply do :
///
/// ```rust,ignore
/// StaticFilesHttpScore {
/// files_to_serve: url!("file:///var/www/assets"),
/// }
/// ```
#[derive(Debug, new, Clone, Serialize)]
pub struct HttpScore {
pub struct StaticFilesHttpScore {
files_to_serve: Url,
}
impl<T: Topology + HttpServer> Score<T> for HttpScore {
impl<T: Topology + HttpServer> Score<T> for StaticFilesHttpScore {
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
Box::new(HttpInterpret::new(self.clone()))
Box::new(StaticFilesHttpInterpret::new(self.clone()))
}
fn name(&self) -> String {
@ -26,12 +37,12 @@ impl<T: Topology + HttpServer> Score<T> for HttpScore {
}
#[derive(Debug, new, Clone)]
pub struct HttpInterpret {
score: HttpScore,
pub struct StaticFilesHttpInterpret {
score: StaticFilesHttpScore,
}
#[async_trait]
impl<T: Topology + HttpServer> Interpret<T> for HttpInterpret {
impl<T: Topology + HttpServer> Interpret<T> for StaticFilesHttpInterpret {
async fn execute(
&self,
_inventory: &Inventory,

View File

@ -22,4 +22,4 @@ tokio-util = { version = "0.7.13", features = [ "codec" ] }
tokio-stream = "0.1.17"
[dev-dependencies]
pretty_assertions = "1.4.1"
pretty_assertions.workspace = true