diff --git a/docs/audit/d129-plugins-20260720.txt b/docs/audit/d129-plugins-20260720.txt new file mode 100644 index 0000000..337042c --- /dev/null +++ b/docs/audit/d129-plugins-20260720.txt @@ -0,0 +1,10 @@ +NOTE: os-qemu-guest-agent installs the PACKAGE only. For a WORKING guest agent the + libvirt domain must expose the org.qemu.guest_agent.0 virtio channel (IaC: + modules/opnsense-edge), the service must be enabled, and the edge restarted. + New DC edges should be BORN with the channel; office1-opnsense retrofits at + its next scheduled restart. (D-129 Verification, 2026-07-18.) +== install os-qemu-guest-agent == +DRY-RUN POST https://10.12.4.1/api/core/firmware/install/os-qemu-guest-agent +== install os-iperf == +DRY-RUN POST https://10.12.4.1/api/core/firmware/install/os-iperf +OK: profile 'vr1-edge' applied (os-qemu-guest-agent os-iperf) diff --git a/scripts/opnsense-plugins.sh b/scripts/opnsense-plugins.sh index 4ce2a5b..5e10269 100755 --- a/scripts/opnsense-plugins.sh +++ b/scripts/opnsense-plugins.sh @@ -86,7 +86,21 @@ EOF } -api() { bash "$API" ${DRY_RUN:+--dry-run} "$@"; } +# DO NOT "simplify" this back to `bash "$API" ${DRY_RUN:+--dry-run} "$@"`. +# That was the original form and it was a FALSE-SUCCESS BUG (found 2026-07-20 on the +# first-ever live run, against the vr1-dc0 edge): `${VAR:+word}` expands whenever VAR +# is set and NON-EMPTY, and DRY_RUN=0 is non-empty -- so EVERY call, including a real +# `apply`, was silently handed --dry-run while the script still printed +# "OK: profile 'vr1-edge' applied". Nothing was ever installed. The harness missed it +# because it only ever drove --dry-run, so the live path had no coverage at all. +# Test the VALUE, never the emptiness. +api() { + if [ "$DRY_RUN" = "1" ]; then + bash "$API" --dry-run "$@" + else + bash "$API" "$@" + fi +} # Poll core/firmware/upgradestatus until the running action finishes. Live only; # dry-run returns immediately (nothing was actually kicked off). diff --git a/tests/opnsense-plugins/run-tests.sh b/tests/opnsense-plugins/run-tests.sh index eaca9c1..97bd94c 100755 --- a/tests/opnsense-plugins/run-tests.sh +++ b/tests/opnsense-plugins/run-tests.sh @@ -58,5 +58,31 @@ grep -qiE '^[^#]*secret[[:space:]]*=' "$S" && bad "script bakes a secret (must delegate to opnsense-api.sh)" || ok grep -q 'opnsense-api.sh' "$S" && ok || bad "does not delegate HTTP to opnsense-api.sh" +# --- THE LIVE PATH (regression, 2026-07-20). The original `${DRY_RUN:+--dry-run}` +# expanded on DRY_RUN=0 (set-and-non-empty), so a REAL `apply` silently dry-ran +# while printing "OK: profile applied" -- a false success that survived because +# every test above drives --dry-run. These two exercise the LIVE branch with a +# stub api client, and assert the flag is passed if and only if it was asked for. +STUB="$(mktemp -d)" +cp "$S" "$STUB/opnsense-plugins.sh" +cat > "$STUB/opnsense-api.sh" <<'STUBEOF' +#!/usr/bin/env bash +# stub: records its own argv so the harness can see what the caller passed. +printf '%s\n' "ARGS:$*" +STUBEOF +chmod +x "$STUB/opnsense-api.sh" + +LIVE="$(OPNSENSE_API_HOST=10.0.0.1 PLUGIN_POLL_MAX=1 PLUGIN_POLL_SLEEP=0 \ + bash "$STUB/opnsense-plugins.sh" apply vr1-edge 2>/dev/null)" +printf '%s' "$LIVE" | grep -q 'ARGS:.*--dry-run' \ + && bad "LIVE apply passed --dry-run to the api client (the DRY_RUN:+ false-success bug is back)" || ok +printf '%s' "$LIVE" | grep -q 'ARGS:POST core/firmware/install/os-qemu-guest-agent' \ + && ok || bad "LIVE apply did not issue a real install POST" + +DRYRUN="$(OPNSENSE_API_HOST=10.0.0.1 bash "$STUB/opnsense-plugins.sh" --dry-run apply vr1-edge 2>/dev/null)" +printf '%s' "$DRYRUN" | grep -q -- '--dry-run' \ + && ok || bad "--dry-run apply did NOT pass --dry-run through to the api client" +rm -rf "$STUB" + echo "opnsense-plugins: $pass passed, $fail failed" [ "$fail" -eq 0 ]