Merge pull request 'feat: introduce Maestro::initialize function that creates the maestro instance and ensure_ready the topology as well. Also refactor all relevant examples to use this new initialize function' (#18) from feat/maestroinitialize into master
Reviewed-on: https://git.nationtech.io/NationTech/harmony/pulls/18 Reviewed-by: taha <taha@noreply.git.nationtech.io>
This commit is contained in:
commit
00c0566533
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -961,6 +961,7 @@ dependencies = [
|
|||||||
"harmony",
|
"harmony",
|
||||||
"harmony_macros",
|
"harmony_macros",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
|
"inquire",
|
||||||
"k8s-openapi",
|
"k8s-openapi",
|
||||||
"kube",
|
"kube",
|
||||||
"log",
|
"log",
|
||||||
|
5
check.sh
Normal file
5
check.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
cargo check --all-targets --all-features --keep-going
|
||||||
|
cargo fmt --check
|
||||||
|
cargo test
|
@ -2,14 +2,14 @@ use harmony::{
|
|||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
maestro::Maestro,
|
maestro::Maestro,
|
||||||
modules::dummy::{ErrorScore, PanicScore, SuccessScore},
|
modules::dummy::{ErrorScore, PanicScore, SuccessScore},
|
||||||
topology::HAClusterTopology,
|
topology::LocalhostTopology,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let inventory = Inventory::autoload();
|
let inventory = Inventory::autoload();
|
||||||
let topology = HAClusterTopology::autoload();
|
let topology = LocalhostTopology::new();
|
||||||
let mut maestro = Maestro::new(inventory, topology);
|
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
||||||
|
|
||||||
maestro.register_all(vec![
|
maestro.register_all(vec![
|
||||||
Box::new(SuccessScore {}),
|
Box::new(SuccessScore {}),
|
||||||
|
@ -18,3 +18,4 @@ kube = "0.98.0"
|
|||||||
k8s-openapi = { version = "0.24.0", features = [ "v1_30" ] }
|
k8s-openapi = { version = "0.24.0", features = [ "v1_30" ] }
|
||||||
http = "1.2.0"
|
http = "1.2.0"
|
||||||
serde_yaml = "0.9.34"
|
serde_yaml = "0.9.34"
|
||||||
|
inquire.workspace = true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use harmony_macros::yaml;
|
use harmony_macros::yaml;
|
||||||
|
use inquire::Confirm;
|
||||||
use k8s_openapi::{
|
use k8s_openapi::{
|
||||||
api::{
|
api::{
|
||||||
apps::v1::{Deployment, DeploymentSpec},
|
apps::v1::{Deployment, DeploymentSpec},
|
||||||
@ -15,6 +16,17 @@ use kube::{
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
let confirmation = Confirm::new(
|
||||||
|
"This will install various ressources to your default kubernetes cluster. Are you sure?",
|
||||||
|
)
|
||||||
|
.with_default(false)
|
||||||
|
.prompt()
|
||||||
|
.expect("Unexpected prompt error");
|
||||||
|
|
||||||
|
if !confirmation {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let client = Client::try_default()
|
let client = Client::try_default()
|
||||||
.await
|
.await
|
||||||
.expect("Should instanciate client from defaults");
|
.expect("Should instanciate client from defaults");
|
||||||
|
@ -9,7 +9,7 @@ use harmony::{
|
|||||||
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::initialize(inventory, topology).await.unwrap();
|
||||||
|
|
||||||
maestro.register_all(vec![
|
maestro.register_all(vec![
|
||||||
// ADD scores :
|
// ADD scores :
|
||||||
|
@ -84,7 +84,7 @@ async fn main() {
|
|||||||
let http_score = HttpScore::new(Url::LocalFolder(
|
let http_score = HttpScore::new(Url::LocalFolder(
|
||||||
"./data/watchguard/pxe-http-files".to_string(),
|
"./data/watchguard/pxe-http-files".to_string(),
|
||||||
));
|
));
|
||||||
let mut maestro = Maestro::new(inventory, topology);
|
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
||||||
maestro.register_all(vec![
|
maestro.register_all(vec![
|
||||||
Box::new(dns_score),
|
Box::new(dns_score),
|
||||||
Box::new(dhcp_score),
|
Box::new(dhcp_score),
|
||||||
|
@ -9,8 +9,7 @@ use harmony::{
|
|||||||
load_balancer::LoadBalancerScore,
|
load_balancer::LoadBalancerScore,
|
||||||
},
|
},
|
||||||
topology::{
|
topology::{
|
||||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode,
|
BackendServer, DummyInfra, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancerService,
|
||||||
LoadBalancerService,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use harmony_macros::ipv4;
|
use harmony_macros::ipv4;
|
||||||
@ -18,8 +17,8 @@ use harmony_macros::ipv4;
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let inventory = Inventory::autoload();
|
let inventory = Inventory::autoload();
|
||||||
let topology = HAClusterTopology::autoload();
|
let topology = DummyInfra {};
|
||||||
let mut maestro = Maestro::new(inventory, topology);
|
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
||||||
|
|
||||||
maestro.register_all(vec![
|
maestro.register_all(vec![
|
||||||
Box::new(SuccessScore {}),
|
Box::new(SuccessScore {}),
|
||||||
|
@ -28,6 +28,12 @@ impl<T: Topology> Maestro<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn initialize(inventory: Inventory, topology: T) -> Result<Self, InterpretError> {
|
||||||
|
let instance = Self::new(inventory, topology);
|
||||||
|
instance.prepare_topology().await?;
|
||||||
|
Ok(instance)
|
||||||
|
}
|
||||||
|
|
||||||
/// Ensures the associated Topology is ready for operations.
|
/// Ensures the associated Topology is ready for operations.
|
||||||
/// Delegates the readiness check and potential setup actions to the Topology.
|
/// Delegates the readiness check and potential setup actions to the Topology.
|
||||||
pub async fn prepare_topology(&self) -> Result<Outcome, InterpretError> {
|
pub async fn prepare_topology(&self) -> Result<Outcome, InterpretError> {
|
||||||
|
@ -218,7 +218,7 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::modules::dns::DnsScore;
|
use crate::modules::dns::DnsScore;
|
||||||
use crate::topology::{self, HAClusterTopology};
|
use crate::topology::HAClusterTopology;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_values_as_string() {
|
fn test_format_values_as_string() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use harmony_macros::ip;
|
use harmony_macros::ip;
|
||||||
use harmony_types::net::MacAddress;
|
use harmony_types::net::MacAddress;
|
||||||
|
use log::info;
|
||||||
|
|
||||||
use crate::executors::ExecutorError;
|
use crate::executors::ExecutorError;
|
||||||
use crate::interpret::InterpretError;
|
use crate::interpret::InterpretError;
|
||||||
@ -223,7 +224,20 @@ impl HttpServer for HAClusterTopology {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DummyInfra;
|
pub struct DummyInfra;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Topology for DummyInfra {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ensure_ready(&self) -> Result<Outcome, InterpretError> {
|
||||||
|
let dummy_msg = "This is a dummy infrastructure that does nothing";
|
||||||
|
info!("{dummy_msg}");
|
||||||
|
Ok(Outcome::success(dummy_msg.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const UNIMPLEMENTED_DUMMY_INFRA: &str = "This is a dummy infrastructure, no operation is supported";
|
const UNIMPLEMENTED_DUMMY_INFRA: &str = "This is a dummy infrastructure, no operation is supported";
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ impl K8sAnywhereTopology {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn try_install_k3d(&self) -> Result<K8sClient, InterpretError> {
|
async fn try_install_k3d(&self) -> Result<K8sClient, InterpretError> {
|
||||||
let maestro = Maestro::new(Inventory::autoload(), LocalhostTopology::new());
|
let maestro = Maestro::initialize(Inventory::autoload(), LocalhostTopology::new()).await?;
|
||||||
let k3d_score = K3DInstallationScore::new();
|
let k3d_score = K3DInstallationScore::new();
|
||||||
maestro.interpret(Box::new(k3d_score)).await?;
|
maestro.interpret(Box::new(k3d_score)).await?;
|
||||||
todo!(
|
todo!(
|
||||||
@ -151,22 +151,20 @@ impl Topology for K8sAnywhereTopology {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn ensure_ready(&self) -> Result<Outcome, InterpretError> {
|
async fn ensure_ready(&self) -> Result<Outcome, InterpretError> {
|
||||||
let k8s_state = self
|
let k8s_state = self
|
||||||
.k8s_state
|
.k8s_state
|
||||||
.get_or_try_init(|| self.try_get_or_install_k8s_client())
|
.get_or_try_init(|| self.try_get_or_install_k8s_client())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let k8s_state: &K8sState = k8s_state
|
let k8s_state: &K8sState = k8s_state.as_ref().ok_or(InterpretError::new(
|
||||||
.as_ref()
|
"No K8s client could be found or installed".to_string(),
|
||||||
.ok_or(InterpretError::new(
|
))?;
|
||||||
"No K8s client could be found or installed".to_string(),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
match self.is_helm_available() {
|
match self.is_helm_available() {
|
||||||
Ok(()) => Ok(Outcome::success(format!(
|
Ok(()) => Ok(Outcome::success(format!(
|
||||||
"{} + helm available",
|
"{} + helm available",
|
||||||
k8s_state.message.clone()
|
k8s_state.message.clone()
|
||||||
))),
|
))),
|
||||||
Err(_) => Err(InterpretError::new("helm unavailable".to_string())),
|
Err(_) => Err(InterpretError::new("helm unavailable".to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,13 +370,10 @@ mod tests {
|
|||||||
let result = get_servers_for_backend(&backend, &haproxy);
|
let result = get_servers_for_backend(&backend, &haproxy);
|
||||||
|
|
||||||
// Check the result
|
// Check the result
|
||||||
assert_eq!(
|
assert_eq!(result, vec![BackendServer {
|
||||||
result,
|
address: "192.168.1.1".to_string(),
|
||||||
vec![BackendServer {
|
port: 80,
|
||||||
address: "192.168.1.1".to_string(),
|
},]);
|
||||||
port: 80,
|
|
||||||
},]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_servers_for_backend_no_linked_servers() {
|
fn test_get_servers_for_backend_no_linked_servers() {
|
||||||
@ -433,18 +430,15 @@ mod tests {
|
|||||||
// Call the function
|
// Call the function
|
||||||
let result = get_servers_for_backend(&backend, &haproxy);
|
let result = get_servers_for_backend(&backend, &haproxy);
|
||||||
// Check the result
|
// Check the result
|
||||||
assert_eq!(
|
assert_eq!(result, vec![
|
||||||
result,
|
BackendServer {
|
||||||
vec![
|
address: "some-hostname.test.mcd".to_string(),
|
||||||
BackendServer {
|
port: 80,
|
||||||
address: "some-hostname.test.mcd".to_string(),
|
},
|
||||||
port: 80,
|
BackendServer {
|
||||||
},
|
address: "192.168.1.2".to_string(),
|
||||||
BackendServer {
|
port: 8080,
|
||||||
address: "192.168.1.2".to_string(),
|
},
|
||||||
port: 8080,
|
]);
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,6 @@ mod test {
|
|||||||
modules::dummy::{ErrorScore, PanicScore, SuccessScore},
|
modules::dummy::{ErrorScore, PanicScore, SuccessScore},
|
||||||
topology::HAClusterTopology,
|
topology::HAClusterTopology,
|
||||||
};
|
};
|
||||||
use harmony::{score::Score, topology::Topology};
|
|
||||||
|
|
||||||
fn init_test_maestro() -> Maestro<HAClusterTopology> {
|
fn init_test_maestro() -> Maestro<HAClusterTopology> {
|
||||||
let inventory = Inventory::autoload();
|
let inventory = Inventory::autoload();
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "example"
|
name = "example"
|
||||||
|
edition = "2024"
|
||||||
|
Loading…
Reference in New Issue
Block a user