fix: Haproxy now has SSL:Other(String) to store unknown values from opnsense, also ran a cargo fmt
Some checks failed
Run Check Script / check (pull_request) Failing after 58s

This commit is contained in:
Jean-Gabriel Gill-Couture 2025-09-04 23:47:09 -04:00
parent ecc461a33f
commit 1304a3a1d1
10 changed files with 61 additions and 31 deletions

View File

@ -5,7 +5,12 @@ use std::{
use cidr::Ipv4Cidr; use cidr::Ipv4Cidr;
use harmony::{ 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, http::StaticFilesHttpScore,
okd::{ okd::{
bootstrap_dhcp::OKDBootstrapDhcpScore, bootstrap_dhcp::OKDBootstrapDhcpScore,
@ -13,7 +18,8 @@ use harmony::{
dns::OKDDnsScore, ipxe::OKDIpxeScore, dns::OKDDnsScore, ipxe::OKDIpxeScore,
}, },
tftp::TftpScore, tftp::TftpScore,
}, topology::{LogicalHost, UnmanagedRouter} },
topology::{LogicalHost, UnmanagedRouter},
}; };
use harmony_macros::{ip, mac_address}; use harmony_macros::{ip, mac_address};
use harmony_secret::SecretManager; use harmony_secret::SecretManager;

View File

@ -8,7 +8,8 @@ use harmony::{
load_balancer::LoadBalancerScore, load_balancer::LoadBalancerScore,
}, },
topology::{ topology::{
BackendServer, DummyInfra, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancerService, SSL, BackendServer, DummyInfra, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancerService,
SSL,
}, },
}; };
use harmony_macros::ipv4; use harmony_macros::ipv4;

View File

@ -102,13 +102,13 @@ pub enum HttpStatusCode {
ServerError5xx, ServerError5xx,
} }
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]
pub enum SSL { pub enum SSL {
SSL, SSL,
Disabled, Disabled,
Default, Default,
SNI, SNI,
Other(String),
} }
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]

View File

@ -1,13 +1,15 @@
use async_trait::async_trait; use async_trait::async_trait;
use log::{debug, info, warn}; use log::{debug, error, info, warn};
use opnsense_config_xml::{Frontend, HAProxy, HAProxyBackend, HAProxyHealthCheck, HAProxyServer, MaybeString}; use opnsense_config_xml::{
Frontend, HAProxy, HAProxyBackend, HAProxyHealthCheck, HAProxyServer, MaybeString,
};
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
executors::ExecutorError, executors::ExecutorError,
topology::{ topology::{
BackendServer, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService, BackendServer, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, LoadBalancerService,
LogicalHost, LogicalHost, SSL,
}, },
}; };
use harmony_types::net::IpAddress; use harmony_types::net::IpAddress;
@ -206,7 +208,22 @@ pub(crate) fn get_health_check_for_backend(
.unwrap_or_default() .unwrap_or_default()
.into(); .into();
let status_code: HttpStatusCode = HttpStatusCode::Success2xx; 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), _ => panic!("Received unsupported health check type {}", uppercase),
} }
@ -243,10 +260,11 @@ pub(crate) fn harmony_load_balancer_service_to_haproxy_xml(
match health_check { match health_check {
HealthCheck::HTTP(path, http_method, _http_status_code, ssl) => { HealthCheck::HTTP(path, http_method, _http_status_code, ssl) => {
let ssl: MaybeString = match ssl { let ssl: MaybeString = match ssl {
crate::topology::SSL::SSL => "ssl".into(), SSL::SSL => "ssl".into(),
crate::topology::SSL::SNI => "sslni".into(), SSL::SNI => "sslni".into(),
crate::topology::SSL::Disabled => "nossl".into(), SSL::Disabled => "nossl".into(),
crate::topology::SSL::Default => "".into(), SSL::Default => "".into(),
SSL::Other(other) => other.as_str().into(),
}; };
let haproxy_check = HAProxyHealthCheck { let haproxy_check = HAProxyHealthCheck {
name: format!("HTTP_{http_method}_{path}"), name: format!("HTTP_{http_method}_{path}"),

View File

@ -371,7 +371,7 @@ impl Interpret<HAClusterTopology> for OKDSetup02BootstrapInterpret {
self.prepare_ignition_files(inventory, topology).await?; self.prepare_ignition_files(inventory, topology).await?;
self.render_per_mac_pxe(inventory, topology).await?; self.render_per_mac_pxe(inventory, topology).await?;
self.setup_bootstrap_load_balancer(inventory, topology) 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 // 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?; // self.validate_dns_config(inventory, topology).await?;

View File

@ -7,19 +7,17 @@ use log::{debug, info};
use serde::Serialize; use serde::Serialize;
use crate::{ use crate::{
data::Version,
hardware::PhysicalHost, hardware::PhysicalHost,
infra::inventory::InventoryRepositoryFactory, infra::inventory::InventoryRepositoryFactory,
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
inventory::{HostRole, Inventory}, inventory::{HostRole, Inventory},
modules::{ modules::{
dhcp::DhcpHostBindingScore, dhcp::DhcpHostBindingScore, http::IPxeMacBootFileScore,
http::IPxeMacBootFileScore, inventory::DiscoverHostForRoleScore, okd::templates::BootstrapIpxeTpl,
inventory::DiscoverHostForRoleScore,
okd::templates::BootstrapIpxeTpl,
}, },
score::Score, score::Score,
topology::{HAClusterTopology, HostBinding}, topology::{HAClusterTopology, HostBinding},
data::Version,
}; };
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
// Step 03: Control Plane // Step 03: Control Plane
@ -91,7 +89,10 @@ impl OKDSetup03ControlPlaneInterpret {
))) )))
} else { } else {
// Take exactly the number of required hosts to ensure consistency. // 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)| { .map(|(logical_host, physical_host)| {
info!( info!(
"Creating binding: Logical Host '{}' -> Physical Host ID '{}'", "Creating binding: Logical Host '{}' -> Physical Host ID '{}'",
logical_host.name, logical_host.name, physical_host.id
physical_host.id
); );
HostBinding { HostBinding {
logical_host: logical_host.clone(), logical_host: logical_host.clone(),
@ -191,7 +191,10 @@ impl OKDSetup03ControlPlaneInterpret {
/// Prompts the user to reboot the target control plane nodes. /// Prompts the user to reboot the target control plane nodes.
async fn reboot_targets(&self, nodes: &Vec<PhysicalHost>) -> Result<(), InterpretError> { async fn reboot_targets(&self, nodes: &Vec<PhysicalHost>) -> Result<(), InterpretError> {
let node_ids: Vec<String> = nodes.iter().map(|n| n.id.to_string()).collect(); let node_ids: Vec<String> = 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( 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(", ")), &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)))?; .map_err(|e| InterpretError::new(format!("User prompt failed: {}", e)))?;
if !confirmation { if !confirmation {
return Err(InterpretError::new("User aborted the operation.".to_string())); return Err(InterpretError::new(
"User aborted the operation.".to_string(),
));
} }
Ok(()) Ok(())
@ -247,7 +252,8 @@ impl Interpret<HAClusterTopology> for OKDSetup03ControlPlaneInterpret {
let nodes = self.get_nodes(inventory, topology).await?; let nodes = self.get_nodes(inventory, topology).await?;
// 2. Create DHCP reservations for the control plane nodes. // 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. // 3. Create iPXE files for each control plane node to boot from the master ignition.
self.configure_ipxe(inventory, topology, &nodes).await?; self.configure_ipxe(inventory, topology, &nodes).await?;

View File

@ -1,11 +1,11 @@
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
use std::{fmt::Write, path::PathBuf};
use async_trait::async_trait; use async_trait::async_trait;
use derive_new::new; use derive_new::new;
use harmony_secret::SecretManager; use harmony_secret::SecretManager;
use harmony_types::id::Id; use harmony_types::id::Id;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fmt::Write, path::PathBuf};
use tokio::{fs::File, io::AsyncWriteExt, process::Command}; use tokio::{fs::File, io::AsyncWriteExt, process::Command};
use crate::{ use crate::{

View File

@ -8,7 +8,7 @@ use crate::{
score::Score, score::Score,
topology::{ topology::{
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer,
LoadBalancerService, Topology, SSL, LoadBalancerService, SSL, Topology,
}, },
}; };
@ -44,7 +44,7 @@ impl OKDBootstrapLoadBalancerScore {
"/readyz".to_string(), "/readyz".to_string(),
HttpMethod::GET, HttpMethod::GET,
HttpStatusCode::Success2xx, HttpStatusCode::Success2xx,
SSL::SSL SSL::SSL,
)), )),
}, },
]; ];

View File

@ -8,7 +8,7 @@ use crate::{
score::Score, score::Score,
topology::{ topology::{
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer, BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode, LoadBalancer,
LoadBalancerService, Topology, SSL, LoadBalancerService, SSL, Topology,
}, },
}; };

View File

@ -51,7 +51,6 @@ pub struct OPNsense {
impl From<String> for OPNsense { impl From<String> for OPNsense {
fn from(content: String) -> Self { fn from(content: String) -> Self {
yaserde::de::from_str(&content) yaserde::de::from_str(&content)
.map_err(|e| println!("{}", e)) .map_err(|e| println!("{}", e))
.expect("OPNSense received invalid string, should be full XML") .expect("OPNSense received invalid string, should be full XML")