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>
170 lines
4.4 KiB
Bash
Executable File
170 lines
4.4 KiB
Bash
Executable File
#!/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
|