Files
threshold/.release/linux/test/test-package-scripts.sh
T
shadowdaoandClaude Sonnet 5.5 d07030a10b Make in-place upgrade from HashiCorp Boundary seamless
Linux packages: migrate /etc/boundary.d to /etc/threshold.d without
clobbering, reuse the boundary service user, carry over service
enablement with a boundary.service alias, provide a boundary command.
Docker: accept /boundary/config.hcl, boundary command, /boundary symlink.
CLI: deprecation notice when invoked as boundary (stderr only).
Dev mode: also create *.threshold.dev aliases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 11:12:29 -07:00

268 lines
11 KiB
Bash
Executable File

#!/bin/sh
# Self-contained test for the Linux package scripts (preinst/postinst/postrm).
#
# Simulates an old HashiCorp Boundary layout in a temporary directory (fake
# /etc/boundary.d, a "boundary" user, a running boundary.service) using the
# THRESHOLD_PKG_ROOT prefix and fake id/useradd/userdel/systemctl commands.
# Needs neither root nor systemd.
#
# Usage: .release/linux/test/test-package-scripts.sh
set -eu
HERE=$(cd "$(dirname "$0")" && pwd)
PKG_DIR=$(cd "$HERE/.." && pwd)
PREINST="$PKG_DIR/preinst"
POSTINST="$PKG_DIR/postinst"
POSTRM="$PKG_DIR/postrm"
SH=${TEST_SH:-sh}
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT INT TERM
FAILS=0
PASSES=0
pass() { PASSES=$((PASSES + 1)); }
fail() {
FAILS=$((FAILS + 1))
echo "FAIL: $*" >&2
}
assert() { # assert DESC cmd...
_d=$1
shift
if "$@"; then pass; else fail "$_d"; fi
}
refute() { # refute DESC cmd...
_d=$1
shift
if "$@"; then fail "$_d"; else pass; fi
}
file_has() { grep -qF -- "$2" "$1"; }
file_eq() { [ "$(cat "$1")" = "$2" ]; }
# --- fake commands ------------------------------------------------------------
BIN="$WORK/bin"
mkdir -p "$BIN"
cat >"$BIN/id" <<'EOF'
#!/bin/sh
# fake id: id -u NAME | id -gn NAME ; users in $FAKE/users as name:group
mode=$1
name=$2
line=$(grep "^$name:" "$FAKE/users" 2>/dev/null) || exit 1
case "$mode" in
-u) echo 1000 ;;
-gn) echo "${line#*:}" ;;
esac
EOF
cat >"$BIN/useradd" <<'EOF'
#!/bin/sh
for a in "$@"; do name=$a; done
echo "$name:$name" >>"$FAKE/users"
echo "useradd $name" >>"$FAKE/calls"
EOF
cat >"$BIN/userdel" <<'EOF'
#!/bin/sh
grep -v "^$1:" "$FAKE/users" >"$FAKE/users.new" || true
mv "$FAKE/users.new" "$FAKE/users"
echo "userdel $1" >>"$FAKE/calls"
EOF
cat >"$BIN/systemctl" <<'EOF'
#!/bin/sh
# fake systemctl backed by files in $FAKE (state) and $THRESHOLD_PKG_ROOT
resolve() {
if [ -L "$THRESHOLD_PKG_ROOT/etc/systemd/system/$1" ]; then
_t=$(readlink "$THRESHOLD_PKG_ROOT/etc/systemd/system/$1")
echo "${_t##*/}"
else
echo "$1"
fi
}
echo "systemctl $*" >>"$FAKE/calls"
case "$1" in
show)
u=$(resolve "$4")
case "$3" in
Id) echo "Id=$u" ;;
LoadState)
if [ -f "$THRESHOLD_PKG_ROOT/usr/lib/systemd/system/$u" ]; then
echo "LoadState=loaded"
else
echo "LoadState=not-found"
fi
;;
esac
;;
is-enabled) u=$(resolve "$3"); [ -e "$FAKE/enabled/$u" ] ;;
is-active) u=$(resolve "$3"); [ -e "$FAKE/active/$u" ] ;;
enable) u=$(resolve "$2"); : >"$FAKE/enabled/$u" ;;
disable) u=$(resolve "$2"); rm -f "$FAKE/enabled/$u" ;;
start)
u=$(resolve "$2")
[ -e "$FAKE/fail_start/$u" ] && exit 1
: >"$FAKE/active/$u"
;;
stop) u=$(resolve "$2"); rm -f "$FAKE/active/$u" ;;
daemon-reload) : ;;
esac
exit $?
EOF
chmod 755 "$BIN"/*
# --- scenario helpers -----------------------------------------------------------
new_root() { # new_root NAME -> sets ROOT and FAKE, creates skeleton
ROOT="$WORK/$1/root"
FAKE="$WORK/$1/fake"
mkdir -p "$ROOT/etc" "$ROOT/usr/bin" "$ROOT/usr/lib/systemd/system" \
"$ROOT/etc/systemd/system" "$ROOT/run/systemd/system" \
"$FAKE/enabled" "$FAKE/active" "$FAKE/fail_start"
: >"$FAKE/users"
: >"$FAKE/calls"
# What the package itself would have unpacked.
: >"$ROOT/usr/bin/threshold"
echo "[Service]" >"$ROOT/usr/lib/systemd/system/threshold.service"
export THRESHOLD_PKG_ROOT="$ROOT" FAKE
}
run_script() { # run_script SCRIPT [ARGS...]
_s=$1
shift
PATH="$BIN:$PATH" "$SH" "$_s" "$@" >"$WORK/out.log" 2>&1
}
add_legacy_layout() {
mkdir -p "$ROOT/etc/boundary.d/tls"
echo 'controller { name = "mine" }' >"$ROOT/etc/boundary.d/boundary.hcl"
echo 'BOUNDARY_POSTGRES_URL=secret' >"$ROOT/etc/boundary.d/boundary.env"
echo 'worker { name = "w" }' >"$ROOT/etc/boundary.d/worker.hcl"
echo 'KEY' >"$ROOT/etc/boundary.d/tls/server.key"
chmod 600 "$ROOT/etc/boundary.d/tls/server.key"
echo "boundary:boundary" >>"$FAKE/users"
echo "[Service]" >"$ROOT/usr/lib/systemd/system/boundary.service"
}
# ==============================================================================
echo "== scenario 1: upgrade from Boundary (running + enabled), existing threshold.hcl"
new_root s1
add_legacy_layout
: >"$FAKE/enabled/boundary.service"
: >"$FAKE/active/boundary.service"
mkdir -p "$ROOT/etc/threshold.d"
echo 'USER-OWNED' >"$ROOT/etc/threshold.d/threshold.hcl"
assert "preinst succeeds" run_script "$PREINST" install
assert "threshold.hcl NOT clobbered" file_eq "$ROOT/etc/threshold.d/threshold.hcl" "USER-OWNED"
assert "boundary.env migrated to threshold.env" file_has "$ROOT/etc/threshold.d/threshold.env" "BOUNDARY_POSTGRES_URL=secret"
assert "worker.hcl copied under same name" file_has "$ROOT/etc/threshold.d/worker.hcl" 'name = "w"'
assert "subdirectory copied" file_has "$ROOT/etc/threshold.d/tls/server.key" "KEY"
assert "originals kept: boundary.hcl" test -f "$ROOT/etc/boundary.d/boundary.hcl"
assert "originals kept: boundary.env" test -f "$ROOT/etc/boundary.d/boundary.env"
refute "no duplicate threshold user created" grep -q '^useradd' "$FAKE/calls"
refute "no boundary.hcl name left in threshold.d" test -e "$ROOT/etc/threshold.d/boundary.hcl"
assert "postinst succeeds" run_script "$POSTINST" configure
assert "drop-in written" file_has "$ROOT/etc/systemd/system/threshold.service.d/10-legacy-boundary-user.conf" "User=boundary"
assert "drop-in group" file_has "$ROOT/etc/systemd/system/threshold.service.d/10-legacy-boundary-user.conf" "Group=boundary"
assert "boundary command symlink" test -L "$ROOT/usr/bin/boundary"
assert "boundary symlink target is threshold" test "$(readlink "$ROOT/usr/bin/boundary")" = "threshold"
assert "boundary.service alias symlink" test -L "$ROOT/etc/systemd/system/boundary.service"
assert "legacy service stopped" test ! -e "$FAKE/active/boundary.service"
assert "threshold enabled" test -e "$FAKE/enabled/threshold.service"
assert "threshold started" test -e "$FAKE/active/threshold.service"
refute "legacy unit not left enabled as itself" grep -q 'enable boundary.service' "$FAKE/calls"
: >"$FAKE/calls"
assert "postinst idempotent (2nd run)" run_script "$POSTINST" configure
refute "2nd run does not stop/start anything" grep -qE 'systemctl (stop|start|enable|disable)' "$FAKE/calls"
assert "preinst idempotent (2nd run)" run_script "$PREINST" upgrade
assert "threshold.hcl still not clobbered" file_eq "$ROOT/etc/threshold.d/threshold.hcl" "USER-OWNED"
echo "== scenario 1b: postrm remove/purge cleans only generated pieces"
assert "postrm remove" run_script "$POSTRM" remove
refute "boundary command symlink removed" test -L "$ROOT/usr/bin/boundary"
refute "alias symlink removed" test -L "$ROOT/etc/systemd/system/boundary.service"
refute "drop-in removed" test -e "$ROOT/etc/systemd/system/threshold.service.d/10-legacy-boundary-user.conf"
assert "user config untouched after remove" test -f "$ROOT/etc/boundary.d/boundary.hcl"
assert "migrated config untouched after remove" test -f "$ROOT/etc/threshold.d/threshold.env"
assert "postrm purge (no threshold user: no userdel)" run_script "$POSTRM" purge
refute "boundary user never deleted" grep -q 'userdel boundary' "$FAKE/calls"
# ==============================================================================
echo "== scenario 2: fresh install, no Boundary"
new_root s2
assert "preinst succeeds" run_script "$PREINST" install
assert "threshold user created" grep -q '^useradd threshold' "$FAKE/calls"
refute "no /etc/threshold.d created by migration" test -e "$ROOT/etc/threshold.d"
assert "postinst succeeds" run_script "$POSTINST" configure
refute "no drop-in" test -e "$ROOT/etc/systemd/system/threshold.service.d"
refute "no boundary.service alias on fresh install" test -L "$ROOT/etc/systemd/system/boundary.service"
assert "boundary command symlink still provided" test -L "$ROOT/usr/bin/boundary"
refute "threshold not auto-enabled on fresh install" test -e "$FAKE/enabled/threshold.service"
assert "postrm purge deletes threshold user" run_script "$POSTRM" purge
assert "userdel threshold called" grep -q '^userdel threshold' "$FAKE/calls"
# ==============================================================================
echo "== scenario 3: boundary service enabled but threshold start fails -> rollback"
new_root s3
add_legacy_layout
: >"$FAKE/enabled/boundary.service"
: >"$FAKE/active/boundary.service"
: >"$FAKE/fail_start/threshold.service"
assert "preinst succeeds" run_script "$PREINST" install
assert "postinst still exits 0" run_script "$POSTINST" configure
assert "legacy service running again" test -e "$FAKE/active/boundary.service"
assert "legacy service enabled again" test -e "$FAKE/enabled/boundary.service"
refute "threshold left disabled" test -e "$FAKE/enabled/threshold.service"
refute "alias removed on rollback" test -L "$ROOT/etc/systemd/system/boundary.service"
assert "rollback explained" file_has "$WORK/out.log" "rolling back"
# ==============================================================================
echo "== scenario 4: enabled but stopped boundary service is only carried over"
new_root s4
add_legacy_layout
: >"$FAKE/enabled/boundary.service"
assert "preinst" run_script "$PREINST" install
assert "postinst" run_script "$POSTINST" configure
assert "threshold enabled" test -e "$FAKE/enabled/threshold.service"
refute "threshold not started" test -e "$FAKE/active/threshold.service"
# ==============================================================================
echo "== scenario 5: custom regular-file /etc/systemd/system/boundary.service is left alone"
new_root s5
add_legacy_layout
: >"$FAKE/enabled/boundary.service"
: >"$FAKE/active/boundary.service"
echo "CUSTOM" >"$ROOT/etc/systemd/system/boundary.service"
assert "preinst" run_script "$PREINST" install
assert "postinst" run_script "$POSTINST" configure
assert "custom unit untouched" file_eq "$ROOT/etc/systemd/system/boundary.service" "CUSTOM"
assert "legacy service still running" test -e "$FAKE/active/boundary.service"
refute "threshold not started" test -e "$FAKE/active/threshold.service"
# ==============================================================================
echo "== scenario 6: old boundary package binary present is not replaced"
new_root s6
add_legacy_layout
echo "OLDBIN" >"$ROOT/usr/bin/boundary"
assert "preinst" run_script "$PREINST" install
assert "postinst" run_script "$POSTINST" configure
refute "boundary binary not turned into symlink" test -L "$ROOT/usr/bin/boundary"
assert "boundary binary content kept" file_eq "$ROOT/usr/bin/boundary" "OLDBIN"
assert "postrm remove does not delete the old binary" run_script "$POSTRM" remove
assert "old binary still there" test -f "$ROOT/usr/bin/boundary"
# ==============================================================================
echo "== scenario 7: threshold user already exists alongside boundary -> no drop-in"
new_root s7
add_legacy_layout
echo "threshold:threshold" >>"$FAKE/users"
assert "preinst" run_script "$PREINST" install
assert "postinst" run_script "$POSTINST" configure
refute "no drop-in when threshold user exists" test -e "$ROOT/etc/systemd/system/threshold.service.d"
# ==============================================================================
echo
echo "passed: $PASSES, failed: $FAILS"
[ "$FAILS" -eq 0 ]