#!/usr/bin/env bash set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" positional_restore_path="/tmp/baron-sso-restore-positional.tar.gz" trap 'rm -f "$positional_restore_path"' EXIT INT TERM : >"$positional_restore_path" fail() { echo "ERROR: $*" >&2 exit 1 } assert_dry_run_contains() { local output="$1" local expected="$2" grep -Fq -- "$expected" <<<"$output" || fail "dry-run output must contain: $expected" } grep -Fq "FROM debian:trixie-slim" "$repo_root/docker/backup-tools/Dockerfile" \ || fail "backup-tools image must be based on debian:trixie-slim." grep -Fq "zstd" "$repo_root/docker/backup-tools/Dockerfile" \ || fail "backup-tools image must include zstd so restore does not depend on the host." grep -Fq "docker-cli" "$repo_root/docker/backup-tools/Dockerfile" \ || fail "backup-tools image must include docker CLI for containerized dump/restore orchestration." grep -Fq "perl" "$repo_root/docker/backup-tools/Dockerfile" \ || fail "backup-tools image must include perl for legacy ClickHouse schema dump decoding." grep -Fq "unzip" "$repo_root/docker/backup-tools/Dockerfile" \ || fail "backup-tools image must include unzip for .zip restore archives." dump_dry_run="$( make --dry-run --always-make -C "$repo_root" dump DUMP_SERVICES="postgres,config" DUMP_MODE="maintenance" 2>&1 )" assert_dry_run_contains "$dump_dry_run" "docker build" assert_dry_run_contains "$dump_dry_run" "docker run" assert_dry_run_contains "$dump_dry_run" "baron-sso-backup-tools:local" assert_dry_run_contains "$dump_dry_run" "--env-file .env" assert_dry_run_contains "$dump_dry_run" "/var/run/docker.sock:/var/run/docker.sock" assert_dry_run_contains "$dump_dry_run" "/tmp:/tmp" assert_dry_run_contains "$dump_dry_run" "scripts/backup/dump.sh" assert_dry_run_contains "$dump_dry_run" "DUMP_SERVICES=\"postgres,config\"" assert_dry_run_contains "$dump_dry_run" "DUMP_MODE=\"maintenance\"" restore_dry_run="$( make --dry-run --always-make -C "$repo_root" restore BACKUP="backups/example" DUMP_FILE="backups/example.tar.zst" RESTORE_SERVICES="postgres,config" CONFIRM_RESTORE="baron-sso" RESTORE_REPORT="reports/restore-report.json" 2>&1 )" assert_dry_run_contains "$restore_dry_run" "scripts/backup/restore.sh" assert_dry_run_contains "$restore_dry_run" "docker run" assert_dry_run_contains "$restore_dry_run" "BACKUP=\"backups/example\"" assert_dry_run_contains "$restore_dry_run" "DUMP_FILE=\"backups/example.tar.zst\"" assert_dry_run_contains "$restore_dry_run" "RESTORE_SERVICES=\"postgres,config\"" assert_dry_run_contains "$restore_dry_run" "CONFIRM_RESTORE=\"baron-sso\"" assert_dry_run_contains "$restore_dry_run" "RESTORE_REPORT=\"reports/restore-report.json\"" assert_dry_run_contains "$restore_dry_run" "Ensuring restore target containers" assert_dry_run_contains "$restore_dry_run" "ensure_restore_container baron_postgres compose.infra.yaml postgres" assert_dry_run_contains "$restore_dry_run" "ensure_restore_container ory_postgres compose.ory.yaml postgres" restore_file_path_dry_run="$( make --dry-run --always-make -C "$repo_root" restore FILE_PATH="backups/example.tar.zst" RESTORE_SERVICES="postgres" CONFIRM_RESTORE="baron-sso" 2>&1 )" assert_dry_run_contains "$restore_file_path_dry_run" "RESTORE_INPUT=\"backups/example.tar.zst\"" assert_dry_run_contains "$restore_file_path_dry_run" "RESTORE_SERVICES=\"postgres\"" assert_dry_run_contains "$restore_file_path_dry_run" "CONFIRM_RESTORE=\"baron-sso\"" restore_positional_dry_run="$( make --dry-run --always-make -C "$repo_root" restore "$positional_restore_path" RESTORE_SERVICES="config" CONFIRM_RESTORE="baron-sso" 2>&1 )" assert_dry_run_contains "$restore_positional_dry_run" "RESTORE_INPUT=\"$positional_restore_path\"" assert_dry_run_contains "$restore_positional_dry_run" "RESTORE_SERVICES=\"config\"" for target in dump-verify restore-verify dump-list restore-plan; do target_dry_run="$( make --dry-run --always-make -C "$repo_root" "$target" BACKUP="backups/example" 2>&1 )" assert_dry_run_contains "$target_dry_run" "scripts/backup/" done upload_default_dry_run="$( make --dry-run --always-make -C "$repo_root" upload-cloud BACKUP="backups/example" 2>&1 )" assert_dry_run_contains "$upload_default_dry_run" "scripts/backup/upload_cloud.sh" if grep -Fq 'WORKS_DRIVE_AUTH_MODE=""' <<<"$upload_default_dry_run"; then fail "make upload-cloud must not pass an empty WORKS_DRIVE_AUTH_MODE that masks .env." fi if grep -Fq 'WORKS_DRIVE_DRY_RUN=""' <<<"$upload_default_dry_run"; then fail "make upload-cloud must not pass an empty WORKS_DRIVE_DRY_RUN that masks .env." fi upload_dry_run="$( make --dry-run --always-make -C "$repo_root" upload-cloud BACKUP="backups/example" WORKS_DRIVE_DRY_RUN=true WORKS_DRIVE_AUTH_MODE=refresh-token 2>&1 )" assert_dry_run_contains "$upload_dry_run" "docker run" assert_dry_run_contains "$upload_dry_run" "scripts/backup/upload_cloud.sh" assert_dry_run_contains "$upload_dry_run" "BACKUP=\"backups/example\"" assert_dry_run_contains "$upload_dry_run" "WORKS_DRIVE_DRY_RUN=\"true\"" assert_dry_run_contains "$upload_dry_run" "WORKS_DRIVE_AUTH_MODE=\"refresh-token\"" if make -C "$repo_root" BACKUP_USE_DOCKER=false restore >/tmp/baron-sso-restore-missing.out 2>&1; then fail "make restore must fail when BACKUP and CONFIRM_RESTORE are not provided." fi if ! grep -Fq "CONFIRM_RESTORE=baron-sso" /tmp/baron-sso-restore-missing.out; then fail "make restore failure must mention the required confirmation value." fi echo "OK: backup Makefile targets expose the expected guarded interface"