blob: 1791eb24e8065f351d35fdabb822d4c7321b935b [file]
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# upgrade_postgres_simple.sh - Upgrade Hamilton UI from PostgreSQL 12 to 18
# Uses Django's dumpdata/loaddata for safe, validated migration
set -euo pipefail
BACKUP_FILE="hamilton_migration_$(date +%Y%m%d_%H%M%S).json"
echo "Hamilton UI PostgreSQL 12 → 18 Migration"
echo "========================================="
echo ""
echo "This script will:"
echo " 1. Export your Hamilton data using Django"
echo " 2. Stop containers and remove PostgreSQL 12 volume"
echo " 3. Start PostgreSQL 18 containers (with new volume structure)"
echo " 4. Restore your Hamilton data"
echo ""
echo "Note: PostgreSQL 18 uses a new data directory structure."
echo "The old volume at /var/lib/postgresql/data is incompatible."
echo "This script will create a new volume at /var/lib/postgresql."
echo ""
# Check if docker compose or docker-compose is available
if command -v docker-compose &> /dev/null; then
DOCKER_COMPOSE="docker-compose"
elif docker compose version &> /dev/null 2>&1; then
DOCKER_COMPOSE="docker compose"
else
echo "Error: Neither 'docker compose' nor 'docker-compose' found"
exit 1
fi
# Check if containers are running
if ! $DOCKER_COMPOSE ps --services --filter "status=running" | grep -q "backend"; then
echo "Error: Hamilton UI containers not running"
echo "Start them first: ./run.sh"
exit 1
fi
# Check PostgreSQL version
echo "Checking current PostgreSQL version..."
PG_VERSION=$($DOCKER_COMPOSE exec -T db psql -U postgres -d postgres -At -c "SHOW server_version;" | cut -d. -f1)
if [ "$PG_VERSION" -ge 18 ]; then
echo "Already on PostgreSQL $PG_VERSION. No migration needed."
exit 0
fi
if [ "$PG_VERSION" -lt 12 ]; then
echo "Error: PostgreSQL $PG_VERSION detected"
echo "This script handles PostgreSQL 12+ → 18"
echo "Manual upgrade required for older versions"
exit 1
fi
echo "Current version: PostgreSQL $PG_VERSION"
echo ""
read -p "Continue with migration? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "Aborted."
exit 0
fi
echo ""
echo "================================================================"
echo "Step 1: Exporting Hamilton data"
echo "================================================================"
echo ""
# Use the backup script
if ! ./backup_hamilton_data.sh "$BACKUP_FILE"; then
echo "Error: Data export failed"
exit 1
fi
# Verify backup was created and has content
if [ ! -s "$BACKUP_FILE" ]; then
echo "Error: Backup file is empty or missing"
exit 1
fi
RECORD_COUNT=$(uv run python -c "import json; print(len(json.load(open('$BACKUP_FILE'))))")
if [ "$RECORD_COUNT" -eq 0 ]; then
echo "Warning: Backup contains 0 records"
echo "This is OK if you have no data yet, but unexpected if you've been using Hamilton UI"
read -p "Continue anyway? (yes/no): " CONTINUE
if [ "$CONTINUE" != "yes" ]; then
echo "Aborted. Backup saved at: $BACKUP_FILE"
exit 0
fi
fi
echo ""
echo "================================================================"
echo "Step 2: Removing PostgreSQL 12 data"
echo "================================================================"
echo ""
echo "⚠️ WARNING: About to delete PostgreSQL 12 data volume"
echo " Backup: $BACKUP_FILE ($RECORD_COUNT records)"
echo ""
read -p "Type 'DELETE' to confirm: " CONFIRM_DELETE
if [ "$CONFIRM_DELETE" != "DELETE" ]; then
echo "Aborted. Your backup is saved at: $BACKUP_FILE"
exit 0
fi
echo ""
echo "Stopping containers..."
$DOCKER_COMPOSE down
echo "Removing PostgreSQL 12 volume..."
if docker volume rm ui_postgres_data; then
echo "✓ Volume removed"
else
echo "Error: Could not remove volume"
echo "It may not exist or be in use by another container"
docker volume ls | grep postgres
exit 1
fi
echo ""
echo "================================================================"
echo "Step 3: Starting PostgreSQL 18"
echo "================================================================"
echo ""
if [ ! -f "./run.sh" ]; then
echo "Error: ./run.sh not found"
echo "Run this script from the ui/ directory"
exit 1
fi
echo "Building and starting containers..."
echo "(This may take a few minutes on first build)"
echo ""
if ! ./run.sh --build; then
echo ""
echo "Error: Failed to start containers"
echo "Your backup is safe at: $BACKUP_FILE"
echo ""
echo "To retry manually:"
echo " 1. Fix any Docker issues"
echo " 2. Run: ./run.sh --build"
echo " 3. Run: ./restore_hamilton_data.sh $BACKUP_FILE"
exit 1
fi
# Wait for backend to be ready
echo ""
echo "Waiting for backend to be ready..."
MAX_RETRIES=30
RETRY_COUNT=0
until $DOCKER_COMPOSE exec -T backend python manage.py migrate --check > /dev/null 2>&1; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "Error: Backend not ready after $MAX_RETRIES attempts"
echo "Your backup is safe at: $BACKUP_FILE"
echo ""
echo "To restore manually:"
echo " 1. Wait for containers to be healthy: $DOCKER_COMPOSE ps"
echo " 2. Run: ./restore_hamilton_data.sh $BACKUP_FILE"
exit 1
fi
echo " Waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "✓ Backend ready"
# Check new PostgreSQL version
NEW_PG_VERSION=$($DOCKER_COMPOSE exec -T db psql -U postgres -d postgres -At -c "SHOW server_version;" | cut -d. -f1)
echo "✓ PostgreSQL $NEW_PG_VERSION running"
echo ""
echo "================================================================"
echo "Step 4: Restoring Hamilton data"
echo "================================================================"
echo ""
# Copy backup into backend container so loaddata can access it
echo "Copying backup into container..."
$DOCKER_COMPOSE cp "$BACKUP_FILE" backend:/tmp/restore.json
# Use the restore script
if ! $DOCKER_COMPOSE exec -T backend bash -c "cd /code && python manage.py loaddata /tmp/restore.json"; then
echo ""
echo "Error: Data restore failed"
echo "Your backup is safe at: $BACKUP_FILE"
echo ""
echo "To retry manually:"
echo " ./restore_hamilton_data.sh $BACKUP_FILE"
exit 1
fi
echo "✓ Data restored"
# Verify
echo ""
echo "Verifying migration..."
POST_COUNTS=$($DOCKER_COMPOSE exec -T backend python manage.py shell <<'PYTHON'
from trackingserver_base.models import Project
from trackingserver_run_tracking.models import DAGRun
print(f"{Project.objects.count()},{DAGRun.objects.count()}")
PYTHON
)
IFS=',' read -r PROJECTS RUNS <<< "$POST_COUNTS"
echo " Projects: $PROJECTS"
echo " Runs: $RUNS"
echo ""
echo "================================================================"
echo "✅ Migration Complete!"
echo "================================================================"
echo ""
echo "Your Hamilton UI has been upgraded from PostgreSQL $PG_VERSION to $NEW_PG_VERSION"
echo ""
echo "Next steps:"
echo " 1. Navigate to http://localhost:8242"
echo " 2. Verify your projects and runs appear"
echo " 3. If everything looks good, delete the backup:"
echo " rm $BACKUP_FILE"
echo ""
echo "If you encounter issues:"
echo " - Backup file: $BACKUP_FILE"
echo " - Check logs: $DOCKER_COMPOSE logs"
echo " - Get help: https://github.com/apache/hamilton/issues"