#!/bin/bash # bootstrap-modes.sh — R-21 slice C regression harness for felhom-bootstrap.sh's two modes. Runs as # root inside a throwaway container (felhom-iso-assistant:trixie — python3 needed by the pairing # parsers; writes /etc/felhom etc.); fakes curl + host-install + systemctl + sleep on PATH. Asserts: # D (regression): a DIRECT env (customer-id + passphrase) enters run_direct and makes ZERO calls to # /api/v1/appliance/* — the pairing code path is provably not entered. # P (pairing+delivery, v1.21.0 loop semantics): an env WITHOUT customer-id/passphrase enters # run_pairing, POSTs /appliance/register, persists the token, polls 204 INSIDE one # invocation (fake sleep counts the waits; the script never exits between polls), # then consumes the 200 delivery, writes the direct env and runs host-install. # 410: a consumed-delivery poll exits non-zero (the crash-window hand-back to systemd). # (Updated for v1.21.0/R-33: the old one-poll-per-invocation scenarios expected a non-zero exit on # 204, which the in-script wait deliberately no longer does — waiting is not failing.) set -uo pipefail BSTRAP=/work/felhom-bootstrap.sh FAKE=/work/fakebin; rm -rf "$FAKE"; mkdir -p "$FAKE" CALLS=/work/curl.log export PATH="$FAKE:$PATH" fail=0 say() { echo "TEST: $*"; } check() { if eval "$2"; then echo " ok: $1"; else echo " FAIL: $1"; fail=1; fi; } # --- fake sleep: counts waits; flips the poll to 200 after 3, hard-aborts a runaway loop ------------ cat > "$FAKE/sleep" <<'SLEEP' #!/bin/bash n=$(cat /work/sleep.count 2>/dev/null || echo 0); n=$((n+1)); echo "$n" > /work/sleep.count flip=$(cat /work/sleep.flip 2>/dev/null || echo "") [ -n "$flip" ] && [ "$n" -ge "$flip" ] && echo 200 > /work/poll-mode if [ "$n" -gt 25 ]; then echo "RUNAWAY: fake sleep hit $n calls — killing the loop" >&2; kill -TERM $PPID; fi exit 0 SLEEP chmod +x "$FAKE/sleep" # --- fake curl: logs every invocation's URL; emulates -o (fetch), --data (register), -w code (poll) -- cat > "$FAKE/curl" <<'CURL' #!/bin/bash url=""; ofile=""; wfmt="" prev="" for a in "$@"; do case "$a" in http*|https*) url="$a";; esac case "$prev" in -o) ofile="$a";; -w) wfmt="$a";; esac prev="$a" done echo "$url" >> /work/curl.log mode=$(cat /work/poll-mode 2>/dev/null || echo 204) case "$url" in *"/felhom-host-install.sh") # write a stub host-install to the -o target cat > "$ofile" <<'HI' #!/bin/bash echo "fake host-install ran: $*" >> /work/hostinstall.log exit 0 HI exit 0 ;; *"/appliance/register") echo '{"appliance_token":"TESTTOKEN123456","poll_interval_sec":30}' exit 0 ;; *"/appliance/poll") if [ "$mode" = "200" ]; then # body then, if -w set, a newline + code (matches the bootstrap's -w '\n%{http_code}') printf '%s' '{"customer_id":"drill","retrieval_passphrase":"SEKRET-PASS","mode":"appliance","extra_args":"--cores 2"}' [ -n "$wfmt" ] && printf '\n200' else [ -n "$wfmt" ] && printf '\n%s' "$mode" # 204 / 410 / whatever the scenario set fi exit 0 ;; esac exit 0 CURL chmod +x "$FAKE/curl" # fake systemctl (disable is a no-op) printf '#!/bin/bash\nexit 0\n' > "$FAKE/systemctl"; chmod +x "$FAKE/systemctl" reset_state() { rm -rf /etc/felhom /run/felhom-bootstrap-pass /var/lib/felhom-install "$CALLS" /work/hostinstall.log \ /work/poll-mode /work/sleep.count /work/sleep.flip mkdir -p /etc/felhom } # ============================ Scenario D — direct mode, zero appliance calls ========================= say "D: direct env -> run_direct, NO appliance calls" reset_state cat > /etc/felhom/bootstrap.env <<'ENV' FELHOM_CUSTOMER_ID=acme FELHOM_MODE=appliance FELHOM_RETRIEVAL_PASSPHRASE=direct-pass FELHOM_HUB_URL=https://hub.example ENV chmod 0600 /etc/felhom/bootstrap.env bash "$BSTRAP"; rc=$? check "run_direct exited 0 (host-install stub succeeded)" "[ $rc -eq 0 ]" check "host-install was invoked" "[ -f /work/hostinstall.log ]" check "ZERO /appliance/register calls" "! grep -q '/appliance/register' $CALLS" check "ZERO /appliance/poll calls" "! grep -q '/appliance/poll' $CALLS" check "done-flag written" "[ -f /etc/felhom/.bootstrap-done ]" check "env shredded on success" "[ ! -f /etc/felhom/bootstrap.env ]" # ============ P: pairing loop (v1.21.0) — register, wait unbound INSIDE one invocation, deliver ===== say "P: pairing env -> register + in-script 204 wait -> 200 delivery -> host-install, ONE invocation" reset_state cat > /etc/felhom/bootstrap.env <<'ENV' FELHOM_HUB_URL=https://hub.example ENV echo 204 > /work/poll-mode echo 3 > /work/sleep.flip # after 3 in-script waits the hub "binds" (poll flips to 200) bash "$BSTRAP"; rc=$? check "single invocation ran to done (exit 0)" "[ $rc -eq 0 ]" check "POSTed /appliance/register" "grep -q '/appliance/register' $CALLS" check "appliance token persisted 0600" "[ -f /etc/felhom/.bootstrap-done ] || { [ -f /etc/felhom/appliance-token ] && [ \"\$(stat -c %a /etc/felhom/appliance-token)\" = 600 ]; }" check "polled more than once (the wait lived in-script, not in systemd restarts)" "[ \$(grep -c '/appliance/poll' $CALLS) -ge 2 ]" check "waited between polls (fake sleep called >=3x)" "[ \"\$(cat /work/sleep.count 2>/dev/null || echo 0)\" -ge 3 ]" check "host-install invoked after delivery" "[ -f /work/hostinstall.log ]" check "done-flag written" "[ -f /etc/felhom/.bootstrap-done ]" # the token was ALSO consumed on success (run_direct scrubs both secrets) check "env shredded on success" "[ ! -f /etc/felhom/bootstrap.env ]" # ============ 410: consumed delivery without a local env -> exit non-zero (crash window) ============ say "410: consumed delivery + no env -> exit non-zero so systemd restarts clean" reset_state cat > /etc/felhom/bootstrap.env <<'ENV' FELHOM_HUB_URL=https://hub.example ENV echo 410 > /work/poll-mode bash "$BSTRAP"; rc=$? check "410 poll exits non-zero" "[ $rc -ne 0 ]" check "host-install NOT run" "[ ! -f /work/hostinstall.log ]" echo "==================================================" if [ $fail -eq 0 ]; then echo "ALL BOOTSTRAP-MODE TESTS PASSED"; else echo "SOME TESTS FAILED"; fi exit $fail