#!/bin/bash set -Eeuo pipefail # Configuration TARGET_ENV="${1:-stsharedservices-dev}" DBNAME="${2:-geco}" POD_NAME="${3:-stpgclusterdev-1}" CONTAINER_NAME="${4:-postgres}" BACKUP_FILE="${5:-.}" DROP_IF_EXISTS="${6:-true}" DB_USER="${7:-${PGUSER:-postgres}}" DB_PASSWORD="${8:-${PGPASSWORD:-}}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Logging functions log() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $*" } error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR:${NC} $*" >&2 exit 1 } warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARN:${NC} $*" } info() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] INFO:${NC} $*" } log "Inizio restore database PostgreSQL" log "Namespace target: ${TARGET_ENV}" log "Pod target: ${POD_NAME}" log "Database: ${DBNAME}" log "DB user: ${DB_USER}" log "File backup: ${BACKUP_FILE}" # Validate backup file exists if [ ! -f "${BACKUP_FILE}" ]; then error "File di backup non trovato: ${BACKUP_FILE}" fi FILE_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1) log "Dimensione file backup: ${FILE_SIZE}" # Determine if backup is compressed if [[ "${BACKUP_FILE}" == *.gz ]]; then IS_COMPRESSED=true info "Backup compresso (gzip) rilevato" else IS_COMPRESSED=false info "Backup non compresso rilevato" fi # Check if namespace exists if ! kubectl get namespace "${TARGET_ENV}" &>/dev/null; then error "Namespace '${TARGET_ENV}' non trovato" fi # Check if pod exists if ! kubectl get pod "${POD_NAME}" -n "${TARGET_ENV}" &>/dev/null; then error "Pod '${POD_NAME}' non trovato nel namespace '${TARGET_ENV}'" fi # Check if pod is running POD_STATUS=$(kubectl get pod "${POD_NAME}" -n "${TARGET_ENV}" -o jsonpath='{.status.phase}') if [ "${POD_STATUS}" != "Running" ]; then error "Pod '${POD_NAME}' non è in stato Running (stato attuale: ${POD_STATUS})" fi # Check database connectivity info "Verifica connessione al database..." if ! kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" pg_isready -U "${DB_USER}" -d "${DBNAME}" &>/dev/null; then error "Impossibile connettersi a PostgreSQL nel pod '${POD_NAME}'" fi log "Connessione al database verificata" # Drop database if requested if [ "${DROP_IF_EXISTS}" = "true" ]; then warn "Elimino il database '${DBNAME}' se esiste..." kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -c "DROP DATABASE IF EXISTS \"${DBNAME}\" WITH (FORCE);" 2>/dev/null || warn "Database non esiste o elimina non è riuscita" info "Creo nuovo database '${DBNAME}'..." kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -c "CREATE DATABASE \"${DBNAME}\";" || error "Impossibile creare il database '${DBNAME}'" fi log "Inizio restore del database..." # Execute restore if [ "${IS_COMPRESSED}" = "true" ]; then info "Decompressione e restore in corso..." gunzip -c "${BACKUP_FILE}" | kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" pg_restore -U "${DB_USER}" -d "${DBNAME}" --no-owner -v 2>&1 | grep -E "(NOTICE|ERROR|completed)" || true else info "Restore da file plain SQL in corso..." cat "${BACKUP_FILE}" | kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -d "${DBNAME}" -v ON_ERROR_STOP=1 2>&1 | grep -E "(NOTICE|ERROR|INSERT|CREATE)" | tail -20 || true fi log "Restore completato" info "Allineo owner delle tabelle al proprietario del database target..." TARGET_DB_OWNER=$(kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -d postgres -t -A -c "SELECT pg_get_userbyid(datdba) FROM pg_database WHERE datname='${DBNAME}';") if [ -z "${TARGET_DB_OWNER}" ]; then error "Impossibile determinare l'owner del database '${DBNAME}'" fi kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -d "${DBNAME}" -v ON_ERROR_STOP=1 -c "DO \$\$ DECLARE r RECORD; BEGIN FOR r IN SELECT n.nspname, c.relname FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r', 'p') AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND n.nspname NOT LIKE 'pg_toast%' LOOP EXECUTE format('ALTER TABLE %I.%I OWNER TO %I', r.nspname, r.relname, '${TARGET_DB_OWNER}'); END LOOP; END \$\$;" >/dev/null log "Owner tabelle allineato a '${TARGET_DB_OWNER}'" # Verify restore success info "Verifica integrità database..." TABLE_COUNT=$(kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -d "${DBNAME}" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public';" 2>/dev/null || echo "0") if [ "${TABLE_COUNT}" -gt 0 ]; then log "✅ Restore completato con successo" log "Database '${DBNAME}' contiene ${TABLE_COUNT} tabelle" else warn "⚠️ Database '${DBNAME}' non contiene tabelle pubbliche (potrebbe essere empty)" fi # Get database size DB_SIZE=$(kubectl exec -i "${POD_NAME}" \ -c "${CONTAINER_NAME}" \ -n "${TARGET_ENV}" \ -- env "PGPASSWORD=${DB_PASSWORD}" psql -U "${DB_USER}" -t -c "SELECT pg_size_pretty(pg_database_size('${DBNAME}'));" 2>/dev/null || echo "N/A") log "Dimensione database: ${DB_SIZE}" log "✅ Restore completato con successo"