fix: teardown-host refuses a terminal-less run instead of aborting mute #119
3 changed files with 32 additions and 0 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -154,6 +154,21 @@ which records not just what changed but what each drill run proved.
|
|||
wrong default: it is the only thing to roll back *to*, at exactly the
|
||||
moment that matters. No behaviour change.
|
||||
|
||||
- **`teardown-host.sh` refuses a terminal-less run instead of aborting mute**
|
||||
(#113) — the most destructive script in the tree was the one that would not
|
||||
tell a non-interactive caller how to proceed. With no `--yes`/`BOX_YES` and
|
||||
no TTY it fell straight into `read`, took the instant EOF and exited 1
|
||||
saying only `aborted` — a refusal that names neither the cause nor the
|
||||
override. It now checks `[ -t 0 ]` and refuses with
|
||||
`--yes (or BOX_YES=1) means yes.`, exit **2** — "you invoked this wrong",
|
||||
the same contract and the same code as `host/revoke-user.sh --purge` and
|
||||
`install.sh`'s `confirm()`, versus 1 for "you were asked and you said no".
|
||||
The gate sits *below* the `--yes`/`BOX_YES` arm, so consent given
|
||||
non-interactively still runs headless — CI's uninstall drill and
|
||||
`box uninstall --purge-host --force` forward `--yes` and are unaffected —
|
||||
and *above* the first `incus` call, so the refusal costs no daemon and
|
||||
`test/cli.sh` drives it for real rather than grepping for it.
|
||||
|
||||
## 0.8.0 — 2026-07-19
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@ $purge && echo "Incus itself will also be uninstalled (--purge-incus)."
|
|||
if [ "$yes" -eq 1 ]; then
|
||||
echo "(confirmed non-interactively: --yes/BOX_YES)"
|
||||
else
|
||||
# No terminal to ask on, and no consent given: refuse and say how to proceed,
|
||||
# rather than fall into 'read', hit instant EOF and abort with nothing but
|
||||
# "aborted" (#113). This must stay BELOW the --yes/BOX_YES arm above — the
|
||||
# order is the contract: consent given non-interactively still runs headless
|
||||
# (CI's uninstall drill and 'box uninstall --purge-host --force' depend on
|
||||
# it), consent NOT given without a terminal is a usage error, exit 2, the
|
||||
# same shape as host/revoke-user.sh and install.sh. It also lands before the
|
||||
# first 'incus' call below, so the refusal needs no daemon.
|
||||
if [ ! -t 0 ]; then
|
||||
echo "teardown-host: refusing to run without a terminal to confirm on. --yes (or BOX_YES=1) means yes." >&2
|
||||
exit 2
|
||||
fi
|
||||
# EOF (Ctrl-D) refuses, out loud: unguarded, errexit would end the run on
|
||||
# this line and the 'aborted' below would never print (#111).
|
||||
read -rp "Continue? [y/N] " a || { echo "aborted"; exit 1; }
|
||||
|
|
|
|||
|
|
@ -1993,6 +1993,11 @@ check "teardown-host: honors --yes/BOX_YES (CI runs it unattended)" 0 "" \
|
|||
grep -qF 'BOX_YES' "$ROOT/host/teardown-host.sh"
|
||||
check "teardown-host: points at box uninstall when done" 0 "" \
|
||||
grep -qF "box uninstall" "$ROOT/host/teardown-host.sh"
|
||||
# ...and the other side of that contract (#113): consent NOT given and no
|
||||
# terminal to ask on is a usage error, not a mute 'aborted'. Driven for real —
|
||||
# the gate sits above the first 'incus' call, so a daemon-free run reaches it.
|
||||
check "teardown-host: refuses without a TTY and names the override (#113)" 2 \
|
||||
"--yes (or BOX_YES=1) means yes" bash "$ROOT/host/teardown-host.sh" </dev/null
|
||||
|
||||
# #102's race, in the one other file that sets pipefail. A daemon-free run
|
||||
# cannot exercise a UFW teardown, so the shape is pinned instead: no `ufw
|
||||
|
|
|
|||
Loading…
Reference in a new issue