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>
268 lines
11 KiB
Bash
Executable File
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 ]
|