feat(deploy): merge Phase 5a deployment configuration
Complete containerized deployment system with Docker/Podman support. Key features: - Multi-stage Dockerfile with Python 3.11-slim base - Docker Compose configurations for production and development - Nginx reverse proxy with security headers and rate limiting - Systemd service units for Docker, Podman, and docker-compose - Backup/restore scripts with integrity verification - Podman compatibility (ADR-009) All tests pass including Podman verification testing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
156
deployment/scripts/backup.sh
Executable file
156
deployment/scripts/backup.sh
Executable file
@@ -0,0 +1,156 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Gondulf SQLite Database Backup Script
|
||||
# Compatible with both Podman and Docker (auto-detects)
|
||||
#
|
||||
# Usage: ./backup.sh [backup_dir]
|
||||
#
|
||||
# Environment Variables:
|
||||
# GONDULF_DATABASE_URL - Database URL (default: sqlite:////data/gondulf.db)
|
||||
# BACKUP_DIR - Backup directory (default: ./backups)
|
||||
# BACKUP_RETENTION_DAYS - Days to keep backups (default: 7)
|
||||
# COMPRESS_BACKUPS - Compress backups with gzip (default: true)
|
||||
# CONTAINER_NAME - Container name (default: gondulf)
|
||||
# CONTAINER_ENGINE - Force specific engine: podman or docker (default: auto-detect)
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Auto-detect container engine
|
||||
detect_container_engine() {
|
||||
if [ -n "${CONTAINER_ENGINE:-}" ]; then
|
||||
echo "$CONTAINER_ENGINE"
|
||||
elif command -v podman &> /dev/null; then
|
||||
echo "podman"
|
||||
elif command -v docker &> /dev/null; then
|
||||
echo "docker"
|
||||
else
|
||||
echo "ERROR: Neither podman nor docker found" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ENGINE=$(detect_container_engine)
|
||||
CONTAINER_NAME="${CONTAINER_NAME:-gondulf}"
|
||||
|
||||
echo "========================================="
|
||||
echo "Gondulf Database Backup"
|
||||
echo "========================================="
|
||||
echo "Container engine: $ENGINE"
|
||||
echo "Container name: $CONTAINER_NAME"
|
||||
echo ""
|
||||
|
||||
# Configuration
|
||||
DATABASE_URL="${GONDULF_DATABASE_URL:-sqlite:////data/gondulf.db}"
|
||||
BACKUP_DIR="${1:-${BACKUP_DIR:-./backups}}"
|
||||
RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-7}"
|
||||
COMPRESS="${COMPRESS_BACKUPS:-true}"
|
||||
|
||||
# Extract database path from URL (handle both 3-slash and 4-slash formats)
|
||||
if [[ "$DATABASE_URL" =~ ^sqlite:////(.+)$ ]]; then
|
||||
# Four slashes = absolute path
|
||||
DB_PATH="/${BASH_REMATCH[1]}"
|
||||
elif [[ "$DATABASE_URL" =~ ^sqlite:///(.+)$ ]]; then
|
||||
# Three slashes = relative path (assume /data in container)
|
||||
DB_PATH="/data/${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "ERROR: Invalid DATABASE_URL format: $DATABASE_URL" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Database path: $DB_PATH"
|
||||
|
||||
# Verify container is running
|
||||
if ! $ENGINE ps | grep -q "$CONTAINER_NAME"; then
|
||||
echo "ERROR: Container '$CONTAINER_NAME' is not running" >&2
|
||||
echo "Start the container first with: $ENGINE start $CONTAINER_NAME" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create backup directory on host if it doesn't exist
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Generate backup filename with timestamp
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE_CONTAINER="/tmp/gondulf_backup_${TIMESTAMP}.db"
|
||||
BACKUP_FILE_HOST="$BACKUP_DIR/gondulf_backup_${TIMESTAMP}.db"
|
||||
|
||||
echo "Starting backup..."
|
||||
echo " Backup file: $BACKUP_FILE_HOST"
|
||||
echo ""
|
||||
|
||||
# Perform backup using SQLite VACUUM INTO (safe hot backup)
|
||||
# This creates a clean, optimized copy of the database
|
||||
echo "Creating database backup (this may take a moment)..."
|
||||
$ENGINE exec "$CONTAINER_NAME" sqlite3 "$DB_PATH" "VACUUM INTO '$BACKUP_FILE_CONTAINER'" || {
|
||||
echo "ERROR: Backup failed" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Copy backup out of container to host
|
||||
echo "Copying backup to host..."
|
||||
$ENGINE cp "$CONTAINER_NAME:$BACKUP_FILE_CONTAINER" "$BACKUP_FILE_HOST" || {
|
||||
echo "ERROR: Failed to copy backup from container" >&2
|
||||
$ENGINE exec "$CONTAINER_NAME" rm -f "$BACKUP_FILE_CONTAINER" 2>/dev/null || true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Clean up temporary file in container
|
||||
$ENGINE exec "$CONTAINER_NAME" rm -f "$BACKUP_FILE_CONTAINER"
|
||||
|
||||
# Verify backup was created on host
|
||||
if [ ! -f "$BACKUP_FILE_HOST" ]; then
|
||||
echo "ERROR: Backup file was not created on host" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify backup integrity
|
||||
echo "Verifying backup integrity..."
|
||||
if sqlite3 "$BACKUP_FILE_HOST" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
echo "✓ Backup integrity check passed"
|
||||
else
|
||||
echo "ERROR: Backup integrity check failed" >&2
|
||||
rm -f "$BACKUP_FILE_HOST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Backup created successfully"
|
||||
|
||||
# Compress backup if enabled
|
||||
if [ "$COMPRESS" = "true" ]; then
|
||||
echo "Compressing backup..."
|
||||
gzip "$BACKUP_FILE_HOST"
|
||||
BACKUP_FILE_HOST="$BACKUP_FILE_HOST.gz"
|
||||
echo "✓ Backup compressed"
|
||||
fi
|
||||
|
||||
# Calculate and display backup size
|
||||
BACKUP_SIZE=$(du -h "$BACKUP_FILE_HOST" | cut -f1)
|
||||
echo "Backup size: $BACKUP_SIZE"
|
||||
|
||||
# Clean up old backups
|
||||
echo ""
|
||||
echo "Cleaning up backups older than $RETENTION_DAYS days..."
|
||||
DELETED_COUNT=$(find "$BACKUP_DIR" -name "gondulf_backup_*.db*" -type f -mtime +$RETENTION_DAYS -delete -print | wc -l)
|
||||
if [ "$DELETED_COUNT" -gt 0 ]; then
|
||||
echo "✓ Deleted $DELETED_COUNT old backup(s)"
|
||||
else
|
||||
echo " No old backups to delete"
|
||||
fi
|
||||
|
||||
# List current backups
|
||||
echo ""
|
||||
echo "Current backups:"
|
||||
if ls "$BACKUP_DIR"/gondulf_backup_*.db* 1> /dev/null 2>&1; then
|
||||
ls -lht "$BACKUP_DIR"/gondulf_backup_*.db* | head -10
|
||||
else
|
||||
echo " (none)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Backup complete!"
|
||||
echo "========================================="
|
||||
echo "Backup location: $BACKUP_FILE_HOST"
|
||||
echo "Container engine: $ENGINE"
|
||||
echo ""
|
||||
206
deployment/scripts/restore.sh
Executable file
206
deployment/scripts/restore.sh
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Gondulf SQLite Database Restore Script
|
||||
# Compatible with both Podman and Docker (auto-detects)
|
||||
#
|
||||
# Usage: ./restore.sh <backup_file>
|
||||
#
|
||||
# CAUTION: This will REPLACE the current database!
|
||||
# A safety backup will be created before restoration.
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Auto-detect container engine
|
||||
detect_container_engine() {
|
||||
if [ -n "${CONTAINER_ENGINE:-}" ]; then
|
||||
echo "$CONTAINER_ENGINE"
|
||||
elif command -v podman &> /dev/null; then
|
||||
echo "podman"
|
||||
elif command -v docker &> /dev/null; then
|
||||
echo "docker"
|
||||
else
|
||||
echo "ERROR: Neither podman nor docker found" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check arguments
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <backup_file>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0 ./backups/gondulf_backup_20251120_120000.db.gz"
|
||||
echo " $0 ./backups/gondulf_backup_20251120_120000.db"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_FILE="$1"
|
||||
ENGINE=$(detect_container_engine)
|
||||
CONTAINER_NAME="${CONTAINER_NAME:-gondulf}"
|
||||
|
||||
echo "========================================="
|
||||
echo "Gondulf Database Restore"
|
||||
echo "========================================="
|
||||
echo "Container engine: $ENGINE"
|
||||
echo "Container name: $CONTAINER_NAME"
|
||||
echo "Backup file: $BACKUP_FILE"
|
||||
echo ""
|
||||
echo "⚠️ WARNING: This will REPLACE the current database!"
|
||||
echo ""
|
||||
|
||||
# Validate backup file exists
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
echo "ERROR: Backup file not found: $BACKUP_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
DATABASE_URL="${GONDULF_DATABASE_URL:-sqlite:////data/gondulf.db}"
|
||||
|
||||
# Extract database path from URL
|
||||
if [[ "$DATABASE_URL" =~ ^sqlite:////(.+)$ ]]; then
|
||||
DB_PATH="/${BASH_REMATCH[1]}"
|
||||
elif [[ "$DATABASE_URL" =~ ^sqlite:///(.+)$ ]]; then
|
||||
DB_PATH="/data/${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "ERROR: Invalid DATABASE_URL format: $DATABASE_URL" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Database path in container: $DB_PATH"
|
||||
|
||||
# Check if container is running
|
||||
CONTAINER_RUNNING=false
|
||||
if $ENGINE ps | grep -q "$CONTAINER_NAME"; then
|
||||
CONTAINER_RUNNING=true
|
||||
echo "Container status: running"
|
||||
echo ""
|
||||
echo "⚠️ Container is running. It will be stopped during restoration."
|
||||
read -p "Continue? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Restore cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Stopping container..."
|
||||
$ENGINE stop "$CONTAINER_NAME"
|
||||
else
|
||||
echo "Container status: stopped"
|
||||
fi
|
||||
|
||||
# Decompress if needed
|
||||
TEMP_FILE=""
|
||||
RESTORE_FILE=""
|
||||
if [[ "$BACKUP_FILE" == *.gz ]]; then
|
||||
echo "Decompressing backup..."
|
||||
TEMP_FILE=$(mktemp)
|
||||
gunzip -c "$BACKUP_FILE" > "$TEMP_FILE"
|
||||
RESTORE_FILE="$TEMP_FILE"
|
||||
echo "✓ Decompressed to temporary file"
|
||||
else
|
||||
RESTORE_FILE="$BACKUP_FILE"
|
||||
fi
|
||||
|
||||
# Verify backup integrity before restore
|
||||
echo "Verifying backup integrity..."
|
||||
if ! sqlite3 "$RESTORE_FILE" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
echo "ERROR: Backup integrity check failed" >&2
|
||||
[ -n "$TEMP_FILE" ] && rm -f "$TEMP_FILE"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Backup integrity verified"
|
||||
|
||||
# Create temporary container to access volume if container is stopped
|
||||
if [ "$CONTAINER_RUNNING" = false ]; then
|
||||
echo "Creating temporary container to access volume..."
|
||||
TEMP_CONTAINER="${CONTAINER_NAME}_restore_temp"
|
||||
$ENGINE run -d --name "$TEMP_CONTAINER" \
|
||||
-v gondulf_data:/data \
|
||||
alpine:latest sleep 300
|
||||
CONTAINER_NAME="$TEMP_CONTAINER"
|
||||
fi
|
||||
|
||||
# Create safety backup of current database
|
||||
echo "Creating safety backup of current database..."
|
||||
SAFETY_BACKUP_CONTAINER="/data/gondulf_pre_restore_$(date +%Y%m%d_%H%M%S).db"
|
||||
if $ENGINE exec "$CONTAINER_NAME" test -f "$DB_PATH" 2>/dev/null; then
|
||||
$ENGINE exec "$CONTAINER_NAME" cp "$DB_PATH" "$SAFETY_BACKUP_CONTAINER" || {
|
||||
echo "WARNING: Failed to create safety backup" >&2
|
||||
}
|
||||
echo "✓ Safety backup created: $SAFETY_BACKUP_CONTAINER"
|
||||
else
|
||||
echo " No existing database found (first time setup)"
|
||||
fi
|
||||
|
||||
# Copy restore file into container
|
||||
RESTORE_FILE_CONTAINER="/tmp/restore_db.tmp"
|
||||
echo "Copying backup to container..."
|
||||
$ENGINE cp "$RESTORE_FILE" "$CONTAINER_NAME:$RESTORE_FILE_CONTAINER"
|
||||
|
||||
# Perform restore
|
||||
echo "Restoring database..."
|
||||
$ENGINE exec "$CONTAINER_NAME" sh -c "cp '$RESTORE_FILE_CONTAINER' '$DB_PATH'"
|
||||
|
||||
# Verify restored database
|
||||
echo "Verifying restored database..."
|
||||
if $ENGINE exec "$CONTAINER_NAME" sqlite3 "$DB_PATH" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
echo "✓ Restored database integrity verified"
|
||||
else
|
||||
echo "ERROR: Restored database integrity check failed" >&2
|
||||
echo "Attempting to restore from safety backup..."
|
||||
|
||||
if $ENGINE exec "$CONTAINER_NAME" test -f "$SAFETY_BACKUP_CONTAINER" 2>/dev/null; then
|
||||
$ENGINE exec "$CONTAINER_NAME" cp "$SAFETY_BACKUP_CONTAINER" "$DB_PATH"
|
||||
echo "✓ Reverted to safety backup"
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
$ENGINE exec "$CONTAINER_NAME" rm -f "$RESTORE_FILE_CONTAINER"
|
||||
[ -n "$TEMP_FILE" ] && rm -f "$TEMP_FILE"
|
||||
|
||||
# Stop temporary container if created
|
||||
if [ "$CONTAINER_RUNNING" = false ]; then
|
||||
$ENGINE stop "$TEMP_CONTAINER" 2>/dev/null || true
|
||||
$ENGINE rm "$TEMP_CONTAINER" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up temporary restore file in container
|
||||
$ENGINE exec "$CONTAINER_NAME" rm -f "$RESTORE_FILE_CONTAINER"
|
||||
|
||||
# Clean up temporary decompressed file on host
|
||||
[ -n "$TEMP_FILE" ] && rm -f "$TEMP_FILE"
|
||||
|
||||
# Stop and remove temporary container if we created one
|
||||
if [ "$CONTAINER_RUNNING" = false ]; then
|
||||
echo "Cleaning up temporary container..."
|
||||
$ENGINE stop "$TEMP_CONTAINER" 2>/dev/null || true
|
||||
$ENGINE rm "$TEMP_CONTAINER" 2>/dev/null || true
|
||||
CONTAINER_NAME="${CONTAINER_NAME%_restore_temp}" # Restore original name
|
||||
fi
|
||||
|
||||
# Restart original container if it was running
|
||||
if [ "$CONTAINER_RUNNING" = true ]; then
|
||||
echo "Starting container..."
|
||||
$ENGINE start "$CONTAINER_NAME"
|
||||
echo "Waiting for container to be healthy..."
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Restore complete!"
|
||||
echo "========================================="
|
||||
echo "Backup restored from: $BACKUP_FILE"
|
||||
echo "Safety backup location: $SAFETY_BACKUP_CONTAINER"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Verify the application is working correctly"
|
||||
echo "2. Once verified, you may delete the safety backup with:"
|
||||
echo " $ENGINE exec $CONTAINER_NAME rm $SAFETY_BACKUP_CONTAINER"
|
||||
echo ""
|
||||
169
deployment/scripts/test-backup-restore.sh
Executable file
169
deployment/scripts/test-backup-restore.sh
Executable file
@@ -0,0 +1,169 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Gondulf Backup and Restore Test Script
|
||||
# Tests backup and restore procedures without modifying production data
|
||||
#
|
||||
# Usage: ./test-backup-restore.sh
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Auto-detect container engine
|
||||
detect_container_engine() {
|
||||
if [ -n "${CONTAINER_ENGINE:-}" ]; then
|
||||
echo "$CONTAINER_ENGINE"
|
||||
elif command -v podman &> /dev/null; then
|
||||
echo "podman"
|
||||
elif command -v docker &> /dev/null; then
|
||||
echo "docker"
|
||||
else
|
||||
echo "ERROR: Neither podman nor docker found" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ENGINE=$(detect_container_engine)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="/tmp/gondulf-backup-test-$$"
|
||||
|
||||
echo "========================================="
|
||||
echo "Gondulf Backup/Restore Test"
|
||||
echo "========================================="
|
||||
echo "Container engine: $ENGINE"
|
||||
echo "Test directory: $TEST_DIR"
|
||||
echo ""
|
||||
|
||||
# Create test directory
|
||||
mkdir -p "$TEST_DIR"
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "Cleaning up test directory..."
|
||||
rm -rf "$TEST_DIR"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
# Test 1: Create a backup
|
||||
echo "Test 1: Creating backup..."
|
||||
echo "----------------------------------------"
|
||||
if BACKUP_DIR="$TEST_DIR" "$SCRIPT_DIR/backup.sh"; then
|
||||
echo "✓ Test 1 PASSED: Backup created successfully"
|
||||
else
|
||||
echo "✗ Test 1 FAILED: Backup creation failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Verify backup file exists
|
||||
BACKUP_FILE=$(ls -t "$TEST_DIR"/gondulf_backup_*.db.gz 2>/dev/null | head -1)
|
||||
if [ -z "$BACKUP_FILE" ]; then
|
||||
echo "✗ Test FAILED: No backup file found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Backup file: $BACKUP_FILE"
|
||||
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
echo "Backup size: $BACKUP_SIZE"
|
||||
echo ""
|
||||
|
||||
# Test 2: Verify backup integrity
|
||||
echo "Test 2: Verifying backup integrity..."
|
||||
echo "----------------------------------------"
|
||||
TEMP_DB=$(mktemp)
|
||||
gunzip -c "$BACKUP_FILE" > "$TEMP_DB"
|
||||
|
||||
if sqlite3 "$TEMP_DB" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
echo "✓ Test 2 PASSED: Backup integrity check successful"
|
||||
else
|
||||
echo "✗ Test 2 FAILED: Backup integrity check failed"
|
||||
rm -f "$TEMP_DB"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 3: Verify backup contains expected tables
|
||||
echo "Test 3: Verifying backup structure..."
|
||||
echo "----------------------------------------"
|
||||
TABLES=$(sqlite3 "$TEMP_DB" "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;")
|
||||
echo "Tables found in backup:"
|
||||
echo "$TABLES"
|
||||
|
||||
# Check for expected tables (based on Gondulf schema)
|
||||
# Tables: authorization_codes, domains, migrations, tokens, sqlite_sequence
|
||||
EXPECTED_TABLES=("authorization_codes" "domains" "tokens")
|
||||
ALL_TABLES_FOUND=true
|
||||
|
||||
for table in "${EXPECTED_TABLES[@]}"; do
|
||||
if echo "$TABLES" | grep -q "^$table$"; then
|
||||
echo "✓ Found table: $table"
|
||||
else
|
||||
echo "✗ Missing table: $table"
|
||||
ALL_TABLES_FOUND=false
|
||||
fi
|
||||
done
|
||||
|
||||
rm -f "$TEMP_DB"
|
||||
|
||||
if [ "$ALL_TABLES_FOUND" = true ]; then
|
||||
echo "✓ Test 3 PASSED: All expected tables found"
|
||||
else
|
||||
echo "✗ Test 3 FAILED: Missing expected tables"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 4: Test decompression
|
||||
echo "Test 4: Testing backup decompression..."
|
||||
echo "----------------------------------------"
|
||||
UNCOMPRESSED_DB="$TEST_DIR/test_uncompressed.db"
|
||||
if gunzip -c "$BACKUP_FILE" > "$UNCOMPRESSED_DB"; then
|
||||
if [ -f "$UNCOMPRESSED_DB" ] && [ -s "$UNCOMPRESSED_DB" ]; then
|
||||
echo "✓ Test 4 PASSED: Backup decompression successful"
|
||||
UNCOMPRESSED_SIZE=$(du -h "$UNCOMPRESSED_DB" | cut -f1)
|
||||
echo " Uncompressed size: $UNCOMPRESSED_SIZE"
|
||||
else
|
||||
echo "✗ Test 4 FAILED: Decompressed file is empty or missing"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "✗ Test 4 FAILED: Decompression failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 5: Verify backup can be queried
|
||||
echo "Test 5: Testing backup database queries..."
|
||||
echo "----------------------------------------"
|
||||
if DOMAIN_COUNT=$(sqlite3 "$UNCOMPRESSED_DB" "SELECT COUNT(*) FROM domains;" 2>/dev/null); then
|
||||
echo "✓ Test 5 PASSED: Backup database is queryable"
|
||||
echo " Domain count: $DOMAIN_COUNT"
|
||||
else
|
||||
echo "✗ Test 5 FAILED: Cannot query backup database"
|
||||
rm -f "$UNCOMPRESSED_DB"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$UNCOMPRESSED_DB"
|
||||
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo "========================================="
|
||||
echo "All Tests Passed!"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "Summary:"
|
||||
echo " Backup file: $BACKUP_FILE"
|
||||
echo " Backup size: $BACKUP_SIZE"
|
||||
echo " Container engine: $ENGINE"
|
||||
echo ""
|
||||
echo "The backup and restore system is working correctly."
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user