From 1304a3a1d1baa12a8f94b8a50545b0ab1be099b4 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Thu, 4 Sep 2025 23:47:09 -0400 Subject: [PATCH] fix: Haproxy now has SSL:Other(String) to store unknown values from opnsense, also ran a cargo fmt --- examples/nanodc/src/main.rs | 10 ++++-- examples/tui/src/main.rs | 3 +- harmony/src/domain/topology/load_balancer.rs | 2 +- harmony/src/infra/opnsense/load_balancer.rs | 34 ++++++++++++++----- .../src/modules/okd/bootstrap_02_bootstrap.rs | 2 +- .../modules/okd/bootstrap_03_control_plane.rs | 32 ++++++++++------- .../okd/bootstrap_06_installation_report.rs | 2 +- .../modules/okd/bootstrap_load_balancer.rs | 4 +-- harmony/src/modules/okd/load_balancer.rs | 2 +- opnsense-config-xml/src/data/opnsense.rs | 1 - 10 files changed, 61 insertions(+), 31 deletions(-) diff --git a/examples/nanodc/src/main.rs b/examples/nanodc/src/main.rs index c89de73..57574d2 100644 --- a/examples/nanodc/src/main.rs +++ b/examples/nanodc/src/main.rs @@ -5,7 +5,12 @@ use std::{ use cidr::Ipv4Cidr; use harmony::{ - config::secret::SshKeyPair, data::{FileContent, FilePath}, hardware::{HostCategory, Location, PhysicalHost, SwitchGroup}, infra::opnsense::OPNSenseManagementInterface, inventory::Inventory, modules::{ + config::secret::SshKeyPair, + data::{FileContent, FilePath}, + hardware::{HostCategory, Location, PhysicalHost, SwitchGroup}, + infra::opnsense::OPNSenseManagementInterface, + inventory::Inventory, + modules::{ http::StaticFilesHttpScore, okd::{ bootstrap_dhcp::OKDBootstrapDhcpScore, @@ -13,7 +18,8 @@ use harmony::{ dns::OKDDnsScore, ipxe::OKDIpxeScore, }, tftp::TftpScore, - }, topology::{LogicalHost, UnmanagedRouter} + }, + topology::{LogicalHost, UnmanagedRouter}, }; use harmony_macros::{ip, mac_address}; use harmony_secret::SecretManager; diff --git a/examples/tui/src/main.rs b/examples/tui/src/main.rs index b2c3cf5..d9c85a6 100644 --- a/examples/tui/src/main.rs +++ b/examples/tui/src/main.rs @@ -8,7 +8,8 @@ use harmony::{ load_balancer::LoadBalancerScore, }, topology::{ - BackendServer, DummyInfra, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancerService, SSL, + BackendServer, DummyInfra, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancerService, + SSL, }, }; use harmony_macros::ipv4; diff --git a/harmony/src/domain/topology/load_balancer.rs b/harmony/src/domain/topology/load_balancer.rs index 45c070e..901602b 100644 --- a/harmony/src/domain/topology/load_balancer.rs +++ b/harmony/src/domain/topology/load_balancer.rs @@ -102,13 +102,13 @@ pub enum HttpStatusCode { ServerError5xx, } - #[derive(Debug, Clone, PartialEq, Serialize)] pub enum SSL { SSL, Disabled, Default, SNI, + Other(String), } #[derive(Debug, Clone, PartialEq, Serialize)] diff --git a/harmony/src/infra/opnsense/load_balancer.rs b/harmony/src/infra/opnsense/load_balancer.rs index 667df08..ce47f05 100644 --- a/harmony/src/infra/opnsense/load_balancer.rs +++ b/harmony/src/infra/opnsense/load_balancer.rs @@ -1,13 +1,15 @@ use async_trait::async_trait; -use log::{debug, info, warn}; -use opnsense_config_xml::{Frontend, HAProxy, HAProxyBackend, HAProxyHealthCheck, HAProxyServer, MaybeString}; +use log::{debug, error, info, warn}; +use opnsense_config_xml::{ + Frontend, HAProxy, HAProxyBackend, HAProxyHealthCheck, HAProxyServer, MaybeString, +}; use uuid::Uuid; use crate::{ executors::ExecutorError, topology::{ BackendServer, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, - LogicalHost, + LogicalHost, SSL, }, }; use harmony_types::net::IpAddress; @@ -206,7 +208,22 @@ pub(crate) fn get_health_check_for_backend( .unwrap_or_default() .into(); let status_code: HttpStatusCode = HttpStatusCode::Success2xx; - Some(HealthCheck::HTTP(path, method, status_code)) + let ssl = match haproxy_health_check + .ssl + .content_string() + .to_uppercase() + .as_str() + { + "SSL" => SSL::SSL, + "SSLNI" => SSL::SNI, + "NOSSL" => SSL::Disabled, + "" => SSL::Default, + other => { + error!("Unknown haproxy health check ssl config {other}"); + SSL::Other(other.to_string()) + } + }; + Some(HealthCheck::HTTP(path, method, status_code, ssl)) } _ => panic!("Received unsupported health check type {}", uppercase), } @@ -243,10 +260,11 @@ pub(crate) fn harmony_load_balancer_service_to_haproxy_xml( match health_check { HealthCheck::HTTP(path, http_method, _http_status_code, ssl) => { let ssl: MaybeString = match ssl { - crate::topology::SSL::SSL => "ssl".into(), - crate::topology::SSL::SNI => "sslni".into(), - crate::topology::SSL::Disabled => "nossl".into(), - crate::topology::SSL::Default => "".into(), + SSL::SSL => "ssl".into(), + SSL::SNI => "sslni".into(), + SSL::Disabled => "nossl".into(), + SSL::Default => "".into(), + SSL::Other(other) => other.as_str().into(), }; let haproxy_check = HAProxyHealthCheck { name: format!("HTTP_{http_method}_{path}"), diff --git a/harmony/src/modules/okd/bootstrap_02_bootstrap.rs b/harmony/src/modules/okd/bootstrap_02_bootstrap.rs index c08179a..5b940fb 100644 --- a/harmony/src/modules/okd/bootstrap_02_bootstrap.rs +++ b/harmony/src/modules/okd/bootstrap_02_bootstrap.rs @@ -371,7 +371,7 @@ impl Interpret for OKDSetup02BootstrapInterpret { self.prepare_ignition_files(inventory, topology).await?; self.render_per_mac_pxe(inventory, topology).await?; self.setup_bootstrap_load_balancer(inventory, topology) - .await?; + .await?; // TODO https://docs.okd.io/latest/installing/installing_bare_metal/upi/installing-bare-metal.html#installation-user-provisioned-validating-dns_installing-bare-metal // self.validate_dns_config(inventory, topology).await?; diff --git a/harmony/src/modules/okd/bootstrap_03_control_plane.rs b/harmony/src/modules/okd/bootstrap_03_control_plane.rs index 0ee7f2e..a387e1e 100644 --- a/harmony/src/modules/okd/bootstrap_03_control_plane.rs +++ b/harmony/src/modules/okd/bootstrap_03_control_plane.rs @@ -7,19 +7,17 @@ use log::{debug, info}; use serde::Serialize; use crate::{ + data::Version, hardware::PhysicalHost, infra::inventory::InventoryRepositoryFactory, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::{HostRole, Inventory}, modules::{ - dhcp::DhcpHostBindingScore, - http::IPxeMacBootFileScore, - inventory::DiscoverHostForRoleScore, - okd::templates::BootstrapIpxeTpl, + dhcp::DhcpHostBindingScore, http::IPxeMacBootFileScore, + inventory::DiscoverHostForRoleScore, okd::templates::BootstrapIpxeTpl, }, score::Score, topology::{HAClusterTopology, HostBinding}, - data::Version, }; // ------------------------------------------------------------------------------------------------- // Step 03: Control Plane @@ -91,7 +89,10 @@ impl OKDSetup03ControlPlaneInterpret { ))) } else { // Take exactly the number of required hosts to ensure consistency. - Ok(control_plane_hosts.into_iter().take(REQUIRED_HOSTS).collect()) + Ok(control_plane_hosts + .into_iter() + .take(REQUIRED_HOSTS) + .collect()) } } @@ -121,8 +122,7 @@ impl OKDSetup03ControlPlaneInterpret { .map(|(logical_host, physical_host)| { info!( "Creating binding: Logical Host '{}' -> Physical Host ID '{}'", - logical_host.name, - physical_host.id + logical_host.name, physical_host.id ); HostBinding { logical_host: logical_host.clone(), @@ -187,12 +187,15 @@ impl OKDSetup03ControlPlaneInterpret { Ok(()) } - + /// Prompts the user to reboot the target control plane nodes. async fn reboot_targets(&self, nodes: &Vec) -> Result<(), InterpretError> { let node_ids: Vec = nodes.iter().map(|n| n.id.to_string()).collect(); - info!("[ControlPlane] Requesting reboot for control plane nodes: {:?}", node_ids); - + info!( + "[ControlPlane] Requesting reboot for control plane nodes: {:?}", + node_ids + ); + let confirmation = inquire::Confirm::new( &format!("Please reboot the {} control plane nodes ({}) to apply their PXE configuration. Press enter when ready.", nodes.len(), node_ids.join(", ")), ) @@ -200,7 +203,9 @@ impl OKDSetup03ControlPlaneInterpret { .map_err(|e| InterpretError::new(format!("User prompt failed: {}", e)))?; if !confirmation { - return Err(InterpretError::new("User aborted the operation.".to_string())); + return Err(InterpretError::new( + "User aborted the operation.".to_string(), + )); } Ok(()) @@ -247,7 +252,8 @@ impl Interpret for OKDSetup03ControlPlaneInterpret { let nodes = self.get_nodes(inventory, topology).await?; // 2. Create DHCP reservations for the control plane nodes. - self.configure_host_binding(inventory, topology, &nodes).await?; + self.configure_host_binding(inventory, topology, &nodes) + .await?; // 3. Create iPXE files for each control plane node to boot from the master ignition. self.configure_ipxe(inventory, topology, &nodes).await?; diff --git a/harmony/src/modules/okd/bootstrap_06_installation_report.rs b/harmony/src/modules/okd/bootstrap_06_installation_report.rs index 792d567..2713bd2 100644 --- a/harmony/src/modules/okd/bootstrap_06_installation_report.rs +++ b/harmony/src/modules/okd/bootstrap_06_installation_report.rs @@ -1,11 +1,11 @@ // ------------------------------------------------------------------------------------------------- -use std::{fmt::Write, path::PathBuf}; use async_trait::async_trait; use derive_new::new; use harmony_secret::SecretManager; use harmony_types::id::Id; use log::{debug, error, info, warn}; use serde::{Deserialize, Serialize}; +use std::{fmt::Write, path::PathBuf}; use tokio::{fs::File, io::AsyncWriteExt, process::Command}; use crate::{ diff --git a/harmony/src/modules/okd/bootstrap_load_balancer.rs b/harmony/src/modules/okd/bootstrap_load_balancer.rs index bdb40d4..ccc69c9 100644 --- a/harmony/src/modules/okd/bootstrap_load_balancer.rs +++ b/harmony/src/modules/okd/bootstrap_load_balancer.rs @@ -8,7 +8,7 @@ use crate::{ score::Score, topology::{ BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, - LoadBalancerService, Topology, SSL, + LoadBalancerService, SSL, Topology, }, }; @@ -44,7 +44,7 @@ impl OKDBootstrapLoadBalancerScore { "/readyz".to_string(), HttpMethod::GET, HttpStatusCode::Success2xx, - SSL::SSL + SSL::SSL, )), }, ]; diff --git a/harmony/src/modules/okd/load_balancer.rs b/harmony/src/modules/okd/load_balancer.rs index 93c05c1..8a2b57f 100644 --- a/harmony/src/modules/okd/load_balancer.rs +++ b/harmony/src/modules/okd/load_balancer.rs @@ -8,7 +8,7 @@ use crate::{ score::Score, topology::{ BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, - LoadBalancerService, Topology, SSL, + LoadBalancerService, SSL, Topology, }, }; diff --git a/opnsense-config-xml/src/data/opnsense.rs b/opnsense-config-xml/src/data/opnsense.rs index dc0fded..fa5f985 100644 --- a/opnsense-config-xml/src/data/opnsense.rs +++ b/opnsense-config-xml/src/data/opnsense.rs @@ -51,7 +51,6 @@ pub struct OPNsense { impl From for OPNsense { fn from(content: String) -> Self { - yaserde::de::from_str(&content) .map_err(|e| println!("{}", e)) .expect("OPNSense received invalid string, should be full XML")