Files
harmony/opnsense-config
Jean-Gabriel Gill-Couture c926ff3c4b chore: warning sweep — manual cleanup of remaining 105 → 0
Picks up where the auto-fix pass left off. Workspace warning count
goes from 105 to 0 across `cargo build --workspace --all-targets`.

Three categories of fixes:

1. Mechanical fixes the auto-pass couldn't handle (unused imports
   inside braced multi-name `use` statements, unused variables that
   needed an underscore prefix without breaking other references):
   batched via a small Python script, then 6 manual edits where the
   warning location and the actual identifier were on different
   lines.

2. Dead-code that's intentionally kept around for future wiring or
   debug visibility — `#[allow(dead_code)]` at the right scope:
   - 19 individual items (struct fields, methods, free functions,
     type aliases, enum variants), e.g. `default_namespace` / `default_cluster_issuer`
     in zitadel/mod.rs (used via serde defaults, opaque to rustc),
     `score` fields on the OKD bootstrap interpret types,
     `crd_exists` methods on the prometheus alerting scores, the
     `harmony_inventory_agent::local_presence::{DiscoveryEvent,
     discover_agents}` re-exports.
   - 5 module-level allows for files where most items are
     aspirational scaffolding (harmony_agent's replica workflow,
     opnsense-config dnsmasq, three opnsense-api examples).

3. Special cases that needed real fixes, not allows:
   - `opnsense-config-xml/src/data/haproxy.rs`: deprecated
     `rand::thread_rng` / `Rng::gen` updated to `rng()` / `random`.
   - `harmony_secret/src/lib.rs`: the `secrete2etest` integration
     test gate is now declared in Cargo.toml's `[lints.rust]
     unexpected_cfgs.check-cfg`; the gated test module is structured
     so its dead `TestSecret`/`TestUserMeta` types come along for
     the cfg ride and don't show up as unconditional dead code.
   - `harmony/src/modules/nats/score_nats_k8s.rs:241`: `K8sIngressScore
     { name: todo!(), ... }`'s unreachable expression annotated.
   - `harmony/src/domain/topology/k8s_anywhere/k8s_anywhere.rs:982`:
     wrap the dead-after-`return Ok(Noop)` branch in
     `#[allow(unreachable_code)] { ... }`. Behavior unchanged.
   - `examples/try_rust_webapp/Cargo.toml`: `autobins = false` so
     `src/main.rs` isn't auto-registered as both bin AND example.

All 16 lib-test suites pass: 437 tests, 0 failed, 13 ignored.

Ready for `-Dwarnings` in CI as a follow-up — the gate makes
sense once we're sure no contributor's local builds slip warnings
back in.
2026-05-06 23:09:12 -04:00
..

Supporting a new field in OPNSense config.xml

Two steps:

  • Supporting the field in opnsense-config-xml
  • Enabling Harmony to control the field

We'll use the filename field in the dhcpcd section of the file as an example.

Supporting the field

As type checking if enforced, every field from config.xml must be known by the code. Each subsection of config.xml has its .rs file. For the dhcpcd section, we'll modify opnsense-config-xml/src/data/dhcpd.rs.

When a new field appears in the xml file, an error like this will be thrown and Harmony will panic :

     Running `/home/stremblay/nt/dir/harmony/target/debug/example-nanodc`
Found unauthorized element filename
thread 'main' panicked at opnsense-config-xml/src/data/opnsense.rs:54:14:
OPNSense received invalid string, should be full XML: ()

Define the missing field (filename) in the DhcpInterface struct of opnsense-config-xml/src/data/dhcpd.rs:

pub struct DhcpInterface {
    ...
    pub filename: Option<String>,

Harmony should now be fixed, build and run.

Controlling the field

Define the xml field setter in opnsense-config/src/modules/dhcpd.rs.

impl<'a> DhcpConfig<'a> {
    ...
    pub fn set_filename(&mut self, filename: &str) {
        self.enable_netboot();
        self.get_lan_dhcpd().filename = Some(filename.to_string());
    }
    ...

Define the value setter in the DhcpServer trait in domain/topology/network.rs

#[async_trait]
pub trait DhcpServer: Send + Sync {
    ...
    async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError>;
    ...

Implement the value setter in each DhcpServer implementation. infra/opnsense/dhcp.rs:

#[async_trait]
impl DhcpServer for OPNSenseFirewall {
    ...
    async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
        {
            let mut writable_opnsense = self.opnsense_config.write().await;
            writable_opnsense.dhcp().set_filename(filename);
            debug!("OPNsense dhcp server set filename {filename}");
        }

        Ok(())
    }
    ...

domain/topology/ha_cluster.rs

#[async_trait]
impl DhcpServer for DummyInfra {
    ...
    async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> {
        unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
    }
    ...

Add the new field to the DhcpScore in modules/dhcp.rs

pub struct DhcpScore {
    ...
    pub filename: Option<String>,

Define it in its implementation in modules/okd/dhcp.rs

impl OKDDhcpScore {
        ...
        Self {
            dhcp_score: DhcpScore {
                ...
                filename: Some("undionly.kpxe".to_string()),

Define it in its implementation in modules/okd/bootstrap_dhcp.rs

impl OKDDhcpScore {
        ...
        Self {
            dhcp_score: DhcpScore::new(
                ...
                Some("undionly.kpxe".to_string()),

Update the interpret (function called by the execute fn of the interpret) so it now updates the filename field value in modules/dhcp.rs

impl DhcpInterpret {
        ...
        let filename_outcome = match &self.score.filename {
            Some(filename) => {
                let dhcp_server = Arc::new(topology.dhcp_server.clone());
                dhcp_server.set_filename(&filename).await?;
                Outcome::new(
                    InterpretStatus::SUCCESS,
                    format!("Dhcp Interpret Set filename to {filename}"),
                )
            }
            None => Outcome::noop(),
        };

        if next_server_outcome.status == InterpretStatus::NOOP
            && boot_filename_outcome.status == InterpretStatus::NOOP
            && filename_outcome.status == InterpretStatus::NOOP

            ...

            Ok(Outcome::new(
            InterpretStatus::SUCCESS,
            format!(
                "Dhcp Interpret Set next boot to [{:?}], boot_filename to [{:?}], filename to [{:?}]",
                self.score.boot_filename, self.score.boot_filename, self.score.filename
            )
            ...