#!/bin/bash # ===================================================== # ERP GENERIC - PostgreSQL Restore Script # Restores database from backup file # ===================================================== set -euo pipefail # Usage if [ $# -lt 1 ]; then echo "Usage: $0 [--target=] [--no-prompt]" echo "" echo "Examples:" echo " $0 /backups/postgres/full_20251124_020000.dump" echo " $0 /backups/postgres/full_20251124_020000.dump --target=erp_generic_staging" echo " $0 /backups/postgres/full_20251124_020000.dump --no-prompt" echo "" exit 1 fi BACKUP_FILE="$1" TARGET_DB="${2:-erp_generic}" NO_PROMPT=false # Parse arguments for arg in "$@"; do case $arg in --target=*) TARGET_DB="${arg#*=}" shift ;; --no-prompt) NO_PROMPT=true shift ;; esac done DB_HOST="${POSTGRES_HOST:-postgres}" DB_USER="${POSTGRES_USER:-erp_user}" PGPASSWORD="${POSTGRES_PASSWORD}" export PGPASSWORD # Logging LOG_FILE="/var/log/erp-generic/restore.log" exec > >(tee -a "$LOG_FILE") exec 2>&1 echo "===== PostgreSQL Restore Started at $(date) =====" echo "Backup file: $BACKUP_FILE" echo "Target database: $TARGET_DB" # Verify backup file exists if [ ! -f "$BACKUP_FILE" ]; then echo "✗ Backup file not found: $BACKUP_FILE" exit 1 fi # Verify checksum if exists if [ -f "${BACKUP_FILE}.md5" ]; then echo "Verifying backup integrity..." md5sum -c "${BACKUP_FILE}.md5" if [ $? -ne 0 ]; then echo "✗ Backup integrity check failed!" exit 1 fi echo "✓ Backup integrity verified" fi # Safety prompt (unless --no-prompt) if [ "$NO_PROMPT" = false ]; then echo "" echo "⚠️ WARNING: This will OVERWRITE all data in database '$TARGET_DB'" echo "⚠️ Make sure you have a recent backup before proceeding!" echo "" read -p "Are you sure you want to continue? (yes/no): " -r if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then echo "Restore cancelled by user." exit 0 fi fi # Create safety backup of target database (if not staging/dev) if [[ ! "$TARGET_DB" =~ (staging|dev|test) ]]; then echo "Creating safety backup of $TARGET_DB before restore..." SAFETY_BACKUP="/backups/postgres/safety_${TARGET_DB}_$(date +%Y%m%d_%H%M%S).dump" pg_dump -h "$DB_HOST" -U "$DB_USER" -Fc -d "$TARGET_DB" -f "$SAFETY_BACKUP" echo "✓ Safety backup created: $SAFETY_BACKUP" fi # Terminate active connections to target database echo "Terminating active connections to $TARGET_DB..." psql -h "$DB_HOST" -U "$DB_USER" -d postgres < pg_backend_pid(); SQL # Restore database echo "Restoring database from $BACKUP_FILE..." pg_restore -h "$DB_HOST" -U "$DB_USER" -d "$TARGET_DB" --clean --if-exists --verbose "$BACKUP_FILE" if [ $? -eq 0 ]; then echo "✓ Database restored successfully" else echo "✗ Restore failed!" exit 1 fi # Verify restore echo "Verifying restore..." TABLE_COUNT=$(psql -h "$DB_HOST" -U "$DB_USER" -d "$TARGET_DB" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema');") USER_COUNT=$(psql -h "$DB_HOST" -U "$DB_USER" -d "$TARGET_DB" -tAc "SELECT COUNT(*) FROM auth.users;" 2>/dev/null || echo "N/A") echo "Tables restored: $TABLE_COUNT" echo "Users in auth.users: $USER_COUNT" # Rebuild statistics echo "Rebuilding database statistics..." psql -h "$DB_HOST" -U "$DB_USER" -d "$TARGET_DB" -c "ANALYZE;" echo "✓ Statistics rebuilt" # Send notification (optional) if [ -n "${SLACK_WEBHOOK_URL:-}" ]; then curl -X POST "$SLACK_WEBHOOK_URL" \ -H 'Content-Type: application/json' \ -d "{\"text\": \"✅ PostgreSQL restore completed\n• Database: $TARGET_DB\n• From backup: $(basename $BACKUP_FILE)\n• Tables restored: $TABLE_COUNT\n• Restored by: $USER\"}" fi echo "===== PostgreSQL Restore Completed at $(date) =====" echo "" echo "Next steps:" echo "1. Verify application functionality" echo "2. Run smoke tests: npm run test:smoke" echo "3. Check logs for errors: docker-compose logs -f backend" echo "4. Notify team that restore is complete" echo "" # Exit successfully exit 0