Files
kaidi/scripts/test-purge-fixture.sh
T

96 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
fail() {
printf 'Purge fixture failed: %s\n' "$1" >&2
exit 1
}
sed '$d' "$ROOT/deploy/purge.sh" > "$WORK/purge-functions.sh"
# shellcheck disable=SC1090,SC1091
source "$WORK/purge-functions.sh"
install() {
local -a arguments=()
while [ "$#" -gt 0 ]; do
case "$1" in
-o|-g) shift 2 ;;
*) arguments+=("$1"); shift ;;
esac
done
command install "${arguments[@]}"
}
APP_ROOT="$WORK/opt/kaidi"
BAOTA_ROOT="$WORK/www/kaidi"
CONFIG_ROOT="$WORK/etc/kaidi"
STATE_ROOT="$WORK/var/lib/kaidi"
UPDATE_STATE_ROOT="$WORK/var/lib/kaidi-update"
LOG_ROOT="$WORK/var/log/kaidi"
FIRST_LOGIN_FILE="$WORK/root/kaidi-first-login.txt"
# shellcheck disable=SC2034 # Referenced by the sourced purge helper.
BACKUP_ROOT="$WORK/recovery"
BACKUP_ARCHIVE=
mkdir -p \
"$APP_ROOT" \
"$BAOTA_ROOT" \
"$CONFIG_ROOT" \
"$STATE_ROOT/files" \
"$UPDATE_STATE_ROOT/backups" \
"$UPDATE_STATE_ROOT/failed" \
"$UPDATE_STATE_ROOT/transactions" \
"$LOG_ROOT" \
"$(dirname "$FIRST_LOGIN_FILE")" \
"$WORK/external-mysql" \
"$WORK/reverse-proxy"
printf 'DB_PASSWORD="secret"\n' > "$CONFIG_ROOT/kaidi.env"
printf 'document\n' > "$STATE_ROOT/files/document.txt"
printf 'dump\n' > "$UPDATE_STATE_ROOT/backups/mysql.sql"
printf 'setup code\n' > "$FIRST_LOGIN_FILE"
printf 'database sentinel\n' > "$WORK/external-mysql/keep"
printf 'proxy sentinel\n' > "$WORK/reverse-proxy/keep"
create_recovery_backup
[ -s "$BACKUP_ARCHIVE" ] || fail 'root-only recovery archive was not created'
[ "$(stat -c '%a' "$BACKUP_ARCHIVE" 2>/dev/null || stat -f '%Lp' "$BACKUP_ARCHIVE")" = 600 ] \
|| fail 'recovery archive mode is not 0600'
archive_list=$(tar -tzf "$BACKUP_ARCHIVE")
grep -Fq "${CONFIG_ROOT#/}/kaidi.env" <<< "$archive_list" \
|| fail 'configuration was omitted from the recovery archive'
grep -Fq "${STATE_ROOT#/}/files/document.txt" <<< "$archive_list" \
|| fail 'file storage was omitted from the recovery archive'
grep -Fq "${UPDATE_STATE_ROOT#/}/backups/mysql.sql" <<< "$archive_list" \
|| fail 'database backup was omitted from the recovery archive'
remove_managed_paths
for path in "$APP_ROOT" "$BAOTA_ROOT" "$CONFIG_ROOT" "$STATE_ROOT" "$UPDATE_STATE_ROOT" "$LOG_ROOT"; do
[ ! -e "$path" ] || fail "managed path was not removed: $path"
done
[ ! -e "$FIRST_LOGIN_FILE" ] || fail 'first-login file was not removed'
[ -f "$WORK/external-mysql/keep" ] || fail 'external database state was removed'
[ -f "$WORK/reverse-proxy/keep" ] || fail 'reverse-proxy state was removed'
[ -s "$BACKUP_ARCHIVE" ] || fail 'recovery archive was removed with the installation'
[ "$(tail -n 1 "$ROOT/deploy/purge.sh")" = 'main "$@"' ] \
|| fail 'purge actions can execute before a complete curl stream is parsed'
# shellcheck disable=SC2016 # Match the literal guard in the purge source.
grep -Fq 'KAIDI_PURGE_CONFIRM=$REQUIRED_CONFIRMATION' "$ROOT/deploy/purge.sh" \
|| fail 'destructive removal no longer requires explicit confirmation'
grep -Fq 'External MySQL data and reverse-proxy configuration will not be modified' "$ROOT/deploy/purge.sh" \
|| fail 'purge boundary is no longer explicit'
# shellcheck disable=SC2016 # Match literal service-account cleanup calls.
grep -Fq 'terminate_uid_processes "$service_uid"' "$ROOT/deploy/purge.sh" \
|| fail 'dedicated service-account processes are not terminated before account removal'
# shellcheck disable=SC2016 # Match literal forced account removal.
grep -Fq 'userdel --force "$SERVICE_USER"' "$ROOT/deploy/purge.sh" \
|| fail 'dedicated service-account removal is not resilient to a restarting panel process'
grep -Fq '/etc/systemd/system/kaidi-update.service.d' "$ROOT/deploy/purge.sh" \
|| fail 'updater systemd drop-ins are not removed'
printf 'Local purge and recovery fixture passed\n'