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 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;

View File

@ -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;

View File

@ -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)]

View File

@ -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}"),

View File

@ -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(),
@ -191,7 +191,10 @@ impl OKDSetup03ControlPlaneInterpret {
/// Prompts the user to reboot the target control plane nodes.
async fn reboot_targets(&self, nodes: &Vec<PhysicalHost>) -> Result<(), InterpretError> {
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(
&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<HAClusterTopology> 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?;

View File

@ -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::{

View File

@ -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,
)),
},
];

View File

@ -8,7 +8,7 @@ use crate::{
score::Score,
topology::{
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 {
fn from(content: String) -> Self {
yaserde::de::from_str(&content)
.map_err(|e| println!("{}", e))
.expect("OPNSense received invalid string, should be full XML")