From c4126464980e886399784ce3bfd5b55c7f5b4ee2 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 9 May 2026 18:22:22 +0000 Subject: [PATCH 1/2] testing: pre-create /run/fips/ in the unified test image Mirrors systemd's RuntimeDirectory=fips so the daemon's resolve_default_socket() picks /run/fips/control.sock inside containers, matching production layout and the path that the chaos sim harness (testing/chaos/sim/control.py) probes. Without this, the resolver falls through to /tmp/fips-control.sock (no /run/fips, no XDG_RUNTIME_DIR), the daemon binds there, and the harness's hardcoded /run/fips/control.sock probe returns FileNotFoundError on every node. chaos-bloom-storm then fails its bloom_send_rate assertion with start=0 nodes, end=0 nodes; other chaos scenarios pass only because their tolerances absorb the empty samples. Production hosts always have /run/fips materialized by the fips.service unit's RuntimeDirectory directive before the daemon starts, which is why the regression hit only the containerized test path. Verified locally with chaos-bloom-storm: max per-node delta 27 <= ceiling 30 over the trailing 30s window. --- testing/docker/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testing/docker/Dockerfile b/testing/docker/Dockerfile index bacd89a..7247133 100644 --- a/testing/docker/Dockerfile +++ b/testing/docker/Dockerfile @@ -39,6 +39,11 @@ RUN printf '%s\n' \ COPY fips fipsctl fipstop fips-gateway /usr/local/bin/ RUN chmod +x /usr/local/bin/fips /usr/local/bin/fipsctl /usr/local/bin/fipstop /usr/local/bin/fips-gateway +# Mirror systemd's RuntimeDirectory=fips so the daemon's resolver picks +# /run/fips/control.sock — matches production layout and the chaos sim +# harness probe path (testing/chaos/sim/control.py). +RUN mkdir -p /run/fips + # Static web page for HTTP server (chaos/static modes) RUN printf 'Fuck IPs!\n' > /root/index.html From e471807239d5f127c2c2092f456d950622d7b2d9 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 9 May 2026 18:27:38 +0000 Subject: [PATCH 2/2] testing/firewall: avoid SIGPIPE in drop-counter probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drop-counter sanity check piped `nft list table inet fips` through `awk '/counter packets/ {print $3; exit}'`. Awk's `exit` on first match closes the pipe, the upstream `nft list` SIGPIPEs on its next write, `set -o pipefail` makes the pipeline return 141, and the surrounding command-substitution aborts the script before it can assign DROP_PKTS or print the section header. Replaces the early-exit pattern with `/counter packets/ && !seen { print $3; seen=1 }` — same first-match output, but awk reads the full input so nft never SIGPIPEs. The original form had been latent for as long as the test has existed; recent CI runs at master tip 53ad528 finally tripped it (output shows the script dying immediately after the case-(d) PASS, before "=== Drop counter incremented..." prints). Verified locally: `bash testing/ci-local.sh --only firewall` runs all six setup-and-functional steps green and prints "PASS: drop counter = 5". --- testing/firewall/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/firewall/test.sh b/testing/firewall/test.sh index 75c758f..e21432f 100755 --- a/testing/firewall/test.sh +++ b/testing/firewall/test.sh @@ -238,7 +238,7 @@ fi # ── Drop-counter sanity ──────────────────────────────────────────────── log "Drop counter incremented (case a should have ticked it)" DROP_PKTS="$(docker exec "$CONTAINER_B" nft list table inet fips \ - | awk '/counter packets/ {print $3; exit}')" + | awk '/counter packets/ && !seen { print $3; seen=1 }')" if [ -z "${DROP_PKTS:-}" ] || [ "$DROP_PKTS" -lt 1 ]; then fail "drop counter is $DROP_PKTS — case (a) should have produced drops" fi