#!/bin/bash # Failback to Primary Region Script for Gravl set -euo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} INFO: $*" >&2; } log_success() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} SUCCESS: $*" >&2; } log_warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} WARN: $*" >&2; } log_error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} ERROR: $*" >&2; } PRIMARY_REGION="eu-north-1" SECONDARY_REGION="us-east-1" PRIMARY_NAMESPACE="gravl-prod" SECONDARY_NAMESPACE="gravl-prod" BACKUP_FILE="" DRY_RUN=false print_help() { cat << 'HELP' Failback to Primary Region Script Usage: ./failback.sh [OPTIONS] Options: --backup-file FILE Backup to restore from (default: latest) --dry-run Show what would be done without doing it --confirm Skip confirmation prompt --help Show this help message HELP } parse_args() { while [[ $# -gt 0 ]]; do case $1 in --backup-file) BACKUP_FILE="$2"; shift 2 ;; --dry-run) DRY_RUN=true; shift ;; --confirm) CONFIRM=true; shift ;; --help) print_help; exit 0 ;; *) log_error "Unknown option: $1"; exit 1 ;; esac done } confirm_failback() { log_warn "FAILBACK OPERATION - CRITICAL ACTION" log_warn "Primary Region: $PRIMARY_REGION" log_warn "Secondary Region: $SECONDARY_REGION" echo "" read -p "Type 'failback-confirm' to proceed: " confirmation if [ "$confirmation" != "failback-confirm" ]; then log_error "Failback cancelled" exit 1 fi } backup_secondary() { log_info "Backing up current secondary before failback..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would backup secondary" return 0 fi # Call backup script on secondary # /workspace/gravl/scripts/backup.sh --region us-east-1 log_success "Secondary backed up" } restore_primary() { log_info "Restoring primary from backup..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would restore primary" return 0 fi # /workspace/gravl/scripts/restore.sh --backup-file "$BACKUP_FILE" --validate log_success "Primary restored" } resync_secondary() { log_info "Setting secondary as replica of primary..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would resync secondary" return 0 fi # kubectl exec gravl-db-0 -n gravl-prod --kubeconfig=$SECONDARY_KUBECONFIG -- \ # pg_basebackup -h gravl-db.gravl-prod.eu-north-1.svc.cluster.local \ # -D /var/lib/postgresql/data/pgdata -U gravl_replication log_success "Secondary resynchronized" } update_dns_to_primary() { log_info "Updating DNS to point to primary..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would update DNS" return 0 fi # aws route53 change-resource-record-sets ... log_success "DNS updated to primary" } restart_applications() { log_info "Restarting applications..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would restart applications" return 0 fi # kubectl rollout restart deployment/gravl-backend -n gravl-prod # kubectl rollout restart deployment/gravl-frontend -n gravl-prod log_success "Applications restarted" } main() { log_info "==========================================" log_info "Gravl Database Failback Script" log_info "==========================================" parse_args "$@" confirm_failback backup_secondary restore_primary resync_secondary update_dns_to_primary restart_applications log_success "Failback completed! Primary is active again." } main "$@"