#!/bin/bash set -euo pipefail # Komodo Mongo Daten-Restore Test # # Baut auf dem bestehenden Komodo-Bootstrap-Test auf und fuegt hinzu: # - mongorestore von komodo-mongo.archive.gz in die Test-Mongo # - Liest danach die stack-Collection, um zu pruefen, dass Komodo- # Stack-Definitionen wiederhergestellt sind # # Das ist der Test, der im DR-Fall beweist, dass die KOMODO_*-Stack- # ENV-Werte aus dem Mongo-Dump rekonstruiert werden koennen (die # kanonische Quelle gemaess docs/DISASTER_RECOVERY.md 6.2.1). # # Produktive Komodo-Container und produktive Mongo-Datadir werden # NICHT angefasst. SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" . "$SCRIPT_DIR/common.sh" WHATIF=0 KEEP_DATA=0 for arg in "$@"; do case "$arg" in --what-if) WHATIF=1 ;; --keep-data) KEEP_DATA=1 ;; *) echo "Unknown argument: $arg" >&2; exit 1 ;; esac done RESTORE_ROOT="/mnt/user/backups/restore-lab/komodo-mongo-restore" REPORT_ROOT="/mnt/user/backups/restore-reports" COMPOSE_FILE="$SCRIPT_DIR/komodo-bootstrap-compose.test.yml" PROJECT_NAME="restoretest-komodo-mongo" REPORT_FILE="$REPORT_ROOT/komodo-mongo-restore-$(date +%F).md" DUMP_HOST_PATH="/mnt/user/backups/borg/dumps/latest/komodo-mongo.archive.gz" if [ "$WHATIF" -eq 1 ]; then cat </dev/null 2>&1 || true if [ "$RESTORE_SUCCESS" -ne 1 ]; then preserve_on_failure "komodo-mongo-restore" "$RESTORE_ROOT" return fi if [ "$KEEP_DATA" -ne 1 ]; then rm -rf "$RESTORE_ROOT" fi } trap cleanup EXIT rm -rf "$RESTORE_ROOT" mkdir -p "$RESTORE_ROOT/mongo" "$RESTORE_ROOT/core" "$RESTORE_ROOT/keys" "$RESTORE_ROOT/periphery" # Stufe 1: Nur Test-Mongo starten (kein Core/Periphery noetig fuer Dump-Restore) docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" up -d \ restoretest-komodo-mongo >/dev/null mongo_ok=0 for _ in $(seq 1 30); do s="$(docker inspect restoretest-komodo-mongo --format '{{.State.Health.Status}}' 2>/dev/null || true)" if [ "$s" = "healthy" ]; then mongo_ok=1; break; fi sleep 2 done if [ "$mongo_ok" -ne 1 ]; then echo "Test-Mongo never reported healthy" >&2 docker logs --tail 80 restoretest-komodo-mongo >&2 || true exit 1 fi # Stufe 2: mongorestore aus dem Host-Dump # --drop loescht existierende Collections vor dem Restore (frische DB, also harmlos). # --gzip weil der Dump als .archive.gz erzeugt wurde. # Auth mit den Wegwerf-Credentials aus dem Test-Compose. restore_status="ok" # --noIndexRestore: der Smoke prueft nur, dass Daten lesbar sind, nicht dass # alle Indexe sauber aufgebaut werden. mongorestore scheitert sonst am # Index-Rebuild weil der Test-User keine dbAdmin-Rolle hat. Fuer den # DR-Nachweis (Stack-ENV-Werte lesbar) reicht das. if ! docker exec -i restoretest-komodo-mongo \ mongorestore --archive --gzip --noIndexRestore \ -u komodo -p restoretest-komodo-mongo-pwd --authenticationDatabase admin \ --drop \ < "$DUMP_HOST_PATH" 2>/tmp/komodo-mongorestore.err; then restore_status="failed" cat /tmp/komodo-mongorestore.err >&2 exit 1 fi # Stufe 3: Stack-Collection auslesen # Komodo speichert Stack-Definitionen in der DB "komodo", Collection "Stack" # (oder "stack" je nach Version). Wir zaehlen Dokumente als Beweis. stack_count="n/a" for coll in Stack stack; do count="$(docker exec restoretest-komodo-mongo mongosh --quiet \ -u komodo -p restoretest-komodo-mongo-pwd --authenticationDatabase admin \ --eval "db.getSiblingDB('komodo').getCollection('$coll').countDocuments({})" \ 2>/dev/null | tr -d '[:space:]' || true)" if [ -n "$count" ] && [ "$count" != "0" ] && [ "$count" != "n/a" ]; then stack_count="$count (collection: $coll)" break fi done # Alle DBs + Collections auflisten als zusaetzlicher Nachweis db_list="$(docker exec restoretest-komodo-mongo mongosh --quiet \ -u komodo -p restoretest-komodo-mongo-pwd --authenticationDatabase admin \ --eval "db.adminCommand({listDatabases:1}).databases.map(d=>d.name).join(', ')" \ 2>/dev/null | tr -d '\r' || echo "n/a")" write_report "$REPORT_FILE" < $REPORT_FILE"