#!/bin/bash # Failover to Secondary 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" SECONDARY_CLUSTER="gravl-us-secondary" SECONDARY_NAMESPACE="gravl-prod" SECONDARY_DB_POD="gravl-db-0" DRY_RUN=false print_help() { cat << 'HELP' Failover to Secondary Region Script Usage: ./failover.sh [OPTIONS] Options: --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 --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_failover() { log_warn "FAILOVER OPERATION - CRITICAL ACTION" log_warn "Primary Region: $PRIMARY_REGION" log_warn "Secondary Region: $SECONDARY_REGION" echo "" read -p "Type 'failover-confirm' to proceed: " confirmation if [ "$confirmation" != "failover-confirm" ]; then log_error "Failover cancelled" exit 1 fi } check_secondary_health() { log_info "Checking secondary region health..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would check secondary health" return 0 fi # This would use secondary kubeconfig # kubectl get pod "$SECONDARY_DB_POD" -n "$SECONDARY_NAMESPACE" --kubeconfig=$SECONDARY_KUBECONFIG log_info "Secondary health check passed (placeholder)" } promote_secondary() { log_info "Promoting secondary database to primary..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would promote secondary replica" return 0 fi # kubectl exec "$SECONDARY_DB_POD" -n "$SECONDARY_NAMESPACE" --kubeconfig=$SECONDARY_KUBECONFIG -- \ # pg_ctl promote -D /var/lib/postgresql/data/pgdata log_success "Secondary promoted to primary" } update_dns() { log_info "Updating DNS records..." if [ "$DRY_RUN" = true ]; then log_info "[DRY RUN] Would update Route 53 DNS" return 0 fi # aws route53 change-resource-record-sets \ # --hosted-zone-id $HOSTED_ZONE_ID \ # --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"db.gravl.com","Type":"CNAME","TTL":300,"ResourceRecords":[{"Value":"gravl-db.gravl-prod.us-east-1.svc.cluster.local"}]}}]}' log_success "DNS updated" } restart_applications() { log_info "Restarting applications with new connection string..." 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 Failover Script" log_info "==========================================" parse_args "$@" confirm_failover check_secondary_health promote_secondary update_dns restart_applications log_success "Failover completed! Secondary is now primary." } main "$@"