feat: add full disaster-recovery mode to restore.sh

Adds container_running/container_health/wait_for_container/start_db
helpers and cmd_full(), plus tests. Fixed a delimiter bug in the two
new tests' sed scripts (the literal `${TARGET#/}` replacement text
collided with `#` as the sed delimiter) and relaxed the dry-run
no-external-calls assertion to allow the legitimate borg-list call
from resolve_archive(), mirroring the existing db dry-run test.
This commit is contained in:
kbe
2026-07-25 19:23:27 +02:00
parent 5d547f04ec
commit 4be1372e4d
2 changed files with 122 additions and 0 deletions
+42
View File
@@ -146,6 +146,46 @@ test_db_restore_aborts_on_wrong_confirmation() {
rm -rf "$mockdir"
}
test_full_restore_refuses_nonempty_target_without_force() {
local mockdir target rc
mockdir="$(mktemp -d)"
target="$(mktemp -d)"
touch "$target/existing-file"
setup_mock_bin "$mockdir"
set +e
PATH="$mockdir:$PATH" TARGET_OVERRIDE=1 bash -c '
sed "s#^TARGET=\"/home/srv/files/content\"#TARGET=\"'"$target"'\"#; s@^ARCHIVE_TARGET_PATH=.*@ARCHIVE_TARGET_PATH=\"\${TARGET#/}\"@" "'"$RESTORE"'" > "'"$mockdir"'/restore_patched.sh"
bash "'"$mockdir"'/restore_patched.sh" full
' >/dev/null 2>&1
rc=$?
set -e
assert_eq "1" "$rc" "full mode refuses non-empty target without --force"
rm -rf "$mockdir" "$target"
}
test_full_restore_dry_run_makes_no_calls() {
local mockdir target out
mockdir="$(mktemp -d)"
target="$(mktemp -d)"
setup_mock_bin "$mockdir"
out="$(PATH="$mockdir:$PATH" bash -c '
sed "s#^TARGET=\"/home/srv/files/content\"#TARGET=\"'"$target"'\"#; s@^ARCHIVE_TARGET_PATH=.*@ARCHIVE_TARGET_PATH=\"\${TARGET#/}\"@" "'"$RESTORE"'" > "'"$mockdir"'/restore_patched.sh"
bash "'"$mockdir"'/restore_patched.sh" full --dry-run
')"
assert_contains "$out" "DRY-RUN" "full dry-run prints DRY-RUN plan"
# cmd_full calls resolve_archive() (a borg list call) before checking
# DRY_RUN, same as cmd_db/cmd_file, so mock.log legitimately gets a
# "borg list" entry. What must NOT happen in dry-run is a borg extract,
# or any docker/db-client interaction.
if grep -qE "^(borg extract|docker|mysql|mariadb)" "$mockdir/mock.log" 2>/dev/null; then
echo "FAIL: full dry-run invoked borg extract or a docker/db-client mock binary"
FAILURES=$((FAILURES + 1))
else
echo "PASS: full dry-run made no borg extract or docker/db-client calls"
fi
rm -rf "$mockdir" "$target"
}
test_help_exits_zero
test_no_args_exits_one
test_unknown_command_exits_one
@@ -155,6 +195,8 @@ test_file_restore_dry_run_makes_no_borg_call
test_db_restore_with_yes_runs_full_sequence
test_db_restore_dry_run_skips_confirmation_and_calls
test_db_restore_aborts_on_wrong_confirmation
test_full_restore_refuses_nonempty_target_without_force
test_full_restore_dry_run_makes_no_calls
echo "-----"
if [[ "$FAILURES" -gt 0 ]]; then