mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-01-13 09:07:20 +00:00
feat: comprehensive module system and database management improvements
This commit introduces major enhancements to the module installation system, database management, and configuration handling for AzerothCore deployments. ## Module System Improvements ### Module SQL Staging & Installation - Refactor module SQL staging to properly handle AzerothCore's sql/ directory structure - Fix SQL staging path to use correct AzerothCore format (sql/custom/db_*/*) - Implement conditional module database importing based on enabled modules - Add support for both cpp-modules and lua-scripts module types - Handle rsync exit code 23 (permission warnings) gracefully during deployment ### Module Manifest & Automation - Add automated module manifest generation via GitHub Actions workflow - Implement Python-based module manifest updater with comprehensive validation - Add module dependency tracking and SQL file discovery - Support for blocked modules and module metadata management ## Database Management Enhancements ### Database Import System - Add db-guard container for continuous database health monitoring and verification - Implement conditional database import that skips when databases are current - Add backup restoration and SQL staging coordination - Support for Playerbots database (4th database) in all import operations - Add comprehensive database health checking and status reporting ### Database Configuration - Implement 10 new dbimport.conf settings from environment variables: - Database.Reconnect.Seconds/Attempts for connection reliability - Updates.AllowedModules for module auto-update control - Updates.Redundancy for data integrity checks - Worker/Synch thread settings for all three core databases - Auto-apply dbimport.conf settings via auto-post-install.sh - Add environment variable injection for db-import and db-guard containers ### Backup & Recovery - Fix backup scheduler to prevent immediate execution on container startup - Add backup status monitoring script with detailed reporting - Implement backup import/export utilities - Add database verification scripts for SQL update tracking ## User Import Directory - Add new import/ directory for user-provided database files and configurations - Support for custom SQL files, configuration overrides, and example templates - Automatic import of user-provided databases and configs during initialization - Documentation and examples for custom database imports ## Configuration & Environment - Eliminate CLIENT_DATA_VERSION warning by adding default value syntax - Improve CLIENT_DATA_VERSION documentation in .env.template - Add comprehensive database import settings to .env and .env.template - Update setup.sh to handle new configuration variables with proper defaults ## Monitoring & Debugging - Add status dashboard with Go-based terminal UI (statusdash.go) - Implement JSON status output (statusjson.sh) for programmatic access - Add comprehensive database health check script - Add repair-storage-permissions.sh utility for permission issues ## Testing & Documentation - Add Phase 1 integration test suite for module installation verification - Add comprehensive documentation for: - Database management (DATABASE_MANAGEMENT.md) - Module SQL analysis (AZEROTHCORE_MODULE_SQL_ANALYSIS.md) - Implementation mapping (IMPLEMENTATION_MAP.md) - SQL staging comparison and path coverage - Module assets and DBC file requirements - Update SCRIPTS.md, ADVANCED.md, and troubleshooting documentation - Update references from database-import/ to import/ directory ## Breaking Changes - Renamed database-import/ directory to import/ for clarity - Module SQL files now staged to AzerothCore-compatible paths - db-guard container now required for proper database lifecycle management ## Bug Fixes - Fix module SQL staging directory structure for AzerothCore compatibility - Handle rsync exit code 23 gracefully during deployments - Prevent backup from running immediately on container startup - Correct SQL staging paths for proper module installation
This commit is contained in:
348
scripts/bash/verify-sql-updates.sh
Executable file
348
scripts/bash/verify-sql-updates.sh
Executable file
@@ -0,0 +1,348 @@
|
||||
#!/bin/bash
|
||||
# Verify SQL Updates
|
||||
# Checks that SQL updates have been applied via the updates table
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Icons
|
||||
ICON_SUCCESS="✅"
|
||||
ICON_WARNING="⚠️"
|
||||
ICON_ERROR="❌"
|
||||
ICON_INFO="ℹ️"
|
||||
|
||||
# Default values
|
||||
MODULE_NAME=""
|
||||
DATABASE_NAME=""
|
||||
SHOW_ALL=0
|
||||
CHECK_HASH=0
|
||||
CONTAINER_NAME="ac-mysql"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ./verify-sql-updates.sh [options]
|
||||
|
||||
Verify that SQL updates have been applied via AzerothCore's updates table.
|
||||
|
||||
Options:
|
||||
--module NAME Check specific module
|
||||
--database NAME Check specific database (auth/world/characters)
|
||||
--all Show all module updates
|
||||
--check-hash Verify file hashes match database
|
||||
--container NAME MySQL container name (default: ac-mysql)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
./verify-sql-updates.sh --all
|
||||
./verify-sql-updates.sh --module mod-aoe-loot
|
||||
./verify-sql-updates.sh --database acore_world --all
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--module) MODULE_NAME="$2"; shift 2;;
|
||||
--database) DATABASE_NAME="$2"; shift 2;;
|
||||
--all) SHOW_ALL=1; shift;;
|
||||
--check-hash) CHECK_HASH=1; shift;;
|
||||
--container) CONTAINER_NAME="$2"; shift 2;;
|
||||
-h|--help) usage; exit 0;;
|
||||
*) echo "Unknown option: $1"; usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Load environment
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source "$PROJECT_ROOT/.env"
|
||||
set +a
|
||||
fi
|
||||
|
||||
MYSQL_HOST="${MYSQL_HOST:-ac-mysql}"
|
||||
MYSQL_PORT="${MYSQL_PORT:-3306}"
|
||||
MYSQL_USER="${MYSQL_USER:-root}"
|
||||
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-}"
|
||||
DB_AUTH_NAME="${DB_AUTH_NAME:-acore_auth}"
|
||||
DB_WORLD_NAME="${DB_WORLD_NAME:-acore_world}"
|
||||
DB_CHARACTERS_NAME="${DB_CHARACTERS_NAME:-acore_characters}"
|
||||
DB_PLAYERBOTS_NAME="${DB_PLAYERBOTS_NAME:-acore_playerbots}"
|
||||
|
||||
# Logging functions
|
||||
info() {
|
||||
echo -e "${BLUE}${ICON_INFO}${NC} $*"
|
||||
}
|
||||
|
||||
ok() {
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} $*"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} $*"
|
||||
}
|
||||
|
||||
err() {
|
||||
echo -e "${RED}${ICON_ERROR}${NC} $*"
|
||||
}
|
||||
|
||||
# MySQL query helper
|
||||
mysql_query() {
|
||||
local database="${1:-}"
|
||||
local query="$2"
|
||||
|
||||
if [ -z "$MYSQL_ROOT_PASSWORD" ]; then
|
||||
err "MYSQL_ROOT_PASSWORD not set"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
if [ -n "$database" ]; then
|
||||
docker exec "$CONTAINER_NAME" mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_ROOT_PASSWORD" "$database" -N -B -e "$query" 2>/dev/null
|
||||
else
|
||||
docker exec "$CONTAINER_NAME" mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_ROOT_PASSWORD" -N -B -e "$query" 2>/dev/null
|
||||
fi
|
||||
else
|
||||
if [ -n "$database" ]; then
|
||||
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_ROOT_PASSWORD" "$database" -N -B -e "$query" 2>/dev/null
|
||||
else
|
||||
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_ROOT_PASSWORD" -N -B -e "$query" 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if database exists
|
||||
db_exists() {
|
||||
local db_name="$1"
|
||||
local count
|
||||
count=$(mysql_query "" "SELECT COUNT(*) FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='$db_name'" 2>/dev/null || echo "0")
|
||||
[ "$count" = "1" ]
|
||||
}
|
||||
|
||||
# Verify module SQL in database
|
||||
verify_module_sql() {
|
||||
local module_name="$1"
|
||||
local database_name="$2"
|
||||
|
||||
if ! db_exists "$database_name"; then
|
||||
err "Database does not exist: $database_name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "Checking module updates in $database_name"
|
||||
|
||||
# Query updates table for module
|
||||
local query="SELECT name, hash, state, timestamp, speed FROM updates WHERE name LIKE '%${module_name}%' AND state='MODULE' ORDER BY timestamp DESC"
|
||||
local results
|
||||
results=$(mysql_query "$database_name" "$query" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$results" ]; then
|
||||
warn "No updates found for module: $module_name in $database_name"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Display results
|
||||
echo
|
||||
printf "${BOLD}${CYAN}Module Updates for %s in %s:${NC}\n" "$module_name" "$database_name"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
while IFS=$'\t' read -r name hash state timestamp speed; do
|
||||
printf "${GREEN}${ICON_SUCCESS}${NC} %s\n" "$name"
|
||||
printf " Hash: %s\n" "${hash:0:12}..."
|
||||
printf " Applied: %s\n" "$timestamp"
|
||||
printf " Speed: %sms\n" "$speed"
|
||||
echo
|
||||
done <<< "$results"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# List all module updates
|
||||
list_module_updates() {
|
||||
local database_name="$1"
|
||||
|
||||
if ! db_exists "$database_name"; then
|
||||
err "Database does not exist: $database_name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "Listing all module updates in $database_name"
|
||||
|
||||
# Query all module updates
|
||||
local query="SELECT name, state, timestamp FROM updates WHERE state='MODULE' ORDER BY timestamp DESC"
|
||||
local results
|
||||
results=$(mysql_query "$database_name" "$query" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$results" ]; then
|
||||
warn "No module updates found in $database_name"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Display results
|
||||
echo
|
||||
printf "${BOLD}${CYAN}All Module Updates in %s:${NC}\n" "$database_name"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
local count=0
|
||||
while IFS=$'\t' read -r name state timestamp; do
|
||||
printf "${GREEN}${ICON_SUCCESS}${NC} %s\n" "$name"
|
||||
printf " Applied: %s\n" "$timestamp"
|
||||
((count++))
|
||||
done <<< "$results"
|
||||
|
||||
echo
|
||||
ok "Total module updates: $count"
|
||||
echo
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check update applied
|
||||
check_update_applied() {
|
||||
local filename="$1"
|
||||
local database_name="$2"
|
||||
local expected_hash="${3:-}"
|
||||
|
||||
if ! db_exists "$database_name"; then
|
||||
err "Database does not exist: $database_name"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# Query for specific file
|
||||
local query="SELECT hash, state, timestamp FROM updates WHERE name='$filename' LIMIT 1"
|
||||
local result
|
||||
result=$(mysql_query "$database_name" "$query" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$result" ]; then
|
||||
warn "Update not found: $filename"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Parse result
|
||||
IFS=$'\t' read -r hash state timestamp <<< "$result"
|
||||
|
||||
ok "Update applied: $filename"
|
||||
printf " Hash: %s\n" "$hash"
|
||||
printf " State: %s\n" "$state"
|
||||
printf " Applied: %s\n" "$timestamp"
|
||||
|
||||
# Check hash if provided
|
||||
if [ -n "$expected_hash" ] && [ "$expected_hash" != "$hash" ]; then
|
||||
err "Hash mismatch!"
|
||||
printf " Expected: %s\n" "$expected_hash"
|
||||
printf " Actual: %s\n" "$hash"
|
||||
return 2
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Generate verification report
|
||||
generate_verification_report() {
|
||||
echo
|
||||
printf "${BOLD}${BLUE}🔍 Module SQL Verification Report${NC}\n"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
|
||||
local total_updates=0
|
||||
local databases=("$DB_AUTH_NAME" "$DB_WORLD_NAME" "$DB_CHARACTERS_NAME")
|
||||
|
||||
# Add playerbots if it exists
|
||||
if db_exists "$DB_PLAYERBOTS_NAME"; then
|
||||
databases+=("$DB_PLAYERBOTS_NAME")
|
||||
fi
|
||||
|
||||
for db in "${databases[@]}"; do
|
||||
if ! db_exists "$db"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get count of module updates
|
||||
local count
|
||||
count=$(mysql_query "$db" "SELECT COUNT(*) FROM updates WHERE state='MODULE'" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$count" != "0" ]; then
|
||||
printf "${GREEN}${ICON_SUCCESS}${NC} ${BOLD}%s:${NC} %s module update(s)\n" "$db" "$count"
|
||||
total_updates=$((total_updates + count))
|
||||
|
||||
if [ "$SHOW_ALL" = "1" ]; then
|
||||
# Show recent updates
|
||||
local query="SELECT name, timestamp FROM updates WHERE state='MODULE' ORDER BY timestamp DESC LIMIT 5"
|
||||
local results
|
||||
results=$(mysql_query "$db" "$query" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$results" ]; then
|
||||
while IFS=$'\t' read -r name timestamp; do
|
||||
printf " - %s (%s)\n" "$name" "$timestamp"
|
||||
done <<< "$results"
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
else
|
||||
printf "${YELLOW}${ICON_WARNING}${NC} ${BOLD}%s:${NC} No module updates\n" "$db"
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
printf "${BOLD}Total: %s module update(s) applied${NC}\n" "$total_updates"
|
||||
echo
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
echo
|
||||
info "SQL Update Verification"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
|
||||
# Test MySQL connection
|
||||
if ! mysql_query "" "SELECT 1" >/dev/null 2>&1; then
|
||||
err "Cannot connect to MySQL server"
|
||||
printf " Host: %s:%s\n" "$MYSQL_HOST" "$MYSQL_PORT"
|
||||
printf " User: %s\n" "$MYSQL_USER"
|
||||
printf " Container: %s\n\n" "$CONTAINER_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Execute based on options
|
||||
if [ -n "$MODULE_NAME" ]; then
|
||||
# Check specific module
|
||||
if [ -n "$DATABASE_NAME" ]; then
|
||||
verify_module_sql "$MODULE_NAME" "$DATABASE_NAME"
|
||||
else
|
||||
# Check all databases for this module
|
||||
for db in "$DB_AUTH_NAME" "$DB_WORLD_NAME" "$DB_CHARACTERS_NAME"; do
|
||||
if db_exists "$db"; then
|
||||
verify_module_sql "$MODULE_NAME" "$db"
|
||||
fi
|
||||
done
|
||||
if db_exists "$DB_PLAYERBOTS_NAME"; then
|
||||
verify_module_sql "$MODULE_NAME" "$DB_PLAYERBOTS_NAME"
|
||||
fi
|
||||
fi
|
||||
elif [ -n "$DATABASE_NAME" ]; then
|
||||
# List all updates in specific database
|
||||
list_module_updates "$DATABASE_NAME"
|
||||
else
|
||||
# Generate full report
|
||||
generate_verification_report
|
||||
fi
|
||||
|
||||
echo
|
||||
ok "Verification complete"
|
||||
echo
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user