refact: Make RustWebappScore generic, it is now Application score and takes an application and list of features to attach to the application
All checks were successful
Run Check Script / check (pull_request) Successful in -8s

This commit is contained in:
Jean-Gabriel Gill-Couture 2025-07-04 10:27:16 -04:00
parent 6149249a6c
commit b4534c6ee0
5 changed files with 36 additions and 21 deletions

View File

@ -4,7 +4,7 @@ use harmony::{
inventory::Inventory, inventory::Inventory,
maestro::Maestro, maestro::Maestro,
modules::application::{ modules::application::{
RustWebFramework, RustWebapp, RustWebappScore, features::ContinuousDelivery, ApplicationScore, RustWebFramework, RustWebapp, features::ContinuousDelivery,
}, },
topology::{K8sAnywhereTopology, Url}, topology::{K8sAnywhereTopology, Url},
}; };
@ -12,18 +12,20 @@ use harmony::{
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
env_logger::init(); env_logger::init();
let application = 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()),
project_root: PathBuf::from("./examples/rust/webapp"), project_root: PathBuf::from("./examples/rust/webapp"),
framework: Some(RustWebFramework::Leptos), framework: Some(RustWebFramework::Leptos),
}; });
// TODO RustWebappScore should simply take a RustWebApp as config
let app = RustWebappScore { let app = ApplicationScore {
name: "Example Rust Webapp".to_string(), features: vec![
domain: Url::Url(url::Url::parse("https://rustapp.harmony.example.com").unwrap()), Box::new(ContinuousDelivery {
features: vec![Box::new(ContinuousDelivery { application: application.clone(),
application: Arc::new(application.clone()), }),
})], // TODO add monitoring, backups, multisite ha, etc
],
application, application,
}; };

View File

@ -13,7 +13,7 @@ reqwest = { version = "0.11", features = ["blocking", "json"] }
russh = "0.45.0" russh = "0.45.0"
rust-ipmi = "0.1.1" rust-ipmi = "0.1.1"
semver = "1.0.23" semver = "1.0.23"
serde = { version = "1.0.209", features = ["derive"] } serde = { version = "1.0.209", features = ["derive", "rc"] }
serde_json = "1.0.127" serde_json = "1.0.127"
tokio.workspace = true tokio.workspace = true
derive-new.workspace = true derive-new.workspace = true

View File

@ -153,6 +153,11 @@ impl<
"TODO reverse helm chart packaging and docker image build. I put helm package first for faster iterations" "TODO reverse helm chart packaging and docker image build. I put helm package first for faster iterations"
); );
// TODO Write CI/CD workflow files
// we can autotedect the CI type using the remote url (default to github action for github
// url, etc..)
// Or ask for it when unknown
let helm_chart = self.application.build_push_helm_package(&image).await?; let helm_chart = self.application.build_push_helm_package(&image).await?;
info!("Pushed new helm chart {helm_chart}"); info!("Pushed new helm chart {helm_chart}");

View File

@ -23,13 +23,13 @@ pub trait Application: std::fmt::Debug + Send + Sync {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ApplicationInterpret<T: Topology + std::fmt::Debug> { pub struct ApplicationInterpret<A: Application, T: Topology + std::fmt::Debug> {
features: Vec<Box<dyn ApplicationFeature<T>>>, features: Vec<Box<dyn ApplicationFeature<T>>>,
application: Arc<Box<dyn Application>>, application: Arc<A>,
} }
#[async_trait] #[async_trait]
impl<T: Topology + std::fmt::Debug> Interpret<T> for ApplicationInterpret<T> { impl<A: Application, T: Topology + std::fmt::Debug> Interpret<T> for ApplicationInterpret<A, T> {
async fn execute( async fn execute(
&self, &self,
_inventory: &Inventory, _inventory: &Inventory,

View File

@ -19,23 +19,30 @@ use crate::{
use super::{Application, ApplicationFeature, ApplicationInterpret, HelmPackage, OCICompliant}; use super::{Application, ApplicationFeature, ApplicationInterpret, HelmPackage, OCICompliant};
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct RustWebappScore<T: Topology + Clone + Serialize> { pub struct ApplicationScore<A: Application + Serialize, T: Topology + Clone + Serialize>
pub name: String, where
pub domain: Url, Arc<A>: Serialize + Clone,
{
pub features: Vec<Box<dyn ApplicationFeature<T>>>, pub features: Vec<Box<dyn ApplicationFeature<T>>>,
pub application: RustWebapp, pub application: Arc<A>,
} }
impl<T: Topology + std::fmt::Debug + Clone + Serialize + 'static> Score<T> for RustWebappScore<T> { impl<
A: Application + Serialize + Clone + 'static,
T: Topology + std::fmt::Debug + Clone + Serialize + 'static,
> Score<T> for ApplicationScore<A, T>
where
Arc<A>: Serialize,
{
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> { fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
Box::new(ApplicationInterpret { Box::new(ApplicationInterpret {
features: self.features.clone(), features: self.features.clone(),
application: Arc::new(Box::new(self.application.clone())), application: self.application.clone(),
}) })
} }
fn name(&self) -> String { fn name(&self) -> String {
format!("{}-RustWebapp", self.name) format!("Application: {}", self.application.name())
} }
} }
@ -47,6 +54,7 @@ pub enum RustWebFramework {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct RustWebapp { pub struct RustWebapp {
pub name: String, pub name: String,
pub domain: Url,
/// The path to the root of the Rust project to be containerized. /// The path to the root of the Rust project to be containerized.
pub project_root: PathBuf, pub project_root: PathBuf,
pub framework: Option<RustWebFramework>, pub framework: Option<RustWebFramework>,