This commit is contained in:
Ian Letourneau 2025-04-29 15:55:58 -04:00
parent 254f392cb5
commit 2f7c4924c1
7 changed files with 55 additions and 9 deletions

View File

@ -2,9 +2,10 @@ use harmony::{
data::Version, data::Version,
inventory::Inventory, inventory::Inventory,
maestro::Maestro, maestro::Maestro,
modules::lamp::{LAMPConfig, LAMPScore}, modules::lamp::{LAMPConfig, LAMPProfile, LAMPScore},
topology::{K8sAnywhereTopology, Url}, topology::{K8sAnywhereTopology, Url},
}; };
use std::collections::HashMap;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
@ -17,6 +18,10 @@ async fn main() {
project_root: "./php".into(), project_root: "./php".into(),
..Default::default() ..Default::default()
}, },
profiles: HashMap::from([
("dev", LAMPProfile { ssl_enabled: false }),
("prod", LAMPProfile { ssl_enabled: true }),
]),
}; };
let mut maestro = Maestro::<K8sAnywhereTopology>::initialize( let mut maestro = Maestro::<K8sAnywhereTopology>::initialize(

View File

@ -39,8 +39,12 @@ impl std::fmt::Display for InterpretName {
#[async_trait] #[async_trait]
pub trait Interpret<T>: std::fmt::Debug + Send { pub trait Interpret<T>: std::fmt::Debug + Send {
async fn execute(&self, inventory: &Inventory, topology: &T) async fn execute(
-> Result<Outcome, InterpretError>; &self,
inventory: &Inventory,
topology: &T,
profile: &String,
) -> Result<Outcome, InterpretError>;
fn get_name(&self) -> InterpretName; fn get_name(&self) -> InterpretName;
fn get_version(&self) -> Version; fn get_version(&self) -> Version;
fn get_status(&self) -> InterpretStatus; fn get_status(&self) -> InterpretStatus;

View File

@ -16,20 +16,23 @@ pub struct Maestro<T: Topology> {
topology: T, topology: T,
scores: Arc<RwLock<ScoreVec<T>>>, scores: Arc<RwLock<ScoreVec<T>>>,
topology_preparation_result: Mutex<Option<Outcome>>, topology_preparation_result: Mutex<Option<Outcome>>,
profile: String,
} }
impl<T: Topology> Maestro<T> { impl<T: Topology> Maestro<T> {
pub fn new(inventory: Inventory, topology: T) -> Self { pub fn new(inventory: Inventory, topology: T, profile: String) -> Self {
Self { Self {
inventory, inventory,
topology, topology,
scores: Arc::new(RwLock::new(Vec::new())), scores: Arc::new(RwLock::new(Vec::new())),
topology_preparation_result: None.into(), topology_preparation_result: None.into(),
profile,
} }
} }
pub async fn initialize(inventory: Inventory, topology: T) -> Result<Self, InterpretError> { pub async fn initialize(inventory: Inventory, topology: T) -> Result<Self, InterpretError> {
let instance = Self::new(inventory, topology); let profile = "dev".to_string(); // TODO: retrieve from env?
let instance = Self::new(inventory, topology, profile);
instance.prepare_topology().await?; instance.prepare_topology().await?;
Ok(instance) Ok(instance)
} }
@ -78,9 +81,11 @@ impl<T: Topology> Maestro<T> {
); );
} }
info!("Running score {score:?}"); info!("Running score {score:?}");
let interpret = score.create_interpret(); let interpret = score.apply_profile(&self.profile).create_interpret();
info!("Launching interpret {interpret:?}"); info!("Launching interpret {interpret:?}");
let result = interpret.execute(&self.inventory, &self.topology).await; let result = interpret
.execute(&self.inventory, &self.topology, &self.profile)
.await;
info!("Got result {result:?}"); info!("Got result {result:?}");
result result
} }

View File

@ -8,6 +8,9 @@ use super::{interpret::Interpret, topology::Topology};
pub trait Score<T: Topology>: pub trait Score<T: Topology>:
std::fmt::Debug + ScoreToString<T> + Send + Sync + CloneBoxScore<T> + SerializeScore<T> std::fmt::Debug + ScoreToString<T> + Send + Sync + CloneBoxScore<T> + SerializeScore<T>
{ {
fn apply_profile(&self, profile: &String) -> Box<dyn Score<T>> {
Box::new(self.clone())
}
fn create_interpret(&self) -> Box<dyn Interpret<T>>; fn create_interpret(&self) -> Box<dyn Interpret<T>>;
fn name(&self) -> String; fn name(&self) -> String;
} }

View File

@ -75,6 +75,7 @@ impl<T: Topology> Interpret<T> for DummyInterpret {
&self, &self,
_inventory: &Inventory, _inventory: &Inventory,
_topology: &T, _topology: &T,
_profile: &String,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {
self.result.clone() self.result.clone()
} }
@ -121,6 +122,7 @@ impl<T: Topology> Interpret<T> for PanicInterpret {
&self, &self,
_inventory: &Inventory, _inventory: &Inventory,
_topology: &T, _topology: &T,
_profile: &String,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {
panic!("Panic interpret always panics when executed") panic!("Panic interpret always panics when executed")
} }

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use async_trait::async_trait; use async_trait::async_trait;
@ -19,6 +21,7 @@ pub struct LAMPScore {
pub domain: Url, pub domain: Url,
pub config: LAMPConfig, pub config: LAMPConfig,
pub php_version: Version, pub php_version: Version,
pub profiles: HashMap<&'static str, LAMPProfile>,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@ -27,6 +30,11 @@ pub struct LAMPConfig {
pub ssl_enabled: bool, pub ssl_enabled: bool,
} }
#[derive(Debug, Clone, Serialize)]
pub struct LAMPProfile {
pub ssl_enabled: bool,
}
impl Default for LAMPConfig { impl Default for LAMPConfig {
fn default() -> Self { fn default() -> Self {
LAMPConfig { LAMPConfig {
@ -37,6 +45,23 @@ impl Default for LAMPConfig {
} }
impl<T: Topology + K8sclient> Score<T> for LAMPScore { impl<T: Topology + K8sclient> Score<T> for LAMPScore {
fn apply_profile(&self, profile: &String) -> Box<dyn Score<T>> {
let profile = match self.profiles.get(profile.as_str()) {
Some(profile) => profile,
None => panic!("Not good"), // TODO: better handling
};
let config = LAMPConfig {
ssl_enabled: profile.ssl_enabled,
..self.config.clone()
};
Box::new(LAMPScore {
config,
..self.clone()
})
}
fn create_interpret(&self) -> Box<dyn Interpret<T>> { fn create_interpret(&self) -> Box<dyn Interpret<T>> {
Box::new(LAMPInterpret { Box::new(LAMPInterpret {
score: self.clone(), score: self.clone(),
@ -59,6 +84,7 @@ impl<T: Topology + K8sclient> Interpret<T> for LAMPInterpret {
&self, &self,
inventory: &Inventory, inventory: &Inventory,
topology: &T, topology: &T,
profile: &String,
) -> Result<Outcome, InterpretError> { ) -> Result<Outcome, InterpretError> {
let image_name = match self.build_docker_image() { let image_name = match self.build_docker_image() {
Ok(name) => name, Ok(name) => name,
@ -78,8 +104,9 @@ impl<T: Topology + K8sclient> Interpret<T> for LAMPInterpret {
info!("LAMP deployment_score {deployment_score:?}"); info!("LAMP deployment_score {deployment_score:?}");
todo!(); todo!();
deployment_score deployment_score
.apply_profile(profile)
.create_interpret() .create_interpret()
.execute(inventory, topology) .execute(inventory, topology, profile)
.await?; .await?;
todo!() todo!()
} }

View File

@ -41,7 +41,7 @@ pub mod tui {
/// async fn main() { /// async fn main() {
/// let inventory = Inventory::autoload(); /// let inventory = Inventory::autoload();
/// let topology = HAClusterTopology::autoload(); /// let topology = HAClusterTopology::autoload();
/// let mut maestro = Maestro::new(inventory, topology); /// let mut maestro = Maestro::new(inventory, topology, "local");
/// ///
/// maestro.register_all(vec![ /// maestro.register_all(vec![
/// Box::new(SuccessScore {}), /// Box::new(SuccessScore {}),