diff --git a/compose.yml b/compose.yml index 76296bc..650b8c7 100644 --- a/compose.yml +++ b/compose.yml @@ -639,6 +639,12 @@ services: MAX_EXECUTION_TIME: ${PMA_MAX_EXECUTION_TIME:-600} ports: - "${PMA_EXTERNAL_PORT:-8081}:80" + healthcheck: + test: ["CMD", "sh", "-c", "curl -fsS http://localhost:80/ || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s restart: unless-stopped networks: - azerothcore diff --git a/deploy.sh b/deploy.sh index 6ef0931..d373ef2 100755 --- a/deploy.sh +++ b/deploy.sh @@ -148,6 +148,61 @@ modules_need_rebuild(){ [[ -f "$sentinel" ]] } +determine_profile(){ + if [ -n "$TARGET_PROFILE" ]; then + echo "$TARGET_PROFILE" + return + fi + + local module_playerbots + local playerbot_enabled + module_playerbots="$(read_env MODULE_PLAYERBOTS "0")" + playerbot_enabled="$(read_env PLAYERBOT_ENABLED "0")" + if [ "$module_playerbots" = "1" ] || [ "$playerbot_enabled" = "1" ]; then + echo "playerbots" + return + fi + + local compile_vars=( + MODULE_AOE_LOOT + MODULE_LEARN_SPELLS + MODULE_FIREWORKS + MODULE_INDIVIDUAL_PROGRESSION + MODULE_AHBOT + MODULE_AUTOBALANCE + MODULE_TRANSMOG + MODULE_NPC_BUFFER + MODULE_DYNAMIC_XP + MODULE_SOLO_LFG + MODULE_1V1_ARENA + MODULE_PHASED_DUELS + MODULE_BREAKING_NEWS + MODULE_BOSS_ANNOUNCER + MODULE_ACCOUNT_ACHIEVEMENTS + MODULE_AUTO_REVIVE + MODULE_GAIN_HONOR_GUARD + MODULE_TIME_IS_TIME + MODULE_POCKET_PORTAL + MODULE_RANDOM_ENCHANTS + MODULE_SOLOCRAFT + MODULE_PVP_TITLES + MODULE_NPC_BEASTMASTER + MODULE_NPC_ENCHANTER + MODULE_INSTANCE_RESET + MODULE_LEVEL_GRANT + ) + + local var + for var in "${compile_vars[@]}"; do + if [ "$(read_env "$var" "0")" = "1" ]; then + echo "modules" + return + fi + done + + echo "standard" +} + rebuild_source(){ local src_dir="$1" local compose_file="$src_dir/docker-compose.yml" @@ -171,16 +226,6 @@ rebuild_source(){ } tag_module_images(){ - local module_playerbots - local playerbot_enabled - module_playerbots="$(read_env MODULE_PLAYERBOTS "0")" - playerbot_enabled="$(read_env PLAYERBOT_ENABLED "0")" - - if [ "$module_playerbots" = "1" ] || [ "$playerbot_enabled" = "1" ]; then - info "Playerbot mode detected; skipping module image tagging." - return - fi - local source_world="acore/ac-wotlk-worldserver:master" local source_auth="acore/ac-wotlk-authserver:master" local target_world @@ -214,16 +259,21 @@ stage_runtime(){ tail_world_logs(){ info "Tailing worldserver logs (Ctrl+C to stop)" - compose logs -f ac-worldserver + if ! docker logs --follow --tail "${WORLD_LOG_TAIL:-200}" ac-worldserver; then + warn "Worldserver logs unavailable; container may not be running." + fi } main(){ show_deployment_header local src_dir + local resolved_profile show_step 1 5 "Setting up source repository" src_dir="$(ensure_source_repo)" + resolved_profile="$(determine_profile)" + if [ "$KEEP_RUNNING" -ne 1 ]; then show_step 2 5 "Stopping runtime stack" stop_runtime_stack @@ -238,10 +288,12 @@ main(){ else show_step 4 5 "Building realm with modules (this may take 15-45 minutes)" rebuild_source "$src_dir" - tag_module_images fi else info "No module rebuild required." + fi + + if [ "$resolved_profile" = "modules" ]; then tag_module_images fi diff --git a/status.sh b/status.sh index 9d90612..5193770 100755 --- a/status.sh +++ b/status.sh @@ -11,13 +11,14 @@ cd "$PROJECT_DIR" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BLUE='\033[0;34m'; NC='\033[0m' -WATCH_MODE=false +WATCH_MODE=true LOG_LINES=5 SHOW_LOGS=false while [[ $# -gt 0 ]]; do case "$1" in --watch|-w) WATCH_MODE=true; shift;; + --once) WATCH_MODE=false; shift;; --logs|-l) SHOW_LOGS=true; shift;; --lines) LOG_LINES="$2"; shift 2;; -h|--help) @@ -25,7 +26,8 @@ while [[ $# -gt 0 ]]; do ac-compose realm status Usage: $0 [options] - -w, --watch Continuously refresh every 3s + -w, --watch Continuously refresh every 3s (default) + --once Show a single snapshot then exit -l, --logs Show trailing logs for each service --lines N Number of log lines when --logs is used (default 5) EOF @@ -195,6 +197,41 @@ module_summary(){ fi } +user_stats(){ + if ! container_running "ac-mysql"; then + printf "USERS: %sDatabase offline%s\n" "$RED" "$NC" + return + fi + + local mysql_pw db_auth db_characters + mysql_pw="$(read_env MYSQL_ROOT_PASSWORD azerothcore123)" + db_auth="$(read_env DB_AUTH_NAME acore_auth)" + db_characters="$(read_env DB_CHARACTERS_NAME acore_characters)" + + local exec_mysql + exec_mysql(){ + local database="$1" query="$2" + docker exec ac-mysql mysql -N -B -u root -p"${mysql_pw}" "$database" -e "$query" 2>/dev/null | tail -n1 + } + + local account_total account_online character_total last_week + account_total="$(exec_mysql "$db_auth" "SELECT COUNT(*) FROM account;")" + account_online="$(exec_mysql "$db_auth" "SELECT COUNT(*) FROM account WHERE online = 1;")" + character_total="$(exec_mysql "$db_characters" "SELECT COUNT(*) FROM characters;")" + last_week="$(exec_mysql "$db_auth" "SELECT COUNT(*) FROM account WHERE last_login >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 7 DAY);")" + + [[ -z "$account_total" ]] && account_total="0" + [[ -z "$account_online" ]] && account_online="0" + [[ -z "$character_total" ]] && character_total="0" + [[ -z "$last_week" ]] && last_week="0" + + printf "USERS: Accounts %b%s%b | Online %b%s%b | Characters %b%s%b | Active 7d %b%s%b\n" \ + "$GREEN" "$account_total" "$NC" \ + "$YELLOW" "$account_online" "$NC" \ + "$CYAN" "$character_total" "$NC" \ + "$BLUE" "$last_week" "$NC" +} + ports_summary(){ local names=("Auth" "World" "SOAP" "MySQL" "phpMyAdmin" "Keira3") local ports=("$AUTH_PORT" "$WORLD_PORT" "$SOAP_PORT" "$MYSQL_PORT" "$PMA_PORT" "$KEIRA_PORT") @@ -223,8 +260,7 @@ show_realm_status_header(){ echo -e "${BLUE}═══════════════════════════${NC}" } -print_status(){ - clear 2>/dev/null || printf '\033[2J\033[H' +render_snapshot(){ show_realm_status_header printf "\nTIME %s PROJECT %s\n\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$PROJECT_NAME" printf "%-20s %-28s %s\n" "SERVICE" "STATE" "IMAGE" @@ -242,16 +278,26 @@ print_status(){ print_service ac-keira3 "Keira3" echo "" module_summary + user_stats echo "" echo "$(ports_summary)" echo "$(network_summary)" } +display_snapshot(){ + local tmp + tmp="$(mktemp)" + render_snapshot >"$tmp" + clear 2>/dev/null || printf '\033[2J\033[H' + cat "$tmp" + rm -f "$tmp" +} + if [ "$WATCH_MODE" = true ]; then while true; do - print_status + display_snapshot sleep 3 done else - print_status + display_snapshot fi