mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-01-13 00:58:34 +00:00
Introduce dynamic overrides and rename module manifest
This commit is contained in:
@@ -2,6 +2,14 @@
|
|||||||
# Docker Compose will auto-load .env in the same folder as docker-compose.yml.
|
# Docker Compose will auto-load .env in the same folder as docker-compose.yml.
|
||||||
# Template for acore-compose profiles-based compose
|
# Template for acore-compose profiles-based compose
|
||||||
|
|
||||||
|
# =====================
|
||||||
|
# Compose overrides (set to 1 to include matching file under compose-overrides/)
|
||||||
|
# =====================
|
||||||
|
# mysql-expose.yml -> exposes MySQL externally via COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED
|
||||||
|
# worldserver-debug-logging.yml -> raises log verbosity via COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED
|
||||||
|
COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=0
|
||||||
|
COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=0
|
||||||
|
|
||||||
# =====================
|
# =====================
|
||||||
# Project name
|
# Project name
|
||||||
# =====================
|
# =====================
|
||||||
@@ -43,10 +51,10 @@ CONTAINER_POST_INSTALL=ac-post-install
|
|||||||
# =====================
|
# =====================
|
||||||
# Images
|
# Images
|
||||||
# =====================
|
# =====================
|
||||||
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
|
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:master
|
||||||
# Services (Standard)
|
# Services (Standard)
|
||||||
AC_AUTHSERVER_IMAGE=acore/ac-wotlk-authserver:14.0.0-dev
|
AC_AUTHSERVER_IMAGE=acore/ac-wotlk-authserver:master
|
||||||
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:14.0.0-dev
|
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:master
|
||||||
# Services (Playerbots)
|
# Services (Playerbots)
|
||||||
AC_AUTHSERVER_IMAGE_PLAYERBOTS=acore-compose:authserver-playerbots
|
AC_AUTHSERVER_IMAGE_PLAYERBOTS=acore-compose:authserver-playerbots
|
||||||
AC_WORLDSERVER_IMAGE_PLAYERBOTS=acore-compose:worldserver-playerbots
|
AC_WORLDSERVER_IMAGE_PLAYERBOTS=acore-compose:worldserver-playerbots
|
||||||
@@ -55,7 +63,7 @@ AC_WORLDSERVER_IMAGE_PLAYERBOTS=acore-compose:worldserver-playerbots
|
|||||||
AC_AUTHSERVER_IMAGE_MODULES=acore-compose:authserver-modules-latest
|
AC_AUTHSERVER_IMAGE_MODULES=acore-compose:authserver-modules-latest
|
||||||
AC_WORLDSERVER_IMAGE_MODULES=acore-compose:worldserver-modules-latest
|
AC_WORLDSERVER_IMAGE_MODULES=acore-compose:worldserver-modules-latest
|
||||||
# Client Data
|
# Client Data
|
||||||
AC_CLIENT_DATA_IMAGE=acore/ac-wotlk-client-data:14.0.0-dev
|
AC_CLIENT_DATA_IMAGE=acore/ac-wotlk-client-data:master
|
||||||
AC_CLIENT_DATA_IMAGE_PLAYERBOTS=uprightbass360/azerothcore-wotlk-playerbots:client-data-Playerbot
|
AC_CLIENT_DATA_IMAGE_PLAYERBOTS=uprightbass360/azerothcore-wotlk-playerbots:client-data-Playerbot
|
||||||
# Build artifacts
|
# Build artifacts
|
||||||
DOCKER_IMAGE_TAG=master
|
DOCKER_IMAGE_TAG=master
|
||||||
@@ -101,7 +109,6 @@ MYSQL_ROOT_HOST=%
|
|||||||
MYSQL_USER=root
|
MYSQL_USER=root
|
||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3306
|
||||||
MYSQL_EXTERNAL_PORT=64306
|
MYSQL_EXTERNAL_PORT=64306
|
||||||
MYSQL_EXPOSE_PORT=0
|
|
||||||
MYSQL_CHARACTER_SET=utf8mb4
|
MYSQL_CHARACTER_SET=utf8mb4
|
||||||
MYSQL_COLLATION=utf8mb4_unicode_ci
|
MYSQL_COLLATION=utf8mb4_unicode_ci
|
||||||
MYSQL_MAX_CONNECTIONS=1000
|
MYSQL_MAX_CONNECTIONS=1000
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -97,6 +97,7 @@ cd AzerothCore-RealmMaster
|
|||||||
The setup wizard will guide you through:
|
The setup wizard will guide you through:
|
||||||
- **Server Configuration**: IP address, ports, timezone
|
- **Server Configuration**: IP address, ports, timezone
|
||||||
- **Module Selection**: Choose from 30+ available modules or use presets
|
- **Module Selection**: Choose from 30+ available modules or use presets
|
||||||
|
- **Module Definitions**: Customize defaults in `config/module-manifest.json` and optional presets under `config/module-profiles/`
|
||||||
- **Storage Paths**: Configure NFS/local storage locations
|
- **Storage Paths**: Configure NFS/local storage locations
|
||||||
- **Playerbot Settings**: Max bots, account limits (if enabled)
|
- **Playerbot Settings**: Max bots, account limits (if enabled)
|
||||||
- **Backup Settings**: Retention policies for automated backups
|
- **Backup Settings**: Retention policies for automated backups
|
||||||
@@ -116,7 +117,7 @@ The setup wizard will guide you through:
|
|||||||
|
|
||||||
**Required when:**
|
**Required when:**
|
||||||
- Playerbots enabled (`MODULE_PLAYERBOTS=1`)
|
- Playerbots enabled (`MODULE_PLAYERBOTS=1`)
|
||||||
- Any C++ module enabled (modules with `"type": "cpp"` in `config/modules.json`)
|
- Any C++ module enabled (modules with `"type": "cpp"` in `config/module-manifest.json`)
|
||||||
|
|
||||||
**Build process:**
|
**Build process:**
|
||||||
1. Clones AzerothCore source to `local-storage/source/`
|
1. Clones AzerothCore source to `local-storage/source/`
|
||||||
@@ -249,7 +250,7 @@ The remote deployment process transfers:
|
|||||||
- ❌ Build artifacts (source code, compilation files stay local)
|
- ❌ Build artifacts (source code, compilation files stay local)
|
||||||
|
|
||||||
#### Module Presets
|
#### Module Presets
|
||||||
- Define JSON presets in `profiles/*.json`. Each file contains:
|
- Define JSON presets in `config/module-profiles/*.json`. Each file contains:
|
||||||
- `modules` (array, required) – list of `MODULE_*` identifiers to enable.
|
- `modules` (array, required) – list of `MODULE_*` identifiers to enable.
|
||||||
- `label` (string, optional) – text shown in the setup menu (emoji welcome).
|
- `label` (string, optional) – text shown in the setup menu (emoji welcome).
|
||||||
- `description` (string, optional) – short help text for maintainers.
|
- `description` (string, optional) – short help text for maintainers.
|
||||||
@@ -266,11 +267,12 @@ The remote deployment process transfers:
|
|||||||
```
|
```
|
||||||
- `setup.sh` automatically adds these presets to the module menu and enables the listed modules when selected or when `--module-config <name>` is provided.
|
- `setup.sh` automatically adds these presets to the module menu and enables the listed modules when selected or when `--module-config <name>` is provided.
|
||||||
- Built-in presets:
|
- Built-in presets:
|
||||||
- `profiles/suggested-modules.json` – default solo-friendly QoL stack.
|
- `config/module-profiles/suggested-modules.json` – default solo-friendly QoL stack.
|
||||||
- `profiles/playerbots-suggested-modules.json` – suggested stack plus playerbots.
|
- `config/module-profiles/playerbots-suggested-modules.json` – suggested stack plus playerbots.
|
||||||
- `profiles/playerbots-only.json` – playerbot-focused profile (adjust `--playerbot-max-bots`).
|
- `config/module-profiles/playerbots-only.json` – playerbot-focused profile (adjust `--playerbot-max-bots`).
|
||||||
- Custom example:
|
- Custom example:
|
||||||
- `profiles/sam.json` – Sam's playerbot-focused profile (set `--playerbot-max-bots 3000` when using this preset).
|
- `config/module-profiles/sam.json` – Sam's playerbot-focused profile (set `--playerbot-max-bots 3000` when using this preset).
|
||||||
|
- Module metadata lives in `config/module-manifest.json`; update that file if you need to add new modules or change repositories/branches.
|
||||||
|
|
||||||
### Post-Installation Steps
|
### Post-Installation Steps
|
||||||
|
|
||||||
@@ -757,7 +759,7 @@ flowchart TB
|
|||||||
|
|
||||||
| Service / Container | Role | Ports (host → container) | Profile |
|
| Service / Container | Role | Ports (host → container) | Profile |
|
||||||
|---------------------|------|--------------------------|---------|
|
|---------------------|------|--------------------------|---------|
|
||||||
| `ac-mysql` | MySQL 8.0 database | *(optional)* `64306 → 3306` (`MYSQL_EXPOSE_PORT=1`) | `db` |
|
| `ac-mysql` | MySQL 8.0 database | *(optional)* `64306 → 3306` (`COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=1`) | `db` |
|
||||||
| `ac-db-init` | Database schema initialization | – | `db` |
|
| `ac-db-init` | Database schema initialization | – | `db` |
|
||||||
| `ac-db-import` | Database content import | – | `db` |
|
| `ac-db-import` | Database content import | – | `db` |
|
||||||
| `ac-backup` | Automated backup system | – | `db` |
|
| `ac-backup` | Automated backup system | – | `db` |
|
||||||
@@ -775,10 +777,22 @@ flowchart TB
|
|||||||
|
|
||||||
### Database Hardening
|
### Database Hardening
|
||||||
|
|
||||||
- **MySQL port exposure** – By default `MYSQL_EXPOSE_PORT=0`, so `ac-mysql` is reachable only from the internal Docker network. Set `MYSQL_EXPOSE_PORT=1` to publish `${MYSQL_EXTERNAL_PORT}` on the host; RealmMaster scripts automatically include `docker-compose.mysql-expose.yml` so the override Just Works. If you invoke Compose manually, remember to add `-f docker-compose.mysql-expose.yml`.
|
- **MySQL port exposure** – By default `COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=0`, so `ac-mysql` is reachable only from the internal Docker network. Set it to `1` to publish `${MYSQL_EXTERNAL_PORT}` on the host; RealmMaster scripts automatically include `compose-overrides/mysql-expose.yml` so the override Just Works. If you invoke Compose manually, remember to add `-f compose-overrides/mysql-expose.yml`. You can follow the same `COMPOSE_OVERRIDE_<NAME>_ENABLED=1` pattern for any custom override files you drop into `compose-overrides/`.
|
||||||
|
- **Worldserver debug logging** – Need extra verbosity temporarily? Flip `COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=1` to include `compose-overrides/worldserver-debug-logging.yml`, which bumps `AC_LOG_LEVEL` across all worldserver profiles. Turn it back off once you’re done to avoid noisy logs.
|
||||||
- **Binary logging toggle** – `MYSQL_DISABLE_BINLOG=1` appends `--skip-log-bin` via the MySQL wrapper entrypoint to keep disk churn low (and match Playerbot guidance). Flip the flag to `0` to re-enable binlogs for debugging or replication.
|
- **Binary logging toggle** – `MYSQL_DISABLE_BINLOG=1` appends `--skip-log-bin` via the MySQL wrapper entrypoint to keep disk churn low (and match Playerbot guidance). Flip the flag to `0` to re-enable binlogs for debugging or replication.
|
||||||
- **Drop-in configs** – Any `.cnf` placed in `${STORAGE_PATH}/config/mysql/conf.d` (exposed via `MYSQL_CONFIG_DIR`) is mounted into `/etc/mysql/conf.d`. Use this to add custom tunables or temporarily override the binlog setting without touching the image.
|
- **Drop-in configs** – Any `.cnf` placed in `${STORAGE_PATH}/config/mysql/conf.d` (exposed via `MYSQL_CONFIG_DIR`) is mounted into `/etc/mysql/conf.d`. Use this to add custom tunables or temporarily override the binlog setting without touching the image.
|
||||||
|
|
||||||
|
### Compose Overrides
|
||||||
|
|
||||||
|
All helper scripts automatically include any override file found in `compose-overrides/` when its matching flag `COMPOSE_OVERRIDE_<NAME>_ENABLED` is set to `1` in `.env`. Each override declares its flag at the top with `# override-flag: ...`. This lets you ship opt-in tweaks without editing `docker-compose.yml`.
|
||||||
|
|
||||||
|
Current examples:
|
||||||
|
|
||||||
|
- `compose-overrides/mysql-expose.yml` (`COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED`) – Publishes MySQL to `${MYSQL_EXTERNAL_PORT}` for external clients.
|
||||||
|
- `compose-overrides/worldserver-debug-logging.yml` (`COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED`) – Raises `AC_LOG_LEVEL` to `3` across all worldserver profiles for troubleshooting.
|
||||||
|
|
||||||
|
Add your own override by dropping a new `.yml` file into `compose-overrides/`, documenting the flag name in a comment, and toggling that flag in `.env`.
|
||||||
|
|
||||||
### Storage Structure
|
### Storage Structure
|
||||||
|
|
||||||
The project uses a dual-storage approach for optimal performance:
|
The project uses a dual-storage approach for optimal performance:
|
||||||
@@ -986,9 +1000,9 @@ Internal script that runs inside the `ac-modules` container to handle module lif
|
|||||||
- Manages module configuration files
|
- Manages module configuration files
|
||||||
- Tracks installation state
|
- Tracks installation state
|
||||||
|
|
||||||
#### `config/modules.json` & `scripts/modules.py`
|
#### `config/module-manifest.json` & `scripts/modules.py`
|
||||||
Central module registry and management system:
|
Central module registry and management system:
|
||||||
- **`config/modules.json`** - Declarative manifest defining all 30+ supported modules with metadata:
|
- **`config/module-manifest.json`** - Declarative manifest defining all 30+ supported modules with metadata:
|
||||||
- Repository URLs
|
- Repository URLs
|
||||||
- Module type (cpp, data, lua)
|
- Module type (cpp, data, lua)
|
||||||
- Build requirements
|
- Build requirements
|
||||||
|
|||||||
2
build.sh
2
build.sh
@@ -114,7 +114,7 @@ generate_module_state(){
|
|||||||
storage_root="$(resolve_local_storage_path)"
|
storage_root="$(resolve_local_storage_path)"
|
||||||
local output_dir="${storage_root}/modules"
|
local output_dir="${storage_root}/modules"
|
||||||
ensure_modules_dir_writable "$storage_root"
|
ensure_modules_dir_writable "$storage_root"
|
||||||
if ! python3 "$MODULE_HELPER" --env-path "$ENV_PATH" --manifest "$ROOT_DIR/config/modules.json" generate --output-dir "$output_dir"; then
|
if ! python3 "$MODULE_HELPER" --env-path "$ENV_PATH" --manifest "$ROOT_DIR/config/module-manifest.json" generate --output-dir "$output_dir"; then
|
||||||
err "Module manifest validation failed. See errors above."
|
err "Module manifest validation failed. See errors above."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
12
cleanup.sh
12
cleanup.sh
@@ -13,6 +13,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
PROJECT_DIR="${SCRIPT_DIR}"
|
PROJECT_DIR="${SCRIPT_DIR}"
|
||||||
DEFAULT_COMPOSE_FILE="${PROJECT_DIR}/docker-compose.yml"
|
DEFAULT_COMPOSE_FILE="${PROJECT_DIR}/docker-compose.yml"
|
||||||
ENV_FILE="${PROJECT_DIR}/.env"
|
ENV_FILE="${PROJECT_DIR}/.env"
|
||||||
|
source "${PROJECT_DIR}/scripts/lib/compose_overrides.sh"
|
||||||
|
declare -a COMPOSE_FILE_ARGS=()
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; MAGENTA='\033[0;35m'; NC='\033[0m'
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; MAGENTA='\033[0;35m'; NC='\033[0m'
|
||||||
@@ -125,15 +127,7 @@ if [ -f "$ENV_FILE" ]; then
|
|||||||
set -a; source "$ENV_FILE"; set +a
|
set -a; source "$ENV_FILE"; set +a
|
||||||
fi
|
fi
|
||||||
|
|
||||||
COMPOSE_FILE_ARGS=(-f "$DEFAULT_COMPOSE_FILE")
|
compose_overrides::build_compose_args "$PROJECT_DIR" "$ENV_FILE" "$DEFAULT_COMPOSE_FILE" COMPOSE_FILE_ARGS
|
||||||
if [ "${MYSQL_EXPOSE_PORT:-0}" = "1" ]; then
|
|
||||||
EXTRA_COMPOSE_FILE="${PROJECT_DIR}/docker-compose.mysql-expose.yml"
|
|
||||||
if [ -f "$EXTRA_COMPOSE_FILE" ]; then
|
|
||||||
COMPOSE_FILE_ARGS+=(-f "$EXTRA_COMPOSE_FILE")
|
|
||||||
else
|
|
||||||
print_status WARNING "MYSQL_EXPOSE_PORT=1 but $EXTRA_COMPOSE_FILE missing; skipping port exposure override."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
COMPOSE_FILE_ARGS_STR=""
|
COMPOSE_FILE_ARGS_STR=""
|
||||||
for arg in "${COMPOSE_FILE_ARGS[@]}"; do
|
for arg in "${COMPOSE_FILE_ARGS[@]}"; do
|
||||||
COMPOSE_FILE_ARGS_STR+=" ${arg}"
|
COMPOSE_FILE_ARGS_STR+=" ${arg}"
|
||||||
|
|||||||
12
compose-overrides/mysql-expose.yml
Normal file
12
compose-overrides/mysql-expose.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# override-flag: COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED
|
||||||
|
# legacy-flag: MYSQL_EXPOSE_PORT
|
||||||
|
# Optional override file that publishes MySQL to the host. Use it only when you
|
||||||
|
# intentionally need direct access (e.g., external DB clients). RealmMaster scripts
|
||||||
|
# auto-include this file whenever `COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=1`
|
||||||
|
# (or the legacy `MYSQL_EXPOSE_PORT=1`) in `.env`. When running Compose manually, add:
|
||||||
|
# docker compose -f docker-compose.yml -f compose-overrides/mysql-expose.yml up -d
|
||||||
|
# Reset the flag to 0 to return to the secure, internal-only default.
|
||||||
|
services:
|
||||||
|
ac-mysql:
|
||||||
|
ports:
|
||||||
|
- "${MYSQL_EXTERNAL_PORT}:${MYSQL_PORT}"
|
||||||
15
compose-overrides/worldserver-debug-logging.yml
Normal file
15
compose-overrides/worldserver-debug-logging.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# override-flag: COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED
|
||||||
|
# Example override that bumps worldserver log verbosity across all profiles.
|
||||||
|
# Enable by setting COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=1 in .env.
|
||||||
|
# Helpful while investigating live issues; remember to turn it off to reduce noise.
|
||||||
|
# Follow this pattern for any compose layers you want to implement
|
||||||
|
services:
|
||||||
|
ac-worldserver-standard:
|
||||||
|
environment:
|
||||||
|
AC_LOG_LEVEL: "3"
|
||||||
|
ac-worldserver-playerbots:
|
||||||
|
environment:
|
||||||
|
AC_LOG_LEVEL: "3"
|
||||||
|
ac-worldserver-modules:
|
||||||
|
environment:
|
||||||
|
AC_LOG_LEVEL: "3"
|
||||||
@@ -1,28 +1,39 @@
|
|||||||
{
|
{
|
||||||
"modules": [
|
"modules": [
|
||||||
"MODULE_ELUNA",
|
|
||||||
"MODULE_PLAYERBOTS",
|
"MODULE_PLAYERBOTS",
|
||||||
"MODULE_PLAYER_BOT_LEVEL_BRACKETS",
|
|
||||||
"MODULE_SOLO_LFG",
|
|
||||||
"MODULE_TRANSMOG",
|
|
||||||
"MODULE_NPC_BUFFER",
|
|
||||||
"MODULE_LEARN_SPELLS",
|
"MODULE_LEARN_SPELLS",
|
||||||
"MODULE_FIREWORKS",
|
"MODULE_FIREWORKS",
|
||||||
"MODULE_REAGENT_BANK",
|
"MODULE_TRANSMOG",
|
||||||
"MODULE_BLACK_MARKET_AUCTION_HOUSE",
|
"MODULE_NPC_BUFFER",
|
||||||
|
"MODULE_SOLO_LFG",
|
||||||
"MODULE_1V1_ARENA",
|
"MODULE_1V1_ARENA",
|
||||||
"MODULE_ACCOUNT_ACHIEVEMENTS",
|
|
||||||
"MODULE_BREAKING_NEWS",
|
"MODULE_BREAKING_NEWS",
|
||||||
"MODULE_BOSS_ANNOUNCER",
|
"MODULE_BOSS_ANNOUNCER",
|
||||||
|
"MODULE_ACCOUNT_ACHIEVEMENTS",
|
||||||
"MODULE_AUTO_REVIVE",
|
"MODULE_AUTO_REVIVE",
|
||||||
"MODULE_ELUNA_TS",
|
"MODULE_GAIN_HONOR_GUARD",
|
||||||
|
"MODULE_ELUNA",
|
||||||
|
"MODULE_TIME_IS_TIME",
|
||||||
|
"MODULE_RANDOM_ENCHANTS",
|
||||||
|
"MODULE_SOLOCRAFT",
|
||||||
"MODULE_NPC_BEASTMASTER",
|
"MODULE_NPC_BEASTMASTER",
|
||||||
"MODULE_NPC_ENCHANTER",
|
"MODULE_NPC_ENCHANTER",
|
||||||
"MODULE_RANDOM_ENCHANTS",
|
|
||||||
"MODULE_INSTANCE_RESET",
|
"MODULE_INSTANCE_RESET",
|
||||||
"MODULE_TIME_IS_TIME",
|
"MODULE_ARAC",
|
||||||
"MODULE_GAIN_HONOR_GUARD",
|
"MODULE_ASSISTANT",
|
||||||
"MODULE_ARAC"
|
"MODULE_REAGENT_BANK",
|
||||||
|
"MODULE_BLACK_MARKET_AUCTION_HOUSE",
|
||||||
|
"MODULE_STATBOOSTER",
|
||||||
|
"MODULE_ELUNA_TS",
|
||||||
|
"MODULE_AIO",
|
||||||
|
"MODULE_ELUNA_SCRIPTS",
|
||||||
|
"MODULE_EVENT_SCRIPTS",
|
||||||
|
"MODULE_ACTIVE_CHAT",
|
||||||
|
"MODULE_GUILDHOUSE",
|
||||||
|
"MODULE_NPC_FREE_PROFESSIONS",
|
||||||
|
"MODULE_MORPHSUMMON",
|
||||||
|
"MODULE_ITEM_LEVEL_UP",
|
||||||
|
"MODULE_GLOBAL_CHAT"
|
||||||
],
|
],
|
||||||
"label": "\ud83e\udde9 Sam",
|
"label": "\ud83e\udde9 Sam",
|
||||||
"description": "Sam's playerbot-centric preset (use high bot counts)",
|
"description": "Sam's playerbot-centric preset (use high bot counts)",
|
||||||
15
deploy.sh
15
deploy.sh
@@ -11,6 +11,7 @@ set -euo pipefail
|
|||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
DEFAULT_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
DEFAULT_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
||||||
ENV_PATH="$ROOT_DIR/.env"
|
ENV_PATH="$ROOT_DIR/.env"
|
||||||
|
source "$ROOT_DIR/scripts/lib/compose_overrides.sh"
|
||||||
TARGET_PROFILE=""
|
TARGET_PROFILE=""
|
||||||
WATCH_LOGS=1
|
WATCH_LOGS=1
|
||||||
KEEP_RUNNING=0
|
KEEP_RUNNING=0
|
||||||
@@ -280,17 +281,7 @@ read_env(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_compose_files(){
|
init_compose_files(){
|
||||||
local expose_port
|
compose_overrides::build_compose_args "$ROOT_DIR" "$ENV_PATH" "$DEFAULT_COMPOSE_FILE" COMPOSE_FILE_ARGS
|
||||||
expose_port="$(read_env MYSQL_EXPOSE_PORT "0")"
|
|
||||||
COMPOSE_FILE_ARGS=(-f "$DEFAULT_COMPOSE_FILE")
|
|
||||||
if [ "$expose_port" = "1" ]; then
|
|
||||||
local extra_file="$ROOT_DIR/docker-compose.mysql-expose.yml"
|
|
||||||
if [ -f "$extra_file" ]; then
|
|
||||||
COMPOSE_FILE_ARGS+=(-f "$extra_file")
|
|
||||||
else
|
|
||||||
warn "MYSQL_EXPOSE_PORT=1 but $extra_file not found; skipping port override"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_compose_files
|
init_compose_files
|
||||||
@@ -337,7 +328,7 @@ ensure_module_state(){
|
|||||||
local output_dir="${storage_root}/modules"
|
local output_dir="${storage_root}/modules"
|
||||||
ensure_modules_dir_writable "$storage_root"
|
ensure_modules_dir_writable "$storage_root"
|
||||||
|
|
||||||
if ! python3 "$MODULE_HELPER" --env-path "$ENV_PATH" --manifest "$ROOT_DIR/config/modules.json" generate --output-dir "$output_dir"; then
|
if ! python3 "$MODULE_HELPER" --env-path "$ENV_PATH" --manifest "$ROOT_DIR/config/module-manifest.json" generate --output-dir "$output_dir"; then
|
||||||
err "Module manifest validation failed. See errors above."
|
err "Module manifest validation failed. See errors above."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
services:
|
|
||||||
ac-mysql:
|
|
||||||
# Optional override that publishes the MySQL port when MYSQL_EXPOSE_PORT=1
|
|
||||||
ports:
|
|
||||||
- "${MYSQL_EXTERNAL_PORT}:${MYSQL_PORT}"
|
|
||||||
@@ -596,7 +596,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- ./.env
|
- ./.env
|
||||||
environment:
|
environment:
|
||||||
MODULES_MANIFEST_PATH: /tmp/config/modules.json
|
MODULES_MANIFEST_PATH: /tmp/config/module-manifest.json
|
||||||
entrypoint: ["/bin/sh"]
|
entrypoint: ["/bin/sh"]
|
||||||
command:
|
command:
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -14,9 +14,27 @@ This guide mirrors the community “Installing AzerothCore using Docker” workf
|
|||||||
|
|
||||||
RealmMaster keeps the familiar `docker-compose.yml` at the repo root. Instead of editing the YAML directly, run `./setup.sh` (see [README → Getting Started](../README.md#getting-started)) to generate `.env`; every setting from storage paths and ports to module toggles lives there. This mirrors the upstream “use docker-compose.override.yml” advice while preserving a single declarative stack.
|
RealmMaster keeps the familiar `docker-compose.yml` at the repo root. Instead of editing the YAML directly, run `./setup.sh` (see [README → Getting Started](../README.md#getting-started)) to generate `.env`; every setting from storage paths and ports to module toggles lives there. This mirrors the upstream “use docker-compose.override.yml” advice while preserving a single declarative stack.
|
||||||
|
|
||||||
- **Security**: databases stay on the internal `azerothcore` bridge and never publish MySQL ports unless you explicitly set `MYSQL_EXPOSE_PORT` in `.env`. Binary logging is disabled via `MYSQL_DISABLE_BINLOG=1`, matching the upstream recommendation for playerbots.
|
- **Security**: databases stay on the internal `azerothcore` bridge and never publish MySQL ports unless you explicitly set `COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=1` in `.env`. Binary logging is disabled via `MYSQL_DISABLE_BINLOG=1`, matching the upstream recommendation for playerbots.
|
||||||
- **Storage**: bind mounts map to `storage/` and `local-storage/`, ensuring data survives container rebuilds just like the original bind-mount instructions. `ac-volume-init` and `ac-storage-init` bootstrap ownership so you do not need to chown paths manually.
|
- **Storage**: bind mounts map to `storage/` and `local-storage/`, ensuring data survives container rebuilds just like the original bind-mount instructions. `ac-volume-init` and `ac-storage-init` bootstrap ownership so you do not need to chown paths manually.
|
||||||
- **Networks & profiles**: all services share the `azerothcore` bridge, and Compose profiles (`services-standard`, `services-playerbots`, `services-modules`, `tools`) let you enable only what you need, similar to copying multiple override files upstream.
|
- **Networks & profiles**: all services share the `azerothcore` bridge, and Compose profiles (`services-standard`, `services-playerbots`, `services-modules`, `tools`) let you enable only what you need, similar to copying multiple override files upstream.
|
||||||
|
- **Override toggles**: drop-in files under `compose-overrides/` (like `mysql-expose.yml` for port exposure or `worldserver-debug-logging.yml` for verbose logs) can be activated by setting `COMPOSE_OVERRIDE_<NAME>_ENABLED=1` in `.env`, so you can extend the stack without editing the main compose file.
|
||||||
|
- **Module manifest**: all module metadata lives in `config/module-manifest.json`; presets surfaced in `setup.sh` come from `config/module-profiles/*.json`, so you can adapt the same workflow the upstream document used by editing those files.
|
||||||
|
|
||||||
|
### Override Examples
|
||||||
|
|
||||||
|
RealmMaster ships with two opt-in overrides to demonstrate the pattern:
|
||||||
|
|
||||||
|
- `compose-overrides/mysql-expose.yml` (`COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=1`) publishes MySQL on `${MYSQL_EXTERNAL_PORT}` for IDEs or external tooling.
|
||||||
|
- `compose-overrides/worldserver-debug-logging.yml` (`COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=1`) bumps `AC_LOG_LEVEL` to `3` across every worldserver profile for troubleshooting.
|
||||||
|
|
||||||
|
Add your own overrides by dropping a `.yml` file into `compose-overrides/` with a `# override-flag: ...` header and toggling the matching env flag. All project scripts automatically include enabled overrides, so the workflow mirrors the upstream “override file” approach without manual compose arguments.
|
||||||
|
|
||||||
|
### Module Layout
|
||||||
|
|
||||||
|
- **Manifest**: `config/module-manifest.json` tracks every supported module (type, repo, dependencies). Edit this if you need to add or update modules—`scripts/modules.py` and all container helpers consume it automatically.
|
||||||
|
- **Presets**: `config/module-profiles/*.json` replaces the old `profiles/*.json`. Each preset defines a `modules` list plus optional `label/description/order`, and `setup.sh` surfaces them in the module-selection menu or via `--module-config <name>`.
|
||||||
|
|
||||||
|
Because the manifest/preset locations mirror the upstream structure conceptually, experienced users can jump straight into editing those files without re-learning the workflow.
|
||||||
|
|
||||||
Example excerpt (trimmed for clarity):
|
Example excerpt (trimmed for clarity):
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
def load_module_state(root: Path) -> dict:
|
def load_module_state(root: Path) -> dict:
|
||||||
env_path = root / ".env"
|
env_path = root / ".env"
|
||||||
manifest_path = root / "config" / "modules.json"
|
manifest_path = root / "config" / "module-manifest.json"
|
||||||
modules_py = root / "scripts" / "modules.py"
|
modules_py = root / "scripts" / "modules.py"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ set -euo pipefail
|
|||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
|
||||||
DEFAULT_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
DEFAULT_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
||||||
ENV_FILE="$ROOT_DIR/.env"
|
ENV_FILE="$ROOT_DIR/.env"
|
||||||
|
source "$ROOT_DIR/scripts/lib/compose_overrides.sh"
|
||||||
declare -a COMPOSE_FILE_ARGS=()
|
declare -a COMPOSE_FILE_ARGS=()
|
||||||
|
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
@@ -46,15 +47,7 @@ resolve_project_name(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_compose_files(){
|
init_compose_files(){
|
||||||
COMPOSE_FILE_ARGS=(-f "$DEFAULT_COMPOSE_FILE")
|
compose_overrides::build_compose_args "$ROOT_DIR" "$ENV_FILE" "$DEFAULT_COMPOSE_FILE" COMPOSE_FILE_ARGS
|
||||||
if [ "$(read_env MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
|
||||||
local extra_file="$ROOT_DIR/docker-compose.mysql-expose.yml"
|
|
||||||
if [ -f "$extra_file" ]; then
|
|
||||||
COMPOSE_FILE_ARGS+=(-f "$extra_file")
|
|
||||||
else
|
|
||||||
warn "MYSQL_EXPOSE_PORT=1 but $extra_file missing; skipping port override."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_compose_files
|
init_compose_files
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
# Post-Install Hooks Refactoring Summary
|
|
||||||
|
|
||||||
## What Was Accomplished
|
|
||||||
|
|
||||||
### 1. **Legacy System Issues**
|
|
||||||
- Hardcoded hooks in `manage-modules.sh` (only 2 implemented)
|
|
||||||
- 26 undefined hooks from Eluna modules causing warnings
|
|
||||||
- No extensibility or maintainability
|
|
||||||
|
|
||||||
### 2. **New Architecture Implemented**
|
|
||||||
|
|
||||||
#### **External Hook Scripts** (`scripts/hooks/`)
|
|
||||||
- `copy-standard-lua` - Generic Lua script copying for Eluna modules
|
|
||||||
- `copy-aio-lua` - AIO-specific Lua script handling
|
|
||||||
- `mod-ale-patches` - mod-ale compatibility patches
|
|
||||||
- `black-market-setup` - Black Market specific setup
|
|
||||||
- `README.md` - Complete documentation
|
|
||||||
|
|
||||||
#### **Manifest-Driven Configuration**
|
|
||||||
- All hooks now defined in `config/modules.json`
|
|
||||||
- Standardized hook names (kebab-case)
|
|
||||||
- No more undefined hooks
|
|
||||||
|
|
||||||
#### **Refactored Hook Runner** (`manage-modules.sh`)
|
|
||||||
- External script execution with environment variables
|
|
||||||
- Proper error handling (exit codes 0/1/2)
|
|
||||||
- Environment cleanup
|
|
||||||
- Removed legacy fallback code
|
|
||||||
|
|
||||||
### 3. **Hook Mapping Applied**
|
|
||||||
- **24 Eluna modules** → `copy-standard-lua`
|
|
||||||
- **2 AIO modules** → `copy-aio-lua`
|
|
||||||
- **1 mod-ale module** → `mod-ale-patches`
|
|
||||||
- **1 Black Market module** → `black-market-setup`
|
|
||||||
|
|
||||||
### 4. **Benefits Achieved**
|
|
||||||
- ✅ **Maintainable** - Hooks are separate, reusable scripts
|
|
||||||
- ✅ **Extensible** - Easy to add new hooks without code changes
|
|
||||||
- ✅ **Reliable** - No more undefined hook warnings
|
|
||||||
- ✅ **Documented** - Clear interface and usage patterns
|
|
||||||
- ✅ **Clean** - Removed legacy code and hardcoded cases
|
|
||||||
|
|
||||||
## Files Modified
|
|
||||||
- `scripts/hooks/` (new directory with 5 files)
|
|
||||||
- `scripts/manage-modules.sh` (refactored hook runner)
|
|
||||||
- `config/modules.json` (updated all 28 hook definitions)
|
|
||||||
|
|
||||||
## Testing Ready
|
|
||||||
The system is ready for testing with the modules container to ensure all Lua scripts are properly copied to `/azerothcore/lua_scripts` during module installation.
|
|
||||||
101
scripts/lib/compose_overrides.sh
Normal file
101
scripts/lib/compose_overrides.sh
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Helper utilities for dynamically including docker compose override files
|
||||||
|
# based on FEATURE_NAME_ENABLED style environment flags.
|
||||||
|
|
||||||
|
compose_overrides::trim() {
|
||||||
|
local value="$1"
|
||||||
|
# shellcheck disable=SC2001
|
||||||
|
value="$(echo "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||||
|
printf '%s' "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::derive_flag_from_name() {
|
||||||
|
local file="$1"
|
||||||
|
local base
|
||||||
|
base="$(basename "$file")"
|
||||||
|
base="${base%.*}"
|
||||||
|
base="${base//[^[:alnum:]]/_}"
|
||||||
|
base="${base^^}"
|
||||||
|
printf 'COMPOSE_OVERRIDE_%s_ENABLED' "$base"
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::extract_tag() {
|
||||||
|
local file="$1" tag="$2"
|
||||||
|
local line
|
||||||
|
line="$(grep -m1 "^# *${tag}:" "$file" 2>/dev/null || true)"
|
||||||
|
if [ -z "$line" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
line="${line#*:}"
|
||||||
|
compose_overrides::trim "$line"
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::extract_all_tags() {
|
||||||
|
local file="$1" tag="$2"
|
||||||
|
grep "^# *${tag}:" "$file" 2>/dev/null | cut -d':' -f2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::read_env_value() {
|
||||||
|
local env_path="$1" key="$2" default="${3:-}"
|
||||||
|
local value=""
|
||||||
|
if [ -f "$env_path" ]; then
|
||||||
|
value="$(grep -E "^${key}=" "$env_path" | tail -n1 | cut -d'=' -f2- | tr -d '\r')"
|
||||||
|
fi
|
||||||
|
if [ -z "$value" ]; then
|
||||||
|
value="$default"
|
||||||
|
fi
|
||||||
|
printf '%s' "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::list_enabled_files() {
|
||||||
|
local root_dir="$1" env_path="$2" result_var="$3"
|
||||||
|
local overrides_dir="${root_dir}/compose-overrides"
|
||||||
|
local -n __result="$result_var"
|
||||||
|
__result=()
|
||||||
|
|
||||||
|
[ -d "$overrides_dir" ] || return 0
|
||||||
|
|
||||||
|
local -a override_files=()
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
override_files+=("$file")
|
||||||
|
done < <(find "$overrides_dir" -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 | sort -z)
|
||||||
|
|
||||||
|
local file flag flag_value legacy_default legacy_flags legacy_flag
|
||||||
|
for file in "${override_files[@]}"; do
|
||||||
|
flag="$(compose_overrides::extract_tag "$file" "override-flag" || true)"
|
||||||
|
if [ -z "$flag" ]; then
|
||||||
|
flag="$(compose_overrides::derive_flag_from_name "$file")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
legacy_default="0"
|
||||||
|
legacy_flags="$(compose_overrides::extract_all_tags "$file" "legacy-flag" || true)"
|
||||||
|
if [ -n "$legacy_flags" ]; then
|
||||||
|
while IFS= read -r legacy_flag; do
|
||||||
|
[ -z "$legacy_flag" ] && continue
|
||||||
|
legacy_default="$(compose_overrides::read_env_value "$env_path" "$legacy_flag" "$legacy_default")"
|
||||||
|
# Stop at first legacy flag that yields a value
|
||||||
|
if [ -n "$legacy_default" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done <<< "$legacy_flags"
|
||||||
|
fi
|
||||||
|
|
||||||
|
flag_value="$(compose_overrides::read_env_value "$env_path" "$flag" "$legacy_default")"
|
||||||
|
if [ "$flag_value" = "1" ]; then
|
||||||
|
__result+=("$file")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
compose_overrides::build_compose_args() {
|
||||||
|
local root_dir="$1" env_path="$2" default_compose="$3" result_var="$4"
|
||||||
|
local -n __result="$result_var"
|
||||||
|
__result=(-f "$default_compose")
|
||||||
|
|
||||||
|
local -a enabled_files=()
|
||||||
|
compose_overrides::list_enabled_files "$root_dir" "$env_path" enabled_files
|
||||||
|
for file in "${enabled_files[@]}"; do
|
||||||
|
__result+=(-f "$file")
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -130,7 +130,7 @@ ensure_module_metadata(){
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
local manifest_path="${MANIFEST_PATH:-${MODULES_MANIFEST_PATH:-/tmp/config/modules.json}}"
|
local manifest_path="${MANIFEST_PATH:-${MODULES_MANIFEST_PATH:-/tmp/config/module-manifest.json}}"
|
||||||
local env_path="${ENV_PATH:-${MODULES_ENV_PATH:-/tmp/.env}}"
|
local env_path="${ENV_PATH:-${MODULES_ENV_PATH:-/tmp/.env}}"
|
||||||
local state_env_candidate="${STATE_DIR:-${MODULES_ROOT:-/modules}}/modules.env"
|
local state_env_candidate="${STATE_DIR:-${MODULES_ROOT:-/modules}}/modules.env"
|
||||||
if [ -f "$state_env_candidate" ]; then
|
if [ -f "$state_env_candidate" ]; then
|
||||||
|
|||||||
@@ -55,22 +55,22 @@ resolve_manifest_path(){
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
local candidate
|
local candidate
|
||||||
candidate="$PROJECT_ROOT/config/modules.json"
|
candidate="$PROJECT_ROOT/config/module-manifest.json"
|
||||||
if [ -f "$candidate" ]; then
|
if [ -f "$candidate" ]; then
|
||||||
echo "$candidate"
|
echo "$candidate"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
candidate="$SCRIPT_DIR/../config/modules.json"
|
candidate="$SCRIPT_DIR/../config/module-manifest.json"
|
||||||
if [ -f "$candidate" ]; then
|
if [ -f "$candidate" ]; then
|
||||||
echo "$candidate"
|
echo "$candidate"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
candidate="/tmp/config/modules.json"
|
candidate="/tmp/config/module-manifest.json"
|
||||||
if [ -f "$candidate" ]; then
|
if [ -f "$candidate" ]; then
|
||||||
echo "$candidate"
|
echo "$candidate"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
err "Unable to locate module manifest (set MODULES_MANIFEST_PATH or ensure config/modules.json exists)"
|
err "Unable to locate module manifest (set MODULES_MANIFEST_PATH or ensure config/module-manifest.json exists)"
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_git_config(){
|
setup_git_config(){
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
Module manifest helper.
|
Module manifest helper.
|
||||||
|
|
||||||
Reads config/modules.json and .env to produce canonical module state that
|
Reads config/module-manifest.json and .env to produce canonical module state that
|
||||||
downstream shell scripts can consume for staging, rebuild detection, and
|
downstream shell scripts can consume for staging, rebuild detection, and
|
||||||
dependency validation.
|
dependency validation.
|
||||||
"""
|
"""
|
||||||
@@ -466,8 +466,8 @@ def configure_parser() -> argparse.ArgumentParser:
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--manifest",
|
"--manifest",
|
||||||
default="config/modules.json",
|
default="config/module-manifest.json",
|
||||||
help="Path to module manifest (default: config/modules.json)",
|
help="Path to module manifest (default: config/module-manifest.json)",
|
||||||
)
|
)
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ ensure_module_state(){
|
|||||||
local storage_root
|
local storage_root
|
||||||
storage_root="$(resolve_local_storage_path)"
|
storage_root="$(resolve_local_storage_path)"
|
||||||
MODULE_STATE_DIR="${storage_root}/modules"
|
MODULE_STATE_DIR="${storage_root}/modules"
|
||||||
if ! python3 "$MODULE_HELPER" --env-path "$ENV_FILE" --manifest "$PROJECT_DIR/config/modules.json" generate --output-dir "$MODULE_STATE_DIR"; then
|
if ! python3 "$MODULE_HELPER" --env-path "$ENV_FILE" --manifest "$PROJECT_DIR/config/module-manifest.json" generate --output-dir "$MODULE_STATE_DIR"; then
|
||||||
echo "❌ Module manifest validation failed. See details above."
|
echo "❌ Module manifest validation failed. See details above."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -463,7 +463,7 @@ remove_sentinel(){
|
|||||||
fi
|
fi
|
||||||
if command -v docker >/dev/null 2>&1; then
|
if command -v docker >/dev/null 2>&1; then
|
||||||
local db_image
|
local db_image
|
||||||
db_image="$(read_env AC_DB_IMPORT_IMAGE "acore/ac-wotlk-db-import:14.0.0-dev")"
|
db_image="$(read_env AC_DB_IMPORT_IMAGE "acore/ac-wotlk-db-import:master")"
|
||||||
if docker image inspect "$db_image" >/dev/null 2>&1; then
|
if docker image inspect "$db_image" >/dev/null 2>&1; then
|
||||||
local mount_dir
|
local mount_dir
|
||||||
mount_dir="$(dirname "$sentinel_path")"
|
mount_dir="$(dirname "$sentinel_path")"
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
ENV_FILE="$PROJECT_DIR/.env"
|
ENV_FILE="$PROJECT_DIR/.env"
|
||||||
DEFAULT_COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
DEFAULT_COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
||||||
EXTRA_COMPOSE_FILE="$PROJECT_DIR/docker-compose.mysql-expose.yml"
|
source "$PROJECT_DIR/scripts/lib/compose_overrides.sh"
|
||||||
|
|
||||||
usage(){
|
usage(){
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
@@ -116,12 +116,10 @@ resolve_project_name(){
|
|||||||
|
|
||||||
if [ -z "${COMPOSE_FILE:-}" ]; then
|
if [ -z "${COMPOSE_FILE:-}" ]; then
|
||||||
compose_files=("$DEFAULT_COMPOSE_FILE")
|
compose_files=("$DEFAULT_COMPOSE_FILE")
|
||||||
if [ "$(read_env MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
declare -a enabled_overrides=()
|
||||||
if [ -f "$EXTRA_COMPOSE_FILE" ]; then
|
compose_overrides::list_enabled_files "$PROJECT_DIR" "$ENV_FILE" enabled_overrides
|
||||||
compose_files+=("$EXTRA_COMPOSE_FILE")
|
if [ "${#enabled_overrides[@]}" -gt 0 ]; then
|
||||||
else
|
compose_files+=("${enabled_overrides[@]}")
|
||||||
echo "⚠️ MYSQL_EXPOSE_PORT=1 but ${EXTRA_COMPOSE_FILE} not found; continuing without port exposure override."
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
COMPOSE_FILE="$(IFS=:; echo "${compose_files[*]}")"
|
COMPOSE_FILE="$(IFS=:; echo "${compose_files[*]}")"
|
||||||
export COMPOSE_FILE
|
export COMPOSE_FILE
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from pathlib import Path
|
|||||||
root = Path(sys.argv[1])
|
root = Path(sys.argv[1])
|
||||||
modules_py = root / "scripts" / "modules.py"
|
modules_py = root / "scripts" / "modules.py"
|
||||||
env_path = root / ".env"
|
env_path = root / ".env"
|
||||||
manifest_path = root / "config" / "modules.json"
|
manifest_path = root / "config" / "module-manifest.json"
|
||||||
|
|
||||||
state = json.loads(subprocess.check_output([
|
state = json.loads(subprocess.check_output([
|
||||||
sys.executable,
|
sys.executable,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ err(){ echo -e "${RED}❌ $*${NC}"; }
|
|||||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
||||||
ENV_FILE=""
|
ENV_FILE=""
|
||||||
|
source "$PROJECT_DIR/scripts/lib/compose_overrides.sh"
|
||||||
PROFILES=(db services-standard client-data modules tools)
|
PROFILES=(db services-standard client-data modules tools)
|
||||||
SKIP_DEPLOY=false
|
SKIP_DEPLOY=false
|
||||||
QUICK=false
|
QUICK=false
|
||||||
@@ -73,15 +74,13 @@ run_compose(){
|
|||||||
compose_args+=(--env-file "$ENV_FILE")
|
compose_args+=(--env-file "$ENV_FILE")
|
||||||
fi
|
fi
|
||||||
compose_args+=(-f "$COMPOSE_FILE")
|
compose_args+=(-f "$COMPOSE_FILE")
|
||||||
if [ "$(read_env_value MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
local env_path
|
||||||
local extra_file
|
env_path="$(env_file_path)"
|
||||||
extra_file="$(dirname "$COMPOSE_FILE")/docker-compose.mysql-expose.yml"
|
declare -a enabled_overrides=()
|
||||||
if [ -f "$extra_file" ]; then
|
compose_overrides::list_enabled_files "$PROJECT_DIR" "$env_path" enabled_overrides
|
||||||
compose_args+=(-f "$extra_file")
|
for file in "${enabled_overrides[@]}"; do
|
||||||
else
|
compose_args+=(-f "$file")
|
||||||
warn "MYSQL_EXPOSE_PORT=1 but ${extra_file} missing; skipping port exposure override."
|
done
|
||||||
fi
|
|
||||||
fi
|
|
||||||
docker compose "${compose_args[@]}" "$@"
|
docker compose "${compose_args[@]}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
setup.sh
27
setup.sh
@@ -68,11 +68,12 @@ declare -A TEMPLATE_VALUE_MAP=(
|
|||||||
[DEFAULT_AUTH_PORT]=AUTH_EXTERNAL_PORT
|
[DEFAULT_AUTH_PORT]=AUTH_EXTERNAL_PORT
|
||||||
[DEFAULT_SOAP_PORT]=SOAP_EXTERNAL_PORT
|
[DEFAULT_SOAP_PORT]=SOAP_EXTERNAL_PORT
|
||||||
[DEFAULT_MYSQL_PORT]=MYSQL_EXTERNAL_PORT
|
[DEFAULT_MYSQL_PORT]=MYSQL_EXTERNAL_PORT
|
||||||
[DEFAULT_MYSQL_EXPOSE_PORT]=MYSQL_EXPOSE_PORT
|
|
||||||
[DEFAULT_PLAYERBOT_MIN]=PLAYERBOT_MIN_BOTS
|
[DEFAULT_PLAYERBOT_MIN]=PLAYERBOT_MIN_BOTS
|
||||||
[DEFAULT_PLAYERBOT_MAX]=PLAYERBOT_MAX_BOTS
|
[DEFAULT_PLAYERBOT_MAX]=PLAYERBOT_MAX_BOTS
|
||||||
[DEFAULT_LOCAL_STORAGE]=STORAGE_PATH
|
[DEFAULT_LOCAL_STORAGE]=STORAGE_PATH
|
||||||
[DEFAULT_BACKUP_PATH]=BACKUP_PATH
|
[DEFAULT_BACKUP_PATH]=BACKUP_PATH
|
||||||
|
[DEFAULT_COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED]=COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED
|
||||||
|
[DEFAULT_COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED]=COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED
|
||||||
[PERMISSION_LOCAL_USER]=DEFAULT_PERMISSION_LOCAL_USER
|
[PERMISSION_LOCAL_USER]=DEFAULT_PERMISSION_LOCAL_USER
|
||||||
[PERMISSION_NFS_USER]=DEFAULT_PERMISSION_NFS_USER
|
[PERMISSION_NFS_USER]=DEFAULT_PERMISSION_NFS_USER
|
||||||
[DEFAULT_CUSTOM_UID]=DEFAULT_CUSTOM_UID
|
[DEFAULT_CUSTOM_UID]=DEFAULT_CUSTOM_UID
|
||||||
@@ -351,7 +352,7 @@ EOF
|
|||||||
# Module metadata / defaults
|
# Module metadata / defaults
|
||||||
# ==============================
|
# ==============================
|
||||||
|
|
||||||
MODULE_MANIFEST_PATH="$SCRIPT_DIR/config/modules.json"
|
MODULE_MANIFEST_PATH="$SCRIPT_DIR/config/module-manifest.json"
|
||||||
MODULE_MANIFEST_HELPER="$SCRIPT_DIR/scripts/setup_manifest.py"
|
MODULE_MANIFEST_HELPER="$SCRIPT_DIR/scripts/setup_manifest.py"
|
||||||
MODULE_PROFILES_HELPER="$SCRIPT_DIR/scripts/setup_profiles.py"
|
MODULE_PROFILES_HELPER="$SCRIPT_DIR/scripts/setup_profiles.py"
|
||||||
ENV_TEMPLATE_FILE="$SCRIPT_DIR/.env.template"
|
ENV_TEMPLATE_FILE="$SCRIPT_DIR/.env.template"
|
||||||
@@ -576,7 +577,7 @@ Options:
|
|||||||
--backup-retention-hours N Hourly backup retention (default 6)
|
--backup-retention-hours N Hourly backup retention (default 6)
|
||||||
--backup-daily-time HH Daily backup hour 00-23 (default 09)
|
--backup-daily-time HH Daily backup hour 00-23 (default 09)
|
||||||
--module-mode MODE suggested, playerbots, manual, or none
|
--module-mode MODE suggested, playerbots, manual, or none
|
||||||
--module-config NAME Use preset NAME from profiles/<NAME>.json
|
--module-config NAME Use preset NAME from config/module-profiles/<NAME>.json
|
||||||
--enable-modules LIST Comma-separated module list (MODULE_* or shorthand)
|
--enable-modules LIST Comma-separated module list (MODULE_* or shorthand)
|
||||||
--playerbot-enabled 0|1 Override PLAYERBOT_ENABLED flag
|
--playerbot-enabled 0|1 Override PLAYERBOT_ENABLED flag
|
||||||
--playerbot-min-bots N Override PLAYERBOT_MIN_BOTS value
|
--playerbot-min-bots N Override PLAYERBOT_MIN_BOTS value
|
||||||
@@ -935,7 +936,7 @@ fi
|
|||||||
declare -A MODULE_PRESET_LABELS=()
|
declare -A MODULE_PRESET_LABELS=()
|
||||||
declare -A MODULE_PRESET_DESCRIPTIONS=()
|
declare -A MODULE_PRESET_DESCRIPTIONS=()
|
||||||
declare -A MODULE_PRESET_ORDER=()
|
declare -A MODULE_PRESET_ORDER=()
|
||||||
local CONFIG_DIR="$SCRIPT_DIR/profiles"
|
local CONFIG_DIR="$SCRIPT_DIR/config/module-profiles"
|
||||||
if [ ! -x "$MODULE_PROFILES_HELPER" ]; then
|
if [ ! -x "$MODULE_PROFILES_HELPER" ]; then
|
||||||
say ERROR "Profile helper not found or not executable at $MODULE_PROFILES_HELPER"
|
say ERROR "Profile helper not found or not executable at $MODULE_PROFILES_HELPER"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -953,7 +954,7 @@ fi
|
|||||||
local missing_presets=0
|
local missing_presets=0
|
||||||
for required_preset in "$DEFAULT_PRESET_SUGGESTED" "$DEFAULT_PRESET_PLAYERBOTS"; do
|
for required_preset in "$DEFAULT_PRESET_SUGGESTED" "$DEFAULT_PRESET_PLAYERBOTS"; do
|
||||||
if [ -z "${MODULE_PRESET_CONFIGS[$required_preset]:-}" ]; then
|
if [ -z "${MODULE_PRESET_CONFIGS[$required_preset]:-}" ]; then
|
||||||
say ERROR "Missing module preset profiles/${required_preset}.json"
|
say ERROR "Missing module preset config/module-profiles/${required_preset}.json"
|
||||||
missing_presets=1
|
missing_presets=1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -1036,7 +1037,7 @@ fi
|
|||||||
else
|
else
|
||||||
pretty_name=$(echo "$preset_name" | tr '_-' ' ' | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1)) substr($i,2)}}1')
|
pretty_name=$(echo "$preset_name" | tr '_-' ' ' | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1)) substr($i,2)}}1')
|
||||||
fi
|
fi
|
||||||
echo "${menu_index}) ${pretty_name} (profiles/${preset_name}.json)"
|
echo "${menu_index}) ${pretty_name} (config/module-profiles/${preset_name}.json)"
|
||||||
MENU_PRESET_INDEX[$menu_index]="$preset_name"
|
MENU_PRESET_INDEX[$menu_index]="$preset_name"
|
||||||
menu_index=$((menu_index + 1))
|
menu_index=$((menu_index + 1))
|
||||||
done
|
done
|
||||||
@@ -1454,7 +1455,8 @@ fi
|
|||||||
HOST_ZONEINFO_PATH=${HOST_ZONEINFO_PATH:-$DEFAULT_HOST_ZONEINFO_PATH}
|
HOST_ZONEINFO_PATH=${HOST_ZONEINFO_PATH:-$DEFAULT_HOST_ZONEINFO_PATH}
|
||||||
MYSQL_INNODB_REDO_LOG_CAPACITY=${MYSQL_INNODB_REDO_LOG_CAPACITY:-$DEFAULT_MYSQL_INNODB_REDO_LOG_CAPACITY}
|
MYSQL_INNODB_REDO_LOG_CAPACITY=${MYSQL_INNODB_REDO_LOG_CAPACITY:-$DEFAULT_MYSQL_INNODB_REDO_LOG_CAPACITY}
|
||||||
MYSQL_RUNTIME_TMPFS_SIZE=${MYSQL_RUNTIME_TMPFS_SIZE:-$DEFAULT_MYSQL_RUNTIME_TMPFS_SIZE}
|
MYSQL_RUNTIME_TMPFS_SIZE=${MYSQL_RUNTIME_TMPFS_SIZE:-$DEFAULT_MYSQL_RUNTIME_TMPFS_SIZE}
|
||||||
MYSQL_EXPOSE_PORT=${MYSQL_EXPOSE_PORT:-$DEFAULT_MYSQL_EXPOSE_PORT}
|
COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=${COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED:-$DEFAULT_COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED}
|
||||||
|
COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=${COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED:-$DEFAULT_COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED}
|
||||||
MYSQL_DISABLE_BINLOG=${MYSQL_DISABLE_BINLOG:-$DEFAULT_MYSQL_DISABLE_BINLOG}
|
MYSQL_DISABLE_BINLOG=${MYSQL_DISABLE_BINLOG:-$DEFAULT_MYSQL_DISABLE_BINLOG}
|
||||||
MYSQL_CONFIG_DIR=${MYSQL_CONFIG_DIR:-$DEFAULT_MYSQL_CONFIG_DIR}
|
MYSQL_CONFIG_DIR=${MYSQL_CONFIG_DIR:-$DEFAULT_MYSQL_CONFIG_DIR}
|
||||||
CLIENT_DATA_PATH=${CLIENT_DATA_PATH:-$DEFAULT_CLIENT_DATA_PATH}
|
CLIENT_DATA_PATH=${CLIENT_DATA_PATH:-$DEFAULT_CLIENT_DATA_PATH}
|
||||||
@@ -1502,6 +1504,12 @@ fi
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
# Generated by ac-compose/setup.sh
|
# Generated by ac-compose/setup.sh
|
||||||
|
|
||||||
|
# Compose overrides (set to 1 to include matching file under compose-overrides/)
|
||||||
|
# mysql-expose.yml -> exposes MySQL externally via COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED
|
||||||
|
# worldserver-debug-logging.yml -> raises log verbosity via COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED
|
||||||
|
COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=$COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED
|
||||||
|
COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=$COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED
|
||||||
|
|
||||||
COMPOSE_PROJECT_NAME=$DEFAULT_COMPOSE_PROJECT_NAME
|
COMPOSE_PROJECT_NAME=$DEFAULT_COMPOSE_PROJECT_NAME
|
||||||
|
|
||||||
STORAGE_PATH=$STORAGE_PATH
|
STORAGE_PATH=$STORAGE_PATH
|
||||||
@@ -1514,9 +1522,8 @@ MYSQL_IMAGE=$DEFAULT_MYSQL_IMAGE
|
|||||||
MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
|
MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
|
||||||
MYSQL_ROOT_HOST=$DEFAULT_MYSQL_ROOT_HOST
|
MYSQL_ROOT_HOST=$DEFAULT_MYSQL_ROOT_HOST
|
||||||
MYSQL_USER=$DEFAULT_MYSQL_USER
|
MYSQL_USER=$DEFAULT_MYSQL_USER
|
||||||
MYSQL_PORT=$DEFAULT_MYSQL_INTERNAL_PORT
|
MYSQL_PORT=$DEFAULT_MYSQL_INTERNAL_PORT
|
||||||
MYSQL_EXTERNAL_PORT=$MYSQL_EXTERNAL_PORT
|
MYSQL_EXTERNAL_PORT=$MYSQL_EXTERNAL_PORT
|
||||||
MYSQL_EXPOSE_PORT=${MYSQL_EXPOSE_PORT:-$DEFAULT_MYSQL_EXPOSE_PORT}
|
|
||||||
MYSQL_DISABLE_BINLOG=${MYSQL_DISABLE_BINLOG:-$DEFAULT_MYSQL_DISABLE_BINLOG}
|
MYSQL_DISABLE_BINLOG=${MYSQL_DISABLE_BINLOG:-$DEFAULT_MYSQL_DISABLE_BINLOG}
|
||||||
MYSQL_CONFIG_DIR=${MYSQL_CONFIG_DIR:-$DEFAULT_MYSQL_CONFIG_DIR}
|
MYSQL_CONFIG_DIR=${MYSQL_CONFIG_DIR:-$DEFAULT_MYSQL_CONFIG_DIR}
|
||||||
MYSQL_CHARACTER_SET=$DEFAULT_MYSQL_CHARACTER_SET
|
MYSQL_CHARACTER_SET=$DEFAULT_MYSQL_CHARACTER_SET
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ AUTH_PORT="$(read_env AUTH_EXTERNAL_PORT)"
|
|||||||
WORLD_PORT="$(read_env WORLD_EXTERNAL_PORT)"
|
WORLD_PORT="$(read_env WORLD_EXTERNAL_PORT)"
|
||||||
SOAP_PORT="$(read_env SOAP_EXTERNAL_PORT)"
|
SOAP_PORT="$(read_env SOAP_EXTERNAL_PORT)"
|
||||||
MYSQL_PORT="$(read_env MYSQL_EXTERNAL_PORT)"
|
MYSQL_PORT="$(read_env MYSQL_EXTERNAL_PORT)"
|
||||||
MYSQL_EXPOSE_PORT="$(read_env MYSQL_EXPOSE_PORT)"
|
MYSQL_EXPOSE_OVERRIDE="$(read_env COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED "$(read_env MYSQL_EXPOSE_PORT "0")")"
|
||||||
PMA_PORT="$(read_env PMA_EXTERNAL_PORT)"
|
PMA_PORT="$(read_env PMA_EXTERNAL_PORT)"
|
||||||
KEIRA_PORT="$(read_env KEIRA3_EXTERNAL_PORT)"
|
KEIRA_PORT="$(read_env KEIRA3_EXTERNAL_PORT)"
|
||||||
ELUNA_ENABLED="$(read_env AC_ELUNA_ENABLED)"
|
ELUNA_ENABLED="$(read_env AC_ELUNA_ENABLED)"
|
||||||
@@ -255,7 +255,7 @@ ports_summary(){
|
|||||||
for i in "${!names[@]}"; do
|
for i in "${!names[@]}"; do
|
||||||
local svc="${names[$i]}"
|
local svc="${names[$i]}"
|
||||||
local port="${ports[$i]}"
|
local port="${ports[$i]}"
|
||||||
if [ "$svc" = "MySQL" ] && [ "${MYSQL_EXPOSE_PORT}" != "1" ]; then
|
if [ "$svc" = "MySQL" ] && [ "${MYSQL_EXPOSE_OVERRIDE}" != "1" ]; then
|
||||||
printf " %-10s %-6s %b○%b not exposed\n" "$svc" "--" "$CYAN" "$NC"
|
printf " %-10s %-6s %b○%b not exposed\n" "$svc" "--" "$CYAN" "$NC"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user