Files
Cibello-app/infrastructure/deployment/backup-restore-test.sh
T
2026-08-05 19:21:11 +07:00

80 lines
2.9 KiB
Bash

#!/usr/bin/env bash
# Backup-restore-övning (hardening-checklistan: "genomfört och protokollfört, kvartalsvis").
# Kör: DATABASE_URL=postgres://… ./infrastructure/deployment/backup-restore-test.sh
#
# Gör: logisk dump → återställ till temporär databas → jämför radantal per tabell
# → skriv protokoll → städa. Avslutar med exitkod 1 vid avvikelse.
set -euo pipefail
DATABASE_URL="${DATABASE_URL:?Sätt DATABASE_URL}"
# Roll med CREATEDB för test-databasen (RDS master/operatör). Faller tillbaka på DATABASE_URL.
ADMIN_URL="${ADMIN_DATABASE_URL:-$DATABASE_URL}"
STAMP=$(date +%Y%m%d_%H%M%S)
WORKDIR="${BACKUP_DIR:-/tmp/backup-restore-test}"
DUMP="$WORKDIR/dump-$STAMP.pgdump"
RESTORE_DB="restore_test_$STAMP"
PROTOKOLL="$WORKDIR/protokoll-$STAMP.md"
mkdir -p "$WORKDIR"
# Härled anslutning utan databasnamn för att kunna skapa/droppa test-databasen.
BASE_URL="${DATABASE_URL%/*}"
ADMIN_BASE_URL="${ADMIN_URL%/*}"
echo "==> 1/5 Dumpar databasen"
pg_dump "$DATABASE_URL" --format=custom --file="$DUMP"
SIZE=$(du -h "$DUMP" | cut -f1)
echo "==> 2/5 Skapar temporär databas $RESTORE_DB"
psql "$ADMIN_BASE_URL/postgres" -qc "CREATE DATABASE $RESTORE_DB" 2>/dev/null \
|| psql "$ADMIN_URL" -qc "CREATE DATABASE $RESTORE_DB"
cleanup() {
psql "$ADMIN_BASE_URL/postgres" -qc "DROP DATABASE IF EXISTS $RESTORE_DB" 2>/dev/null \
|| psql "$ADMIN_URL" -qc "DROP DATABASE IF EXISTS $RESTORE_DB" || true
}
trap cleanup EXIT
echo "==> 3/5 Återställer till $RESTORE_DB"
# Återställ som admin-rollen (äger test-databasen, får skapa extensions).
pg_restore --dbname="$ADMIN_BASE_URL/$RESTORE_DB" --no-owner --no-privileges "$DUMP"
echo "==> 4/5 Jämför radantal per tabell"
COUNT_SQL="SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY relname"
ROWS_SQL="SELECT string_agg(format('%s:%s', t.tablename, (xpath('/row/cnt/text()', query_to_xml(format('SELECT count(*) AS cnt FROM %I', t.tablename), false, true, '')))[1]::text), E'\n' ORDER BY t.tablename) FROM pg_tables t WHERE schemaname='public'"
ORIG=$(psql "$DATABASE_URL" -tA -c "$ROWS_SQL")
REST=$(psql "$ADMIN_BASE_URL/$RESTORE_DB" -tA -c "$ROWS_SQL")
STATUS="GODKÄND"
DIFF_OUT=""
if [ "$ORIG" != "$REST" ]; then
STATUS="UNDERKÄND"
DIFF_OUT=$(diff <(echo "$ORIG") <(echo "$REST") || true)
fi
echo "==> 5/5 Skriver protokoll: $PROTOKOLL"
TABLES=$(echo "$ORIG" | wc -l)
TOTAL=$(echo "$ORIG" | awk -F: '{s+=$2} END {print s}')
{
echo "# Backup-restore-protokoll $STAMP"
echo
echo "| Fält | Värde |"
echo "| ---- | ----- |"
echo "| Resultat | **$STATUS** |"
echo "| Dumpstorlek | $SIZE |"
echo "| Tabeller jämförda | $TABLES |"
echo "| Totalt antal rader | $TOTAL |"
echo "| Dump | $DUMP |"
echo
if [ -n "$DIFF_OUT" ]; then
echo '## Avvikelser'
echo '```'
echo "$DIFF_OUT"
echo '```'
else
echo "Alla tabellers radantal identiska mellan original och återställning."
fi
} > "$PROTOKOLL"
cat "$PROTOKOLL"
[ "$STATUS" = "GODKÄND" ]