Database Tooling
This commit is contained in:
286
scripts/import-database.sh
Executable file
286
scripts/import-database.sh
Executable file
@@ -0,0 +1,286 @@
|
||||
#!/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'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
CONTAINER_NAME="mvp-postgres"
|
||||
DATABASE_NAME="motovaultpro"
|
||||
|
||||
# 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"
|
||||
}
|
||||
|
||||
# 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
|
||||
-c, --container NAME Container name (default: mvp-postgres)
|
||||
-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)
|
||||
|
||||
Examples:
|
||||
# Import a standard SQL dump
|
||||
$0 database-exports/motovaultpro_export_20250101_120000.sql.gz
|
||||
|
||||
# Import with database recreation
|
||||
$0 --drop-existing --create-db backup.sql
|
||||
|
||||
# Import custom format
|
||||
$0 --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
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_usage
|
||||
;;
|
||||
-c|--container)
|
||||
CONTAINER_NAME="$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
|
||||
|
||||
# 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 "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 "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 ""
|
||||
Reference in New Issue
Block a user