feat: add load balancer score and frontend integration

- Implemented `OKDLoadBalancerScore` and integrated it as a `FrontendScore`.
- Added `FrontendScore` trait for TUI displayable scores.
- Implemented `Display` for `OKDLoadBalancerScore`.
- Updated `ScoreListWidget` to handle `FrontendScore` types.
- Included load balancer score in the TUI.
This commit is contained in:
Jean-Gabriel Gill-Couture 2025-04-03 13:41:29 -04:00
parent e6384da57e
commit ab9b7476a4
8 changed files with 27 additions and 14 deletions

7
Cargo.lock generated
View File

@ -859,13 +859,6 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "example-topology"
version = "0.1.0"
dependencies = [
"rand",
]
[[package]] [[package]]
name = "example-tui" name = "example-tui"
version = "0.1.0" version = "0.1.0"

View File

@ -12,6 +12,12 @@ async fn main() {
let mut maestro = Maestro::new(inventory, topology); let mut maestro = Maestro::new(inventory, topology);
maestro.register_all(vec![ maestro.register_all(vec![
// ADD scores :
// 1. OPNSense setup scores
// 2. Bootstrap node setup
// 3. Control plane setup
// 4. Workers setup
// 5. Various tools and apps setup
Box::new(SuccessScore {}), Box::new(SuccessScore {}),
Box::new(ErrorScore {}), Box::new(ErrorScore {}),
Box::new(PanicScore {}), Box::new(PanicScore {}),

View File

@ -12,7 +12,7 @@ use harmony::{
modules::{ modules::{
dummy::{ErrorScore, PanicScore, SuccessScore}, dummy::{ErrorScore, PanicScore, SuccessScore},
http::HttpScore, http::HttpScore,
okd::{dhcp::OKDDhcpScore, dns::OKDDnsScore}, okd::{dhcp::OKDDhcpScore, dns::OKDDnsScore, load_balancer::OKDLoadBalancerScore},
opnsense::OPNsenseShellCommandScore, opnsense::OPNsenseShellCommandScore,
tftp::TftpScore, tftp::TftpScore,
}, },
@ -78,8 +78,7 @@ async fn main() {
let dhcp_score = OKDDhcpScore::new(&topology, &inventory); let dhcp_score = OKDDhcpScore::new(&topology, &inventory);
let dns_score = OKDDnsScore::new(&topology); let dns_score = OKDDnsScore::new(&topology);
let load_balancer_score = let load_balancer_score = OKDLoadBalancerScore::new(&topology);
harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string())); let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
let http_score = HttpScore::new(Url::LocalFolder( let http_score = HttpScore::new(Url::LocalFolder(

View File

@ -19,3 +19,5 @@ where
Box::new(self.clone()) Box::new(self.clone())
} }
} }
pub trait FrontendScore<T: Topology>: Score<T> + std::fmt::Display {}

View File

@ -334,6 +334,7 @@ impl TftpServer for DummyInfra {
#[async_trait] #[async_trait]
impl HttpServer for DummyInfra { impl HttpServer for DummyInfra {
async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> { async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> {
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA) unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
} }
fn get_ip(&self) -> IpAddress { fn get_ip(&self) -> IpAddress {

View File

@ -5,7 +5,7 @@ use crate::{
data::{Id, Version}, data::{Id, Version},
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
inventory::Inventory, inventory::Inventory,
score::Score, score::{FrontendScore, Score},
topology::{LoadBalancer, LoadBalancerService, Topology}, topology::{LoadBalancer, LoadBalancerService, Topology},
}; };
@ -19,6 +19,8 @@ pub struct LoadBalancerScore {
// uuid? // uuid?
} }
impl <T: Topology + LoadBalancer> FrontendScore<T> for LoadBalancerScore {}
impl<T: Topology + LoadBalancer> Score<T> for LoadBalancerScore { impl<T: Topology + LoadBalancer> Score<T> for LoadBalancerScore {
fn create_interpret(&self) -> Box<dyn Interpret<T>> { fn create_interpret(&self) -> Box<dyn Interpret<T>> {
Box::new(LoadBalancerInterpret::new(self.clone())) Box::new(LoadBalancerInterpret::new(self.clone()))

View File

@ -3,12 +3,20 @@ use std::net::SocketAddr;
use crate::{ use crate::{
interpret::Interpret, interpret::Interpret,
modules::load_balancer::LoadBalancerScore, modules::load_balancer::LoadBalancerScore,
score::Score, score::{FrontendScore, Score},
topology::{ topology::{
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, Topology BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, Topology
}, },
}; };
impl std::fmt::Display for OKDLoadBalancerScore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
impl <T: Topology + LoadBalancer> FrontendScore<T> for OKDLoadBalancerScore {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OKDLoadBalancerScore { pub struct OKDLoadBalancerScore {
load_balancer_score: LoadBalancerScore, load_balancer_score: LoadBalancerScore,

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use crossterm::event::{Event, KeyCode, KeyEventKind}; use crossterm::event::{Event, KeyCode, KeyEventKind};
use harmony::{score::Score, topology::Topology}; use harmony::{modules::okd::load_balancer::OKDLoadBalancerScore, score::Score, topology::{LoadBalancer, Topology}};
use log::{info, warn}; use log::{info, warn};
use ratatui::{ use ratatui::{
layout::Rect, style::{Style, Stylize}, widgets::{List, ListItem, ListState, StatefulWidget, Widget}, Frame layout::Rect, style::{Style, Stylize}, widgets::{List, ListItem, ListState, StatefulWidget, Widget}, Frame
@ -23,10 +23,12 @@ struct Execution<T: Topology> {
score: Box<dyn Score<T>>, score: Box<dyn Score<T>>,
} }
impl <T: Topology + LoadBalancer> FrontendScore<T> for OKDLoadBalancerScore {}
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ScoreListWidget<T: Topology> { pub(crate) struct ScoreListWidget<T: Topology> {
list_state: Arc<RwLock<ListState>>, list_state: Arc<RwLock<ListState>>,
scores: Vec<Box<dyn Score<T>>>, scores: Vec<Box<dyn FrontendScore<T>>>,
execution: Option<Execution<T>>, execution: Option<Execution<T>>,
execution_history: Vec<Execution<T>>, execution_history: Vec<Execution<T>>,
sender: mpsc::Sender<HarmonyTuiEvent<T>>, sender: mpsc::Sender<HarmonyTuiEvent<T>>,