Files
motovaultpro/scripts/import-database.sh
Eric Gullickson c9b756727e
All checks were successful
Deploy to Staging / Build Images (push) Successful in 3m28s
Deploy to Staging / Deploy to Staging (push) Successful in 27s
Deploy to Staging / Verify Staging (push) Successful in 5s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
fix: staging packages, image URL and database scripts
2025-12-30 20:50:52 -06:00

389 lines
11 KiB
Bash
Executable File

#!/bin/bash
set -e
# Database Import Script for MotoVaultPro
# Imports PostgreSQL database from export file
# Usage: ./scripts/import-database.sh [options] <export-file>
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
DATABASE_NAME="motovaultpro"
# Environment-based container names
CONTAINER_NAME="" # Will be set based on environment selection
ENVIRONMENT="" # production or staging
# Default values
BACKUP_EXISTING=true
DROP_EXISTING=false
CREATE_DATABASE=false
FORCE=false
# Function to print colored output
print_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_env() {
echo -e "${BLUE}[ENV]${NC} $1"
}
# Function to select environment
select_environment() {
if [ -n "$ENVIRONMENT" ]; then
# Environment already set via command line
return
fi
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE} MotoVaultPro Database Import${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo "Select environment to import to:"
echo ""
echo " 1) Production (mvp-postgres)"
echo " 2) Staging (mvp-postgres-staging)"
echo ""
read -p "Enter choice [1-2]: " ENV_CHOICE
case $ENV_CHOICE in
1)
ENVIRONMENT="production"
CONTAINER_NAME="mvp-postgres"
;;
2)
ENVIRONMENT="staging"
CONTAINER_NAME="mvp-postgres-staging"
;;
*)
print_error "Invalid choice. Please enter 1 or 2."
exit 1
;;
esac
echo ""
print_env "Selected environment: ${ENVIRONMENT}"
print_env "Container: ${CONTAINER_NAME}"
echo ""
}
# Function to set container name based on environment
set_container_from_environment() {
case $ENVIRONMENT in
production|prod)
ENVIRONMENT="production"
CONTAINER_NAME="mvp-postgres"
;;
staging|stage)
ENVIRONMENT="staging"
CONTAINER_NAME="mvp-postgres-staging"
;;
*)
print_error "Invalid environment: $ENVIRONMENT"
print_error "Valid options: production, staging"
exit 1
;;
esac
}
# Function to show usage
show_usage() {
cat << EOF
Database Import Script for MotoVaultPro
Usage: $0 [options] <export-file>
Options:
-h, --help Show this help message
-e, --env ENV Environment: production or staging (prompts if not specified)
-c, --container NAME Override container name (ignores environment selection)
-d, --database NAME Database name (default: motovaultpro)
--create-db Create database if it doesn't exist
--drop-existing Drop existing database before import (DANGER!)
--no-backup Skip backup of existing database
--force Skip confirmation prompts
-f, --format FORMAT Import format: sql, custom, directory (auto-detected if not specified)
Environments:
production (prod) Uses container: mvp-postgres
staging (stage) Uses container: mvp-postgres-staging
Examples:
# Interactive environment selection
$0 database-exports/backup.sql.gz
# Import to production
$0 --env production database-exports/backup.sql.gz
# Import to staging
$0 --env staging database-exports/backup.sql.gz
# Import with database recreation to staging
$0 -e staging --drop-existing --create-db backup.sql
# Import custom format to production
$0 --env prod --format custom backup.dump
Safety Features:
- Creates backup of existing database by default
- Requires confirmation before destructive operations
- Validates export file before import
- Supports rollback on failure
EOF
exit 0
}
# Parse command line arguments
CONTAINER_OVERRIDE=""
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_usage
;;
-e|--env)
ENVIRONMENT="$2"
shift 2
;;
-c|--container)
CONTAINER_OVERRIDE="$2"
shift 2
;;
-d|--database)
DATABASE_NAME="$2"
shift 2
;;
--create-db)
CREATE_DATABASE=true
shift
;;
--drop-existing)
DROP_EXISTING=true
shift
;;
--no-backup)
BACKUP_EXISTING=false
shift
;;
--force)
FORCE=true
shift
;;
-f|--format)
IMPORT_FORMAT="$2"
shift 2
;;
-*)
print_error "Unknown option: $1"
show_usage
;;
*)
IMPORT_FILE="$1"
shift
;;
esac
done
# Validate import file
if [ -z "$IMPORT_FILE" ]; then
print_error "No import file specified"
show_usage
fi
if [ ! -e "$IMPORT_FILE" ]; then
print_error "Import file does not exist: $IMPORT_FILE"
exit 1
fi
# Handle environment selection
if [ -n "$CONTAINER_OVERRIDE" ]; then
# Container explicitly specified, use it directly
CONTAINER_NAME="$CONTAINER_OVERRIDE"
ENVIRONMENT="custom"
print_info "Using custom container: $CONTAINER_NAME"
elif [ -n "$ENVIRONMENT" ]; then
# Environment specified via command line
set_container_from_environment
else
# No environment specified, prompt user
select_environment
fi
# Auto-detect format if not specified
if [ -z "$IMPORT_FORMAT" ]; then
if [[ "$IMPORT_FILE" == *.sql.gz ]]; then
IMPORT_FORMAT="sql-compressed"
elif [[ "$IMPORT_FILE" == *.sql ]]; then
IMPORT_FORMAT="sql"
elif [[ "$IMPORT_FILE" == *.dump ]]; then
IMPORT_FORMAT="custom"
elif [ -d "$IMPORT_FILE" ]; then
IMPORT_FORMAT="directory"
else
print_error "Cannot auto-detect format. Please specify with --format"
exit 1
fi
print_info "Auto-detected format: $IMPORT_FORMAT"
fi
# Check if container is running
print_info "Checking if PostgreSQL container is running..."
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
print_error "PostgreSQL container '${CONTAINER_NAME}' is not running"
print_info "Start it with: docker compose up -d mvp-postgres"
exit 1
fi
# Check if database exists
print_info "Checking if database exists..."
DB_EXISTS=$(docker exec "$CONTAINER_NAME" psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DATABASE_NAME'" 2>/dev/null || echo "0")
if [ "$DB_EXISTS" = "1" ]; then
print_warn "Database '$DATABASE_NAME' already exists"
if [ "$BACKUP_EXISTING" = true ] && [ "$DROP_EXISTING" = false ]; then
BACKUP_FILE="${PROJECT_ROOT}/database-exports/${DATABASE_NAME}_backup_$(date +%Y%m%d_%H%M%S).sql.gz"
print_info "Creating backup: $BACKUP_FILE"
mkdir -p "$(dirname "$BACKUP_FILE")"
docker exec "$CONTAINER_NAME" pg_dump -U postgres -d "$DATABASE_NAME" | gzip > "$BACKUP_FILE"
print_info "Backup created successfully"
fi
if [ "$DROP_EXISTING" = true ]; then
if [ "$FORCE" = false ]; then
echo ""
print_warn "WARNING: This will DROP the existing database '$DATABASE_NAME'"
print_warn "All data will be permanently deleted!"
echo ""
read -p "Are you sure you want to continue? (type 'yes' to confirm): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
print_info "Import cancelled"
exit 0
fi
fi
print_info "Dropping existing database..."
docker exec "$CONTAINER_NAME" psql -U postgres -c "DROP DATABASE IF EXISTS $DATABASE_NAME" || {
print_error "Failed to drop database"
exit 1
}
CREATE_DATABASE=true
fi
elif [ "$CREATE_DATABASE" = false ]; then
print_error "Database '$DATABASE_NAME' does not exist. Use --create-db to create it"
exit 1
fi
# Create database if needed
if [ "$CREATE_DATABASE" = true ]; then
print_info "Creating database '$DATABASE_NAME'..."
docker exec "$CONTAINER_NAME" psql -U postgres -c "CREATE DATABASE $DATABASE_NAME" || {
print_error "Failed to create database"
exit 1
}
fi
# Import based on format
print_info "Starting database import..."
print_info "Environment: $ENVIRONMENT"
print_info "Container: $CONTAINER_NAME"
print_info "File: $IMPORT_FILE"
print_info "Format: $IMPORT_FORMAT"
print_info "Database: $DATABASE_NAME"
case $IMPORT_FORMAT in
sql)
print_info "Importing SQL dump..."
docker exec -i "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" < "$IMPORT_FILE" || {
print_error "Import failed"
exit 1
}
;;
sql-compressed)
print_info "Importing compressed SQL dump..."
gunzip -c "$IMPORT_FILE" | docker exec -i "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" || {
print_error "Import failed"
exit 1
}
;;
custom)
print_info "Importing custom format dump..."
# Copy file into container
docker cp "$IMPORT_FILE" "${CONTAINER_NAME}:/tmp/restore.dump" || {
print_error "Failed to copy file to container"
exit 1
}
# Restore
docker exec "$CONTAINER_NAME" pg_restore -U postgres -d "$DATABASE_NAME" -c /tmp/restore.dump || {
print_error "Import failed"
docker exec "$CONTAINER_NAME" rm -f /tmp/restore.dump
exit 1
}
# Cleanup
docker exec "$CONTAINER_NAME" rm -f /tmp/restore.dump
;;
directory)
print_info "Importing directory format dump..."
# Copy directory into container
docker cp "$IMPORT_FILE" "${CONTAINER_NAME}:/tmp/restore_dir" || {
print_error "Failed to copy directory to container"
exit 1
}
# Restore
docker exec "$CONTAINER_NAME" pg_restore -U postgres -d "$DATABASE_NAME" -c /tmp/restore_dir || {
print_error "Import failed"
docker exec "$CONTAINER_NAME" rm -rf /tmp/restore_dir
exit 1
}
# Cleanup
docker exec "$CONTAINER_NAME" rm -rf /tmp/restore_dir
;;
*)
print_error "Unknown import format: $IMPORT_FORMAT"
exit 1
;;
esac
# Verify import
print_info "Verifying import..."
TABLE_COUNT=$(docker exec "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public'")
print_info "Imported $TABLE_COUNT tables"
# Summary
echo ""
print_info "==============================================="
print_info "Database Import Complete!"
print_info "==============================================="
print_info "Environment: $ENVIRONMENT"
print_info "Container: $CONTAINER_NAME"
print_info "Database: $DATABASE_NAME"
print_info "Tables: $TABLE_COUNT"
if [ "$BACKUP_EXISTING" = true ] && [ -n "$BACKUP_FILE" ]; then
print_info "Backup: $BACKUP_FILE"
fi
echo ""
print_info "Database is ready to use!"
echo ""