forked from NationTech/harmony
feat(topology): generalize Score and Interpret implementations with topology traits
Refactor various `Score` and `Interpret` implementations to utilize generic `Topology` traits, removing hardcoded dependencies on `HAClusterTopology`. This enhancement allows for more flexible and extensible code, accommodating different types of network topologies.
This commit is contained in:
parent
d7897f29c4
commit
fda007f014
@ -7,7 +7,7 @@ use super::{
|
||||
data::{Id, Version},
|
||||
executors::ExecutorError,
|
||||
inventory::Inventory,
|
||||
topology::HAClusterTopology,
|
||||
topology::Topology,
|
||||
};
|
||||
|
||||
pub enum InterpretName {
|
||||
@ -37,12 +37,9 @@ impl std::fmt::Display for InterpretName {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Interpret: std::fmt::Debug + Send {
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
) -> Result<Outcome, InterpretError>;
|
||||
pub trait Interpret<T: Topology>: std::fmt::Debug + Send {
|
||||
async fn execute(&self, inventory: &Inventory, topology: &T)
|
||||
-> Result<Outcome, InterpretError>;
|
||||
fn get_name(&self) -> InterpretName;
|
||||
fn get_version(&self) -> Version;
|
||||
fn get_status(&self) -> InterpretStatus;
|
||||
|
||||
@ -6,19 +6,19 @@ use super::{
|
||||
interpret::{InterpretError, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::HAClusterTopology,
|
||||
topology::Topology,
|
||||
};
|
||||
|
||||
type ScoreVec = Vec<Box<dyn Score>>;
|
||||
type ScoreVec<T: Topology> = Vec<Box<dyn Score<T>>>;
|
||||
|
||||
pub struct Maestro {
|
||||
pub struct Maestro<T: Topology> {
|
||||
inventory: Inventory,
|
||||
topology: HAClusterTopology,
|
||||
scores: Arc<RwLock<ScoreVec>>,
|
||||
topology: T,
|
||||
scores: Arc<RwLock<ScoreVec<T>>>,
|
||||
}
|
||||
|
||||
impl Maestro {
|
||||
pub fn new(inventory: Inventory, topology: HAClusterTopology) -> Self {
|
||||
impl<T: Topology> Maestro<T> {
|
||||
pub fn new(inventory: Inventory, topology: T) -> Self {
|
||||
Self {
|
||||
inventory,
|
||||
topology,
|
||||
@ -51,12 +51,15 @@ impl Maestro {
|
||||
info!("Starting Maestro");
|
||||
}
|
||||
|
||||
pub fn register_all(&mut self, mut scores: ScoreVec) {
|
||||
pub fn register_all(&mut self, mut scores: ScoreVec<T>) {
|
||||
let mut score_mut = self.scores.write().expect("Should acquire lock");
|
||||
score_mut.append(&mut scores);
|
||||
}
|
||||
|
||||
pub async fn interpret(&self, score: Box<dyn Score>) -> Result<Outcome, InterpretError> {
|
||||
pub async fn interpret<S>(&self, score: S) -> Result<Outcome, InterpretError>
|
||||
where
|
||||
S: Score<T>,
|
||||
{
|
||||
info!("Running score {score:?}");
|
||||
let interpret = score.create_interpret();
|
||||
info!("Launching interpret {interpret:?}");
|
||||
@ -65,7 +68,7 @@ impl Maestro {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn scores(&self) -> Arc<RwLock<ScoreVec>> {
|
||||
pub fn scores(&self) -> Arc<RwLock<ScoreVec<T>>> {
|
||||
self.scores.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use super::interpret::Interpret;
|
||||
use super::{interpret::Interpret, topology::Topology};
|
||||
|
||||
pub trait Score: std::fmt::Debug + Send + Sync {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret>;
|
||||
pub trait Score<T: Topology>: std::fmt::Debug + Send + Sync {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>>;
|
||||
fn name(&self) -> String;
|
||||
fn clone_box(&self) -> Box<dyn Score>;
|
||||
}
|
||||
|
||||
@ -15,9 +15,11 @@ use super::IpAddress;
|
||||
use super::LoadBalancer;
|
||||
use super::LoadBalancerService;
|
||||
use super::LogicalHost;
|
||||
use super::OcK8sclient;
|
||||
use super::Router;
|
||||
use super::TftpServer;
|
||||
|
||||
use super::Topology;
|
||||
use super::Url;
|
||||
use super::openshift::OpenshiftClient;
|
||||
use std::sync::Arc;
|
||||
@ -38,11 +40,20 @@ pub struct HAClusterTopology {
|
||||
pub switch: Vec<LogicalHost>,
|
||||
}
|
||||
|
||||
impl HAClusterTopology {
|
||||
pub async fn oc_client(&self) -> Result<Arc<OpenshiftClient>, kube::Error> {
|
||||
impl Topology for HAClusterTopology {
|
||||
fn name(&self) -> &str {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl OcK8sclient for HAClusterTopology {
|
||||
async fn oc_client(&self) -> Result<Arc<OpenshiftClient>, kube::Error> {
|
||||
Ok(Arc::new(OpenshiftClient::try_default().await?))
|
||||
}
|
||||
}
|
||||
|
||||
impl HAClusterTopology {
|
||||
pub fn autoload() -> Self {
|
||||
let dummy_infra = Arc::new(DummyInfra {});
|
||||
let dummy_host = LogicalHost {
|
||||
@ -67,6 +78,7 @@ impl HAClusterTopology {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DummyInfra;
|
||||
|
||||
const UNIMPLEMENTED_DUMMY_INFRA: &str = "This is a dummy infrastructure, no operation is supported";
|
||||
|
||||
@ -16,6 +16,12 @@ pub use tftp::*;
|
||||
|
||||
use std::net::IpAddr;
|
||||
|
||||
pub trait Topology {
|
||||
fn name(&self) -> &str;
|
||||
}
|
||||
|
||||
pub trait Capability {}
|
||||
|
||||
pub type IpAddress = IpAddr;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use std::{net::Ipv4Addr, str::FromStr};
|
||||
use std::{net::Ipv4Addr, str::FromStr, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use harmony_types::net::MacAddress;
|
||||
|
||||
use crate::executors::ExecutorError;
|
||||
|
||||
use super::{IpAddress, LogicalHost};
|
||||
use super::{openshift::OpenshiftClient, IpAddress, LogicalHost};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DHCPStaticEntry {
|
||||
@ -40,9 +40,14 @@ impl std::fmt::Debug for dyn Firewall {
|
||||
pub struct NetworkDomain {
|
||||
pub name: String,
|
||||
}
|
||||
#[async_trait]
|
||||
pub trait OcK8sclient: Send + Sync + std::fmt::Debug {
|
||||
async fn oc_client(&self) -> Result<Arc<OpenshiftClient>, kube::Error>;
|
||||
}
|
||||
|
||||
|
||||
#[async_trait]
|
||||
pub trait DhcpServer: Send + Sync {
|
||||
pub trait DhcpServer: Send + Sync + std::fmt::Debug {
|
||||
async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError>;
|
||||
async fn remove_static_mapping(&self, mac: &MacAddress) -> Result<(), ExecutorError>;
|
||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
||||
@ -53,12 +58,6 @@ pub trait DhcpServer: Send + Sync {
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for dyn DhcpServer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("DhcpServer {}", self.get_ip()))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait DnsServer: Send + Sync {
|
||||
async fn register_dhcp_leases(&self, register: bool) -> Result<(), ExecutorError>;
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
domain::{data::Version, interpret::InterpretStatus},
|
||||
interpret::{Interpret, InterpretError, InterpretName, Outcome},
|
||||
inventory::Inventory,
|
||||
topology::{DHCPStaticEntry, HAClusterTopology, HostBinding, IpAddress},
|
||||
topology::{DHCPStaticEntry, DhcpServer, HAClusterTopology, HostBinding, IpAddress, Topology},
|
||||
};
|
||||
|
||||
use crate::domain::score::Score;
|
||||
@ -20,18 +20,14 @@ pub struct DhcpScore {
|
||||
pub boot_filename: Option<String>,
|
||||
}
|
||||
|
||||
impl Score for DhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + DhcpServer> Score<T> for DhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(DhcpInterpret::new(self.clone()))
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"DhcpScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.opnsense.org/manual/dhcp.html#advanced-settings
|
||||
@ -52,10 +48,10 @@ impl DhcpInterpret {
|
||||
status: InterpretStatus::QUEUED,
|
||||
}
|
||||
}
|
||||
async fn add_static_entries(
|
||||
async fn add_static_entries<D: DhcpServer>(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
dhcp_server: &D,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let dhcp_entries: Vec<DHCPStaticEntry> = self
|
||||
.score
|
||||
@ -78,7 +74,6 @@ impl DhcpInterpret {
|
||||
.collect();
|
||||
info!("DHCPStaticEntry : {:?}", dhcp_entries);
|
||||
|
||||
let dhcp_server = Arc::new(topology.dhcp_server.clone());
|
||||
info!("DHCP server : {:?}", dhcp_server);
|
||||
|
||||
let number_new_entries = dhcp_entries.len();
|
||||
@ -96,14 +91,13 @@ impl DhcpInterpret {
|
||||
))
|
||||
}
|
||||
|
||||
async fn set_pxe_options(
|
||||
async fn set_pxe_options<D: DhcpServer>(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
dhcp_server: &D,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let next_server_outcome = match self.score.next_server {
|
||||
Some(next_server) => {
|
||||
let dhcp_server = Arc::new(topology.dhcp_server.clone());
|
||||
dhcp_server.set_next_server(next_server).await?;
|
||||
Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
@ -115,7 +109,6 @@ impl DhcpInterpret {
|
||||
|
||||
let boot_filename_outcome = match &self.score.boot_filename {
|
||||
Some(boot_filename) => {
|
||||
let dhcp_server = Arc::new(topology.dhcp_server.clone());
|
||||
dhcp_server.set_boot_filename(&boot_filename).await?;
|
||||
Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
@ -142,7 +135,7 @@ impl DhcpInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for DhcpInterpret {
|
||||
impl<T: Topology + DhcpServer> Interpret<T> for DhcpInterpret {
|
||||
fn get_name(&self) -> InterpretName {
|
||||
InterpretName::OPNSenseDHCP
|
||||
}
|
||||
@ -162,15 +155,15 @@ impl Interpret for DhcpInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
info!("Executing {} on inventory {inventory:?}", self.get_name());
|
||||
info!("Executing DhcpInterpret on inventory {inventory:?}");
|
||||
|
||||
self.set_pxe_options(inventory, topology).await?;
|
||||
|
||||
self.add_static_entries(inventory, topology).await?;
|
||||
|
||||
topology.dhcp_server.commit_config().await?;
|
||||
topology.commit_config().await?;
|
||||
|
||||
Ok(Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::{DnsRecord, HAClusterTopology},
|
||||
topology::{DnsRecord, DnsServer, HAClusterTopology, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, new, Clone)]
|
||||
@ -16,18 +16,14 @@ pub struct DnsScore {
|
||||
register_dhcp_leases: Option<bool>,
|
||||
}
|
||||
|
||||
impl Score for DnsScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + DnsServer> Score<T> for DnsScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(DnsInterpret::new(self.clone()))
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"DnsScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.opnsense.org/manual/dhcp.html#advanced-settings
|
||||
@ -48,12 +44,11 @@ impl DnsInterpret {
|
||||
status: InterpretStatus::QUEUED,
|
||||
}
|
||||
}
|
||||
async fn serve_dhcp_entries(
|
||||
async fn serve_dhcp_entries<T: DnsServer>(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
dns: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let dns = topology.dns_server.clone();
|
||||
if let Some(register) = self.score.register_dhcp_leases {
|
||||
dns.register_dhcp_leases(register).await?;
|
||||
}
|
||||
@ -64,15 +59,12 @@ impl DnsInterpret {
|
||||
))
|
||||
}
|
||||
|
||||
async fn ensure_hosts_registered(
|
||||
async fn ensure_hosts_registered<D: DnsServer>(
|
||||
&self,
|
||||
topology: &HAClusterTopology,
|
||||
dns_server: &D,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let entries = &self.score.dns_entries;
|
||||
topology
|
||||
.dns_server
|
||||
.ensure_hosts_registered(entries.clone())
|
||||
.await?;
|
||||
dns_server.ensure_hosts_registered(entries.clone()).await?;
|
||||
|
||||
Ok(Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
@ -85,7 +77,7 @@ impl DnsInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for DnsInterpret {
|
||||
impl<T: Topology + DnsServer> Interpret<T> for DnsInterpret {
|
||||
fn get_name(&self) -> InterpretName {
|
||||
InterpretName::OPNSenseDns
|
||||
}
|
||||
@ -105,14 +97,14 @@ impl Interpret for DnsInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
info!("Executing {} on inventory {inventory:?}", self.get_name());
|
||||
info!("Executing {} on inventory {inventory:?}", <DnsInterpret as Interpret<T>>::get_name(self));
|
||||
|
||||
self.serve_dhcp_entries(inventory, topology).await?;
|
||||
self.ensure_hosts_registered(&topology).await?;
|
||||
self.ensure_hosts_registered(topology).await?;
|
||||
|
||||
topology.dns_server.commit_config().await?;
|
||||
topology.commit_config().await?;
|
||||
|
||||
Ok(Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
|
||||
@ -5,7 +5,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::HAClusterTopology,
|
||||
topology::{HAClusterTopology, Topology},
|
||||
};
|
||||
|
||||
/// Score that always errors. This is only useful for development/testing purposes. It does nothing
|
||||
@ -13,8 +13,8 @@ use crate::{
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErrorScore;
|
||||
|
||||
impl Score for ErrorScore {
|
||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret> {
|
||||
impl<T: Topology> Score<T> for ErrorScore {
|
||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
|
||||
Box::new(DummyInterpret {
|
||||
result: Err(InterpretError::new("Error Score default error".to_string())),
|
||||
status: InterpretStatus::QUEUED,
|
||||
@ -24,10 +24,6 @@ impl Score for ErrorScore {
|
||||
fn name(&self) -> String {
|
||||
"ErrorScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Score that always succeeds. This is only useful for development/testing purposes. It does nothing
|
||||
@ -35,8 +31,8 @@ impl Score for ErrorScore {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SuccessScore;
|
||||
|
||||
impl Score for SuccessScore {
|
||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret> {
|
||||
impl<T: Topology> Score<T> for SuccessScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(DummyInterpret {
|
||||
result: Ok(Outcome::success("SuccessScore default success".to_string())),
|
||||
status: InterpretStatus::QUEUED,
|
||||
@ -46,10 +42,6 @@ impl Score for SuccessScore {
|
||||
fn name(&self) -> String {
|
||||
"SuccessScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// An interpret that only returns the result it is given when built. It does nothing else. Only
|
||||
@ -61,7 +53,7 @@ struct DummyInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for DummyInterpret {
|
||||
impl<T: Topology> Interpret<T> for DummyInterpret {
|
||||
fn get_name(&self) -> InterpretName {
|
||||
InterpretName::Dummy
|
||||
}
|
||||
@ -81,7 +73,7 @@ impl Interpret for DummyInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
_topology: &HAClusterTopology,
|
||||
_topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
self.result.clone()
|
||||
}
|
||||
@ -92,18 +84,14 @@ impl Interpret for DummyInterpret {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PanicScore;
|
||||
|
||||
impl Score for PanicScore {
|
||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret> {
|
||||
impl<T: Topology> Score<T> for PanicScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(PanicInterpret {})
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"PanicScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// An interpret that always panics when executed. Useful for development/testing purposes.
|
||||
@ -111,7 +99,7 @@ impl Score for PanicScore {
|
||||
struct PanicInterpret;
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for PanicInterpret {
|
||||
impl<T: Topology> Interpret<T> for PanicInterpret {
|
||||
fn get_name(&self) -> InterpretName {
|
||||
InterpretName::Panic
|
||||
}
|
||||
@ -131,7 +119,7 @@ impl Interpret for PanicInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
_topology: &HAClusterTopology,
|
||||
_topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
panic!("Panic interpret always panics when executed")
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, Url},
|
||||
topology::{HAClusterTopology, HttpServer, Topology, Url},
|
||||
};
|
||||
|
||||
#[derive(Debug, new, Clone)]
|
||||
@ -14,18 +14,14 @@ pub struct HttpScore {
|
||||
files_to_serve: Url,
|
||||
}
|
||||
|
||||
impl Score for HttpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + HttpServer> Score<T> for HttpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(HttpInterpret::new(self.clone()))
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"HttpScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, new, Clone)]
|
||||
@ -34,13 +30,12 @@ pub struct HttpInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for HttpInterpret {
|
||||
impl<T: Topology + HttpServer> Interpret<T> for HttpInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
http_server: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let http_server = &topology.http_server;
|
||||
http_server.ensure_initialized().await?;
|
||||
// http_server.set_ip(topology.router.get_gateway()).await?;
|
||||
http_server.serve_files(&self.score.files_to_serve).await?;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use k8s_openapi::api::apps::v1::Deployment;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{interpret::Interpret, score::Score};
|
||||
use crate::{interpret::Interpret, score::Score, topology::{OcK8sclient, Topology}};
|
||||
|
||||
use super::resource::{K8sResourceInterpret, K8sResourceScore};
|
||||
|
||||
@ -11,8 +11,8 @@ pub struct K8sDeploymentScore {
|
||||
pub image: String,
|
||||
}
|
||||
|
||||
impl Score for K8sDeploymentScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl <T:Topology + OcK8sclient> Score<T> for K8sDeploymentScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
let deployment: Deployment = serde_json::from_value(json!(
|
||||
{
|
||||
"metadata": {
|
||||
@ -51,8 +51,4 @@ impl Score for K8sDeploymentScore {
|
||||
fn name(&self) -> String {
|
||||
"K8sDeploymentScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::HAClusterTopology,
|
||||
topology::{HAClusterTopology, OcK8sclient, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -34,21 +34,18 @@ impl<
|
||||
+ 'static
|
||||
+ Send
|
||||
+ Clone,
|
||||
> Score for K8sResourceScore<K>
|
||||
T: Topology,
|
||||
> Score<T> for K8sResourceScore<K>
|
||||
where
|
||||
<K as kube::Resource>::DynamicType: Default,
|
||||
{
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"K8sResourceScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -66,14 +63,15 @@ impl<
|
||||
+ Default
|
||||
+ Send
|
||||
+ Sync,
|
||||
> Interpret for K8sResourceInterpret<K>
|
||||
T: Topology + OcK8sclient,
|
||||
> Interpret<T> for K8sResourceInterpret<K>
|
||||
where
|
||||
<K as kube::Resource>::DynamicType: Default,
|
||||
{
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
topology
|
||||
.oc_client()
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
inventory::Inventory,
|
||||
modules::k8s::deployment::K8sDeploymentScore,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, Url},
|
||||
topology::{HAClusterTopology, OcK8sclient, Topology, Url},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -34,18 +34,14 @@ impl Default for LAMPConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for LAMPScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl <T:Topology> Score<T> for LAMPScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"LampScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -54,14 +50,14 @@ pub struct LAMPInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for LAMPInterpret {
|
||||
impl <T:Topology + OcK8sclient> Interpret<T> for LAMPInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let deployment_score = K8sDeploymentScore {
|
||||
name: self.score.name(),
|
||||
name: <LAMPScore as Score<T>>::name(&self.score),
|
||||
image: "local_image".to_string(),
|
||||
};
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, LoadBalancerService},
|
||||
topology::{HAClusterTopology, LoadBalancer, LoadBalancerService, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -19,18 +19,14 @@ pub struct LoadBalancerScore {
|
||||
// uuid?
|
||||
}
|
||||
|
||||
impl Score for LoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + LoadBalancer> Score<T> for LoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(LoadBalancerInterpret::new(self.clone()))
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"LoadBalancerScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -51,37 +47,32 @@ impl LoadBalancerInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for LoadBalancerInterpret {
|
||||
impl<T: Topology + LoadBalancer> Interpret<T> for LoadBalancerInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
load_balancer: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
info!(
|
||||
"Making sure Load Balancer is initialized: {:?}",
|
||||
topology.load_balancer.ensure_initialized().await?
|
||||
load_balancer.ensure_initialized().await?
|
||||
);
|
||||
|
||||
for service in self.score.public_services.iter() {
|
||||
info!("Ensuring service exists {service:?}");
|
||||
topology
|
||||
.load_balancer
|
||||
.ensure_service_exists(service)
|
||||
.await?;
|
||||
|
||||
load_balancer.ensure_service_exists(service).await?;
|
||||
}
|
||||
|
||||
for service in self.score.private_services.iter() {
|
||||
info!("Ensuring private service exists {service:?}");
|
||||
topology
|
||||
.load_balancer
|
||||
.ensure_service_exists(service)
|
||||
.await?;
|
||||
load_balancer.ensure_service_exists(service).await?;
|
||||
}
|
||||
|
||||
info!("Applying load balancer configuration");
|
||||
topology.load_balancer.commit_config().await?;
|
||||
load_balancer.commit_config().await?;
|
||||
info!("Making a full reload and restart of haproxy");
|
||||
topology.load_balancer.reload_restart().await?;
|
||||
load_balancer.reload_restart().await?;
|
||||
Ok(Outcome::success(format!(
|
||||
"Load balancer successfully configured {} services",
|
||||
self.score.public_services.len() + self.score.private_services.len()
|
||||
|
||||
@ -3,7 +3,7 @@ use crate::{
|
||||
inventory::Inventory,
|
||||
modules::dhcp::DhcpScore,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, HostBinding},
|
||||
topology::{DhcpServer, HAClusterTopology, HostBinding, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -46,16 +46,12 @@ impl OKDBootstrapDhcpScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapDhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + DhcpServer> Score<T> for OKDBootstrapDhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
self.dhcp_score.create_interpret()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OKDBootstrapDhcpScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,7 @@ use crate::{
|
||||
modules::load_balancer::LoadBalancerScore,
|
||||
score::Score,
|
||||
topology::{
|
||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode,
|
||||
LoadBalancerService,
|
||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, Topology
|
||||
},
|
||||
};
|
||||
|
||||
@ -69,16 +68,12 @@ impl OKDBootstrapLoadBalancerScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapLoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + LoadBalancer> Score<T> for OKDBootstrapLoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
self.load_balancer_score.create_interpret()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OKDBootstrapLoadBalancerScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use crate::{
|
||||
inventory::Inventory,
|
||||
modules::dhcp::DhcpScore,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, HostBinding},
|
||||
topology::{DhcpServer, HAClusterTopology, HostBinding, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -38,16 +38,12 @@ impl OKDDhcpScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDDhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + DhcpServer> Score<T> for OKDDhcpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
self.dhcp_score.create_interpret()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OKDDhcpScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ use crate::{
|
||||
interpret::Interpret,
|
||||
modules::dns::DnsScore,
|
||||
score::Score,
|
||||
topology::{DnsRecord, DnsRecordType, HAClusterTopology},
|
||||
topology::{DnsRecord, DnsRecordType, DnsServer, HAClusterTopology, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -40,16 +40,12 @@ impl OKDDnsScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDDnsScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + DnsServer> Score<T> for OKDDnsScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
self.dns_score.create_interpret()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OKDDnsScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,7 @@ use crate::{
|
||||
modules::load_balancer::LoadBalancerScore,
|
||||
score::Score,
|
||||
topology::{
|
||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode,
|
||||
LoadBalancerService,
|
||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, Topology
|
||||
},
|
||||
};
|
||||
|
||||
@ -80,16 +79,12 @@ impl OKDLoadBalancerScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDLoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology + LoadBalancer> Score<T> for OKDLoadBalancerScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
self.load_balancer_score.create_interpret()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OKDLoadBalancerScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::HAClusterTopology,
|
||||
topology::{HAClusterTopology, Topology},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -17,8 +17,8 @@ pub struct OPNsenseShellCommandScore {
|
||||
pub command: String,
|
||||
}
|
||||
|
||||
impl Score for OPNsenseShellCommandScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology> Score<T> for OPNsenseShellCommandScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(OPNsenseShellInterpret {
|
||||
status: InterpretStatus::QUEUED,
|
||||
score: self.clone(),
|
||||
@ -28,10 +28,6 @@ impl Score for OPNsenseShellCommandScore {
|
||||
fn name(&self) -> String {
|
||||
"OPNSenseShellCommandScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -41,11 +37,11 @@ pub struct OPNsenseShellInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for OPNsenseShellInterpret {
|
||||
impl <T:Topology> Interpret<T> for OPNsenseShellInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
_topology: &HAClusterTopology,
|
||||
_topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let output = self
|
||||
.score
|
||||
|
||||
@ -5,6 +5,7 @@ use tokio::sync::RwLock;
|
||||
use crate::{
|
||||
interpret::{Interpret, InterpretStatus},
|
||||
score::Score,
|
||||
topology::Topology,
|
||||
};
|
||||
|
||||
use super::{OPNsenseShellCommandScore, OPNsenseShellInterpret};
|
||||
@ -14,8 +15,8 @@ pub struct OPNSenseLaunchUpgrade {
|
||||
pub opnsense: Arc<RwLock<opnsense_config::Config>>,
|
||||
}
|
||||
|
||||
impl Score for OPNSenseLaunchUpgrade {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl<T: Topology> Score<T> for OPNSenseLaunchUpgrade {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
let score = OPNsenseShellCommandScore {
|
||||
opnsense: self.opnsense.clone(),
|
||||
command: "/usr/local/opnsense/scripts/firmware/update.sh".to_string(),
|
||||
@ -30,8 +31,4 @@ impl Score for OPNSenseLaunchUpgrade {
|
||||
fn name(&self) -> String {
|
||||
"OPNSenseLaunchUpgrade".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, Url},
|
||||
topology::{HAClusterTopology, Router, TftpServer, Topology, Url},
|
||||
};
|
||||
|
||||
#[derive(Debug, new, Clone)]
|
||||
@ -14,18 +14,14 @@ pub struct TftpScore {
|
||||
files_to_serve: Url,
|
||||
}
|
||||
|
||||
impl Score for TftpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
impl <T:Topology + TftpServer + Router> Score<T> for TftpScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(TftpInterpret::new(self.clone()))
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"TftpScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, new, Clone)]
|
||||
@ -34,18 +30,17 @@ pub struct TftpInterpret {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interpret for TftpInterpret {
|
||||
impl <T:Topology + TftpServer + Router> Interpret<T> for TftpInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
topology: &HAClusterTopology,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
let tftp_server = &topology.tftp_server;
|
||||
tftp_server.ensure_initialized().await?;
|
||||
tftp_server.set_ip(topology.router.get_gateway()).await?;
|
||||
tftp_server.serve_files(&self.score.files_to_serve).await?;
|
||||
tftp_server.commit_config().await?;
|
||||
tftp_server.reload_restart().await?;
|
||||
topology.ensure_initialized().await?;
|
||||
topology.set_ip(topology.get_gateway()).await?;
|
||||
topology.serve_files(&self.score.files_to_serve).await?;
|
||||
topology.commit_config().await?;
|
||||
topology.reload_restart().await?;
|
||||
Ok(Outcome::success(format!(
|
||||
"TFTP Server running and serving files from {}",
|
||||
self.score.files_to_serve
|
||||
|
||||
Loading…
Reference in New Issue
Block a user