mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 20:34:53 +08:00
feat(Config): Implement configuration severity policy and logging mechanism (#23284)
This commit is contained in:
parent
d58046032b
commit
a05cc525f0
19
.github/workflows/dashboard-ci.yml
vendored
19
.github/workflows/dashboard-ci.yml
vendored
@ -74,11 +74,16 @@ jobs:
|
||||
|
||||
- name: Configure AzerothCore settings
|
||||
run: |
|
||||
# Create basic configuration
|
||||
cp conf/dist/config.sh conf/config.sh
|
||||
# Configure dashboard
|
||||
sed -i 's/MTHREADS=.*/MTHREADS="4"/' conf/config.sh
|
||||
sed -i 's/CBUILD_TESTING=.*/CBUILD_TESTING="ON"/' conf/config.sh
|
||||
touch conf/config.sh
|
||||
echo 'MTHREADS=4' >> conf/config.sh
|
||||
echo 'CBUILD_TESTING=ON' >> conf/config.sh
|
||||
echo 'AC_ENABLE_ROOT_CMAKE_INSTALL=1' >> conf/config.sh
|
||||
echo 'export AC_CONFIG_POLICY=$AC_CONFIG_POLICY_PRESET_ZERO_CONF' >> conf/config.sh
|
||||
echo 'AC_ENABLE_CONF_COPY_ON_INSTALL=0' >> conf/config.sh
|
||||
cat conf/config.sh
|
||||
|
||||
# debug content of AC_CONFIG_POLICY
|
||||
./acore.sh config show AC_CONFIG_POLICY
|
||||
|
||||
- name: Test module commands
|
||||
run: |
|
||||
@ -92,8 +97,6 @@ jobs:
|
||||
./acore.sh module update --all
|
||||
|
||||
- name: Run complete installation (deps, compile, database, client-data)
|
||||
env:
|
||||
AC_ENABLE_ROOT_CMAKE_INSTALL: 1
|
||||
run: |
|
||||
# This runs: install-deps, compile, database setup, client-data download
|
||||
./acore.sh init
|
||||
@ -113,12 +116,14 @@ jobs:
|
||||
|
||||
- name: Test authserver dry-run
|
||||
run: |
|
||||
source ./acore.sh config load
|
||||
cd env/dist/bin
|
||||
timeout 5m ./authserver -dry-run
|
||||
continue-on-error: false
|
||||
|
||||
- name: Test worldserver dry-run
|
||||
run: |
|
||||
source ./acore.sh config load
|
||||
cd env/dist/bin
|
||||
timeout 5m ./worldserver -dry-run
|
||||
continue-on-error: false
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
function registerHooks() { acore_event_registerHooks "$@"; }
|
||||
function runHooks() { acore_event_runHooks "$@"; }
|
||||
|
||||
#shellcheck source=../../conf/dist/config.sh
|
||||
source "$AC_PATH_CONF/dist/config.sh" # include dist to avoid missing conf variables
|
||||
function acore_common_loadConfig() {
|
||||
#shellcheck source=../../conf/dist/config.sh
|
||||
source "$AC_PATH_CONF/dist/config.sh" # include dist to avoid missing conf variables
|
||||
|
||||
# first check if it's defined in env, otherwise use the default
|
||||
USER_CONF_PATH=${USER_CONF_PATH:-"$AC_PATH_CONF/config.sh"}
|
||||
# first check if it's defined in env, otherwise use the default
|
||||
USER_CONF_PATH=${USER_CONF_PATH:-"$AC_PATH_CONF/config.sh"}
|
||||
|
||||
if [ -f "$USER_CONF_PATH" ]; then
|
||||
source "$USER_CONF_PATH" # should overwrite previous
|
||||
else
|
||||
echo "NOTICE: file <$USER_CONF_PATH> not found, we use default configuration only."
|
||||
fi
|
||||
if [ -f "$USER_CONF_PATH" ]; then
|
||||
source "$USER_CONF_PATH" # should overwrite previous
|
||||
else
|
||||
echo "NOTICE: file <$USER_CONF_PATH> not found, we use default configuration only."
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Load modules
|
||||
|
||||
@ -25,4 +25,6 @@ export AC_PATH_MODULES="$AC_PATH_ROOT/modules"
|
||||
|
||||
export AC_PATH_DEPS="$AC_PATH_ROOT/deps"
|
||||
|
||||
export AC_BASH_LIB_PATH="$AC_PATH_DEPS/acore/bash-lib/src"
|
||||
|
||||
export AC_PATH_VAR="$AC_PATH_ROOT/var"
|
||||
|
||||
@ -16,6 +16,8 @@ source "$AC_PATH_DEPS/acore/bash-lib/src/event/hooks.sh"
|
||||
# shellcheck source=./common.sh
|
||||
source "$AC_PATH_SHARED/common.sh"
|
||||
|
||||
acore_common_loadConfig
|
||||
|
||||
if [[ "$OSTYPE" = "msys" ]]; then
|
||||
AC_BINPATH_FULL="$BINPATH"
|
||||
else
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=../../../deps/acore/bash-lib/src/common/boolean.sh
|
||||
source "$AC_BASH_LIB_PATH/common/boolean.sh"
|
||||
|
||||
# Set SUDO variable - one liner
|
||||
SUDO=""
|
||||
|
||||
@ -135,7 +138,8 @@ function comp_compile() {
|
||||
echo "Done"
|
||||
;;
|
||||
linux*|darwin*)
|
||||
local confDir=${CONFDIR:-"$AC_BINPATH_FULL/../etc"}
|
||||
local confDir
|
||||
confDir=${CONFDIR:-"$AC_BINPATH_FULL/../etc"}
|
||||
|
||||
# create the folders before installing to
|
||||
# set the current user and permissions
|
||||
@ -145,6 +149,8 @@ function comp_compile() {
|
||||
mkdir -p "$confDir"
|
||||
mkdir -p "$confDir/modules"
|
||||
|
||||
confDir=$(realpath "$confDir")
|
||||
|
||||
echo "Cmake install..."
|
||||
$SUDO cmake --install . --config $CTYPE
|
||||
|
||||
@ -161,18 +167,25 @@ function comp_compile() {
|
||||
$SUDO setcap cap_sys_nice=eip "$AC_BINPATH_FULL/authserver"
|
||||
fi
|
||||
|
||||
[[ -f "$confDir/worldserver.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
|
||||
[[ -f "$confDir/authserver.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
|
||||
[[ -f "$confDir/dbimport.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
|
||||
|
||||
for f in "$confDir/modules/"*.dist
|
||||
do
|
||||
[[ -e $f ]] || break # handle the case of no *.dist files
|
||||
cp -v --no-clobber "$f" "${f%.dist}";
|
||||
done
|
||||
if ( isTrue "$AC_ENABLE_CONF_COPY_ON_INSTALL" ) then
|
||||
echo "Copying default configuration files to $confDir ..."
|
||||
[[ -f "$confDir/worldserver.conf.dist" && ! -f "$confDir/worldserver.conf" ]] && \
|
||||
cp -v "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
|
||||
[[ -f "$confDir/authserver.conf.dist" && ! -f "$confDir/authserver.conf" ]] && \
|
||||
cp -v "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
|
||||
[[ -f "$confDir/dbimport.conf.dist" && ! -f "$confDir/dbimport.conf" ]] && \
|
||||
cp -v "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
|
||||
|
||||
for f in "$confDir/modules/"*.dist
|
||||
do
|
||||
[[ -e $f ]] || break # handle the case of no *.dist files
|
||||
if [[ ! -f "${f%.dist}" ]]; then
|
||||
echo "Copying module config $(basename "${f%.dist}")"
|
||||
cp -v "$f" "${f%.dist}";
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Done"
|
||||
;;
|
||||
|
||||
9
apps/installer/includes/config/config-main.sh
Normal file
9
apps/installer/includes/config/config-main.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd )
|
||||
|
||||
# shellcheck source=./config.sh
|
||||
source "$CURRENT_PATH/config.sh"
|
||||
|
||||
acore_dash_config "$@"
|
||||
|
||||
60
apps/installer/includes/config/config.sh
Normal file
60
apps/installer/includes/config/config.sh
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd )
|
||||
|
||||
# shellcheck source=../../../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../../../bash_shared/includes.sh"
|
||||
# shellcheck source=../includes.sh
|
||||
source "$CURRENT_PATH/../includes.sh"
|
||||
# shellcheck source=../../../bash_shared/menu_system.sh
|
||||
source "$AC_PATH_APPS/bash_shared/menu_system.sh"
|
||||
|
||||
function acore_dash_configShowValue() {
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: show <VAR_NAME>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local varName="$1"
|
||||
local varValue="${!varName}"
|
||||
if [ -z "$varValue" ]; then
|
||||
echo "$varName is not set."
|
||||
else
|
||||
echo "$varName=$varValue"
|
||||
fi
|
||||
}
|
||||
|
||||
function acore_dash_configLoad() {
|
||||
acore_common_loadConfig
|
||||
echo "Configuration loaded into the current shell session."
|
||||
}
|
||||
|
||||
# Configuration management menu definition
|
||||
# Format: "key|short|description"
|
||||
config_menu_items=(
|
||||
"show|s|Show configuration variable value"
|
||||
"load|l|Load configurations variables within the current shell session"
|
||||
"help|h|Show detailed help"
|
||||
"quit|q|Close this menu"
|
||||
)
|
||||
|
||||
# Menu command handler for configuration operations
|
||||
function handle_config_command() {
|
||||
local key="$1"
|
||||
shift
|
||||
|
||||
case "$key" in
|
||||
"show")
|
||||
acore_dash_configShowValue "$@"
|
||||
;;
|
||||
"load")
|
||||
acore_dash_configLoad
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function acore_dash_config() {
|
||||
menu_run_with_items "CONFIG MANAGER" handle_config_command -- "${config_menu_items[@]}" -- "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
@ -183,3 +183,5 @@ function inst_download_client_data {
|
||||
&& echo "Remove downloaded file" && rm "$zipPath" \
|
||||
&& echo "INSTALLED_VERSION=$VERSION" > "$dataVersionFile"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd )
|
||||
|
||||
# shellcheck source=../../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../../bash_shared/includes.sh"
|
||||
|
||||
AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
||||
@ -9,14 +10,14 @@ AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
||||
J_PATH="$AC_PATH_DEPS/acore/joiner"
|
||||
J_PATH_MODULES="$AC_PATH_MODULES"
|
||||
|
||||
# shellcheck source=../../../deps/acore/joiner/joiner.sh
|
||||
source "$J_PATH/joiner.sh"
|
||||
|
||||
if [ -f "$AC_PATH_INSTALLER/config.sh" ]; then
|
||||
source "$AC_PATH_INSTALLER/config.sh" # should overwrite previous
|
||||
fi
|
||||
|
||||
# shellcheck source=../../compiler/includes/includes.sh
|
||||
source "$AC_PATH_APPS/compiler/includes/includes.sh"
|
||||
|
||||
# shellcheck source=../../../deps/semver_bash/semver.sh
|
||||
source "$AC_PATH_DEPS/semver_bash/semver.sh"
|
||||
|
||||
# shellcheck source=../includes/functions.sh
|
||||
source "$AC_PATH_INSTALLER/includes/functions.sh"
|
||||
|
||||
@ -59,7 +59,6 @@ else
|
||||
C_GREEN=''
|
||||
C_YELLOW=''
|
||||
C_BLUE=''
|
||||
C_MAGENTA=''
|
||||
C_CYAN=''
|
||||
fi
|
||||
|
||||
@ -174,42 +173,8 @@ function inst_module_list() {
|
||||
# Usage: ./acore.sh module <search|install|update|remove> [args...]
|
||||
# ./acore.sh module # Interactive menu
|
||||
function inst_module() {
|
||||
# If no arguments provided, start interactive menu
|
||||
if [[ $# -eq 0 ]]; then
|
||||
menu_run_with_items "MODULE MANAGER" handle_module_command -- "${module_menu_items[@]}" --
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Normalize arguments into an array
|
||||
local tokens=()
|
||||
read -r -a tokens <<< "$*"
|
||||
local cmd="${tokens[0]}"
|
||||
local args=("${tokens[@]:1}")
|
||||
|
||||
case "$cmd" in
|
||||
""|"help"|"-h"|"--help")
|
||||
inst_module_help
|
||||
;;
|
||||
"search"|"s")
|
||||
inst_module_search "${args[@]}"
|
||||
;;
|
||||
"install"|"i")
|
||||
inst_module_install "${args[@]}"
|
||||
;;
|
||||
"update"|"u")
|
||||
inst_module_update "${args[@]}"
|
||||
;;
|
||||
"remove"|"r")
|
||||
inst_module_remove "${args[@]}"
|
||||
;;
|
||||
"list"|"l")
|
||||
inst_module_list "${args[@]}"
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown module command: $cmd. Use 'help' to see available commands."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
menu_run_with_items "MODULE MANAGER" handle_module_command -- "${module_menu_items[@]}" -- "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@ -45,6 +45,7 @@ menu_items=(
|
||||
"docker|dr|Run docker tools"
|
||||
"version|v|Show AzerothCore version"
|
||||
"service-manager|sm|Run service manager to run authserver and worldserver in background"
|
||||
"config|cf|Configuration manager"
|
||||
"quit|q|Exit from this menu"
|
||||
)
|
||||
|
||||
@ -100,6 +101,9 @@ function handle_menu_command() {
|
||||
bash "$AC_PATH_APPS/startup-scripts/src/service-manager.sh" "$@"
|
||||
exit
|
||||
;;
|
||||
"config")
|
||||
bash "$AC_PATH_APPS/installer/includes/config/config-main.sh" "$@"
|
||||
;;
|
||||
"quit")
|
||||
echo "Goodbye!"
|
||||
exit
|
||||
|
||||
@ -751,5 +751,5 @@ EOF
|
||||
|
||||
run inst_module "unknown-command"
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" =~ "Unknown module command" ]]
|
||||
[[ "$output" =~ "Invalid option" ]]
|
||||
}
|
||||
@ -51,6 +51,8 @@ fi
|
||||
while true; do
|
||||
STARTING_TIME=$(date +%s)
|
||||
|
||||
echo "AC_CONFIG_POLICY: $AC_CONFIG_POLICY"
|
||||
|
||||
# Use starter script to launch the binary with all parameters
|
||||
"$STARTER_SCRIPT" "$BINPATH" "$BINFILE" "$GDB_FILE" "$CONFIG" "$SYSLOG" "$SYSERR" "$GDB_ENABLED" "$CRASHES_PATH"
|
||||
|
||||
|
||||
36
conf/dist/config.sh
vendored
36
conf/dist/config.sh
vendored
@ -118,6 +118,12 @@ export CCACHE_DIR=${CCACHE_DIR:-"$AC_PATH_VAR/ccache"}
|
||||
#
|
||||
export AC_ENABLE_ROOT_CMAKE_INSTALL=${AC_ENABLE_ROOT_CMAKE_INSTALL:-0}
|
||||
|
||||
#
|
||||
# Enable copying configuration files on install
|
||||
# Default: 1 (true)
|
||||
#
|
||||
export AC_ENABLE_CONF_COPY_ON_INSTALL=${AC_ENABLE_CONF_COPY_ON_INSTALL:-1}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# GOOGLE PERF TOOLS
|
||||
@ -182,4 +188,34 @@ export MODULES_EXCLUDE_LIST=""
|
||||
NO_COLOR=${NO_COLOR:-}
|
||||
FORCE_COLOR=${FORCE_COLOR:-}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# CONFIGURATION SEVERITY POLICY
|
||||
#
|
||||
# Controls how the core reacts to missing configuration files,
|
||||
# missing/unknown options and invalid values.
|
||||
# The policy string follows the format "key=severity" separated by commas.
|
||||
# Supported severities: skip, warn, error, fatal.
|
||||
# Possible keys: default, missing_file, missing_option, critical_option,
|
||||
# unknown_option, value_error.
|
||||
#
|
||||
# Examples:
|
||||
# export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_DEFAULT"
|
||||
# export AC_CONFIG_POLICY="default=skip,critical_option=fatal,unknown_option=warn"
|
||||
# export AC_CONFIG_POLICY="missing_file=fatal,missing_option=error"
|
||||
#
|
||||
# Presets:
|
||||
# AC_CONFIG_POLICY_PRESET_DEFAULT -> mirrors the core default behaviour
|
||||
# (errors on missing files, fatal on critical)
|
||||
# AC_CONFIG_POLICY_PRESET_ZERO_CONF -> skips non-critical gaps so the core
|
||||
# can boot from environment defaults
|
||||
# AC_CONFIG_POLICY_PRESET_STRICT -> escalates everything to errors/fatals
|
||||
#
|
||||
|
||||
export AC_CONFIG_POLICY_PRESET_ZERO_CONF='default=skip'
|
||||
export AC_CONFIG_POLICY_PRESET_DEFAULT='missing_file=error,missing_option=warn,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
export AC_CONFIG_POLICY_PRESET_STRICT='default=error,missing_file=fatal,missing_option=error,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
|
||||
export AC_CONFIG_POLICY=$AC_CONFIG_POLICY_PRESET_DEFAULT
|
||||
|
||||
|
||||
|
||||
5
deps/acore/bash-lib/src/common/boolean.sh
vendored
Normal file
5
deps/acore/bash-lib/src/common/boolean.sh
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
function isTrue() {
|
||||
local val
|
||||
val=$(echo "$1" | tr '[:upper:]' '[:lower:]')
|
||||
[[ "$val" == "1" || "$val" == "true" || "$val" == "yes" || "$val" == "on" ]]
|
||||
}
|
||||
101
doc/ConfigPolicy.md
Normal file
101
doc/ConfigPolicy.md
Normal file
@ -0,0 +1,101 @@
|
||||
# Configuration Severity Policy
|
||||
|
||||
The configuration loader can decide how strictly it should react when it
|
||||
encounters missing files, undefined options or invalid values. This document
|
||||
describes the available knobs and provides ready-to-use presets.
|
||||
|
||||
## Severity Levels
|
||||
|
||||
Each policy entry maps a **key** to one of the following severities:
|
||||
|
||||
| Severity | Description |
|
||||
|----------|-----------------------------------------------------------------------------|
|
||||
| `skip` | Ignore the problem and continue silently. |
|
||||
| `warn` | Log a warning and continue. |
|
||||
| `error` | Log an error and continue (useful to surface issues without aborting). |
|
||||
| `fatal` | Log a fatal message and abort the process immediately. |
|
||||
|
||||
## Policy Keys
|
||||
|
||||
The following keys can be customised:
|
||||
|
||||
| Key | Applies to |
|
||||
|--------------------|----------------------------------------------------------------------|
|
||||
| `default` | Fallback severity for any key that is not explicitly overridden. |
|
||||
| `missing_file` | Missing or empty configuration files (worldserver.conf, modules, …). |
|
||||
| `missing_option` | Options looked up in code but not present in any config file. |
|
||||
| `critical_option` | Required options (`RealmID`, `*DatabaseInfo`, …). |
|
||||
| `unknown_option` | Options found in optional configs that the core does not recognise. |
|
||||
| `value_error` | Options that cannot be converted to the expected type. |
|
||||
|
||||
> Critical options remain fatal by default to prevent the core from booting with
|
||||
> incomplete database details; you can relax them if required.
|
||||
|
||||
## Configuration Channels
|
||||
|
||||
### `config.sh`
|
||||
|
||||
`conf/dist/config.sh` exposes the `AC_CONFIG_POLICY` variable alongside a few
|
||||
presets:
|
||||
|
||||
```bash
|
||||
# Mirrors the default behaviour (errors, with fatal criticals)
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_DEFAULT"
|
||||
|
||||
# Skip anything non-critical so the core can bootstrap from defaults + env vars
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_ZERO_CONF"
|
||||
|
||||
# Treat everything strictly (useful for CI)
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_STRICT"
|
||||
```
|
||||
|
||||
The presets are defined as:
|
||||
|
||||
```bash
|
||||
AC_CONFIG_POLICY_PRESET_DEFAULT='missing_file=error,missing_option=warn,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
AC_CONFIG_POLICY_PRESET_ZERO_CONF='default=skip,critical_option=fatal,unknown_option=warn,value_error=warn'
|
||||
AC_CONFIG_POLICY_PRESET_STRICT='default=error,missing_file=fatal,missing_option=error,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
```
|
||||
|
||||
Modify or extend these entries to suit your deployment.
|
||||
|
||||
### Environment Variable
|
||||
|
||||
The runtime honours the `AC_CONFIG_POLICY` environment variable, so you can
|
||||
override the policy without editing `config.sh`:
|
||||
|
||||
```bash
|
||||
export AC_CONFIG_POLICY="default=skip,critical_option=fatal"
|
||||
./acore.sh run-worldserver
|
||||
```
|
||||
|
||||
### CLI Override
|
||||
|
||||
Every server/tool executable accepts `--config-policy`:
|
||||
|
||||
```bash
|
||||
./bin/worldserver --config-policy="missing_file=fatal,unknown_option=warn"
|
||||
./bin/authserver --config-policy "$AC_CONFIG_POLICY_PRESET_STRICT"
|
||||
```
|
||||
|
||||
The CLI flag takes precedence over the environment and `config.sh`.
|
||||
|
||||
## Quick Presets
|
||||
|
||||
| Preset | Intended use |
|
||||
|---------------|---------------------------------------------------------------------------|
|
||||
| `legacy` | Default behaviour before this feature (errors for missing files/options). |
|
||||
| `zero-conf` | Zero-touch deployments; rely on defaults/env vars where possible. |
|
||||
| `strict` | Fail-fast in CI or controlled environments. |
|
||||
|
||||
Feel free to clone these presets and store your own variants inside
|
||||
`config.sh` or deployment scripts.
|
||||
|
||||
## Tips
|
||||
|
||||
- Pair `fatal` severities with monitoring so regressions in configuration
|
||||
surface quickly.
|
||||
- When experimenting locally, start with `zero-conf` and elevate specific keys
|
||||
to `error`/`fatal` as you validate your setup.
|
||||
- Remember that number parsing errors (`value_error`) often indicate typos;
|
||||
keep them at least `error` unless you have a very good reason.
|
||||
@ -21,10 +21,14 @@
|
||||
#include "StringFormat.h"
|
||||
#include "Tokenize.h"
|
||||
#include "Util.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -34,13 +38,14 @@ namespace
|
||||
std::unordered_map<std::string /*name*/, std::string /*value*/> _configOptions;
|
||||
std::unordered_map<std::string /*name*/, std::string /*value*/> _envVarCache;
|
||||
std::mutex _configLock;
|
||||
ConfigPolicy _policy;
|
||||
|
||||
std::vector<std::string> _fatalConfigOptions =
|
||||
std::unordered_set<std::string> _criticalConfigOptions =
|
||||
{
|
||||
{ "RealmID" },
|
||||
{ "LoginDatabaseInfo" },
|
||||
{ "WorldDatabaseInfo" },
|
||||
{ "CharacterDatabaseInfo" },
|
||||
"RealmID",
|
||||
"LoginDatabaseInfo",
|
||||
"WorldDatabaseInfo",
|
||||
"CharacterDatabaseInfo",
|
||||
};
|
||||
|
||||
// Check system configs like *server.conf*
|
||||
@ -62,6 +67,29 @@ namespace
|
||||
return foundAppender != std::string_view::npos || foundLogger != std::string_view::npos;
|
||||
}
|
||||
|
||||
Optional<ConfigSeverity> ParseSeverity(std::string_view value)
|
||||
{
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
std::string lowered(value);
|
||||
std::transform(lowered.begin(), lowered.end(), lowered.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
if (lowered == "skip")
|
||||
return ConfigSeverity::Skip;
|
||||
|
||||
if (lowered == "warn" || lowered == "warning")
|
||||
return ConfigSeverity::Warn;
|
||||
|
||||
if (lowered == "error")
|
||||
return ConfigSeverity::Error;
|
||||
|
||||
if (lowered == "fatal" || lowered == "abort" || lowered == "panic")
|
||||
return ConfigSeverity::Fatal;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void PrintError(std::string_view filename, Format&& fmt, Args&& ... args)
|
||||
{
|
||||
@ -77,6 +105,138 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void LogWithSeverity(ConfigSeverity severity, std::string_view filename, Format&& fmt, Args&&... args)
|
||||
{
|
||||
std::string message = Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...);
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
case ConfigSeverity::Skip:
|
||||
return;
|
||||
case ConfigSeverity::Warn:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_WARN("server.loading", message);
|
||||
return;
|
||||
}
|
||||
case ConfigSeverity::Error:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_ERROR("server.loading", message);
|
||||
return;
|
||||
}
|
||||
case ConfigSeverity::Fatal:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_FATAL("server.loading", message);
|
||||
ABORT(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPolicy ApplyPolicyString(ConfigPolicy policy, std::string_view input)
|
||||
{
|
||||
if (input.empty())
|
||||
return policy;
|
||||
|
||||
std::vector<std::pair<std::string, ConfigSeverity>> overrides;
|
||||
Optional<ConfigSeverity> defaultOverride;
|
||||
|
||||
std::string tokenBuffer(input);
|
||||
for (std::string_view rawToken : Acore::Tokenize(tokenBuffer, ',', false))
|
||||
{
|
||||
std::string token = Acore::String::Trim(std::string(rawToken), std::locale());
|
||||
if (token.empty())
|
||||
continue;
|
||||
|
||||
auto separator = token.find('=');
|
||||
if (separator == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string key = Acore::String::Trim(token.substr(0, separator), std::locale());
|
||||
std::string value = Acore::String::Trim(token.substr(separator + 1), std::locale());
|
||||
|
||||
if (key.empty() || value.empty())
|
||||
continue;
|
||||
|
||||
auto severity = ParseSeverity(value);
|
||||
if (!severity)
|
||||
continue;
|
||||
|
||||
std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
if (key == "default")
|
||||
{
|
||||
defaultOverride = severity;
|
||||
continue;
|
||||
}
|
||||
|
||||
overrides.emplace_back(std::move(key), *severity);
|
||||
}
|
||||
|
||||
if (defaultOverride)
|
||||
{
|
||||
policy.defaultSeverity = *defaultOverride;
|
||||
policy.missingFileSeverity = *defaultOverride;
|
||||
policy.missingOptionSeverity = *defaultOverride;
|
||||
policy.criticalOptionSeverity = *defaultOverride;
|
||||
policy.unknownOptionSeverity = *defaultOverride;
|
||||
policy.valueErrorSeverity = *defaultOverride;
|
||||
}
|
||||
|
||||
for (auto const& [key, severity] : overrides)
|
||||
{
|
||||
if (key == "missing_file" || key == "file")
|
||||
policy.missingFileSeverity = severity;
|
||||
else if (key == "missing_option" || key == "option")
|
||||
policy.missingOptionSeverity = severity;
|
||||
else if (key == "critical_option" || key == "critical")
|
||||
policy.criticalOptionSeverity = severity;
|
||||
else if (key == "unknown_option" || key == "unknown")
|
||||
policy.unknownOptionSeverity = severity;
|
||||
else if (key == "value_error" || key == "value")
|
||||
policy.valueErrorSeverity = severity;
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
ConfigPolicy ApplyPolicyFromArgs(ConfigPolicy policy, std::vector<std::string> const& args)
|
||||
{
|
||||
for (std::size_t i = 0; i < args.size(); ++i)
|
||||
{
|
||||
std::string const& arg = args[i];
|
||||
std::string_view value;
|
||||
|
||||
constexpr std::string_view shortOpt = "--config-policy";
|
||||
|
||||
if (arg.rfind(shortOpt, 0) == 0)
|
||||
{
|
||||
if (arg.size() == shortOpt.size() && (i + 1) < args.size())
|
||||
{
|
||||
value = args[i + 1];
|
||||
++i;
|
||||
}
|
||||
else if (arg.size() > shortOpt.size() && arg[shortOpt.size()] == '=')
|
||||
{
|
||||
value = std::string_view(arg).substr(shortOpt.size() + 1);
|
||||
}
|
||||
|
||||
if (!value.empty())
|
||||
policy = ApplyPolicyString(policy, value);
|
||||
}
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
void AddKey(std::string const& optionName, std::string const& optionKey, std::string_view fileName, bool isOptional, [[maybe_unused]] bool isReload)
|
||||
{
|
||||
auto const& itr = _configOptions.find(optionName);
|
||||
@ -86,7 +246,7 @@ namespace
|
||||
{
|
||||
if (!IsLoggingSystemOptions(optionName) && !isReload)
|
||||
{
|
||||
PrintError(fileName, "> Config::LoadFile: Found incorrect option '{}' in config file '{}'. Skip", optionName, fileName);
|
||||
LogWithSeverity(_policy.unknownOptionSeverity, fileName, "> Config::LoadFile: Found incorrect option '{}' in config file '{}'. Skip", optionName, fileName);
|
||||
|
||||
#ifdef CONFIG_ABORT_INCORRECT_OPTIONS
|
||||
ABORT("> Core can't start if found incorrect options");
|
||||
@ -111,13 +271,10 @@ namespace
|
||||
|
||||
if (in.fail())
|
||||
{
|
||||
if (isOptional)
|
||||
{
|
||||
// No display erorr if file optional
|
||||
return false;
|
||||
}
|
||||
|
||||
throw ConfigException(Acore::StringFormat("Config::LoadFile: Failed open {}file '{}'", isOptional ? "optional " : "", file));
|
||||
ConfigSeverity severity = isOptional ? ConfigSeverity::Skip : _policy.missingFileSeverity;
|
||||
LogWithSeverity(severity, file, "> Config::LoadFile: Failed open {}file '{}'", isOptional ? "optional " : "", file);
|
||||
// Treat SKIP as a successful no-op so the app can proceed
|
||||
return severity == ConfigSeverity::Skip;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
@ -181,13 +338,10 @@ namespace
|
||||
// No lines read
|
||||
if (!count)
|
||||
{
|
||||
if (isOptional)
|
||||
{
|
||||
// No display erorr if file optional
|
||||
return false;
|
||||
}
|
||||
|
||||
throw ConfigException(Acore::StringFormat("Config::LoadFile: Empty file '{}'", file));
|
||||
ConfigSeverity severity = isOptional ? ConfigSeverity::Skip : _policy.missingFileSeverity;
|
||||
LogWithSeverity(severity, file, "> Config::LoadFile: Empty file '{}'", file);
|
||||
// Treat SKIP as a successful no-op
|
||||
return severity == ConfigSeverity::Skip;
|
||||
}
|
||||
|
||||
// Add correct keys if file load without errors
|
||||
@ -382,7 +536,6 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
std::string strValue;
|
||||
|
||||
auto const& itr = _configOptions.find(name);
|
||||
bool fatalConfig = false;
|
||||
bool notFound = itr == _configOptions.end();
|
||||
auto envVarName = GetEnvVarName(name);
|
||||
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
|
||||
@ -401,23 +554,23 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
for (std::string s : _fatalConfigOptions)
|
||||
if (s == name)
|
||||
{
|
||||
fatalConfig = true;
|
||||
break;
|
||||
}
|
||||
bool isCritical = _criticalConfigOptions.find(name) != _criticalConfigOptions.end();
|
||||
ConfigSeverity severity = isCritical ? _policy.criticalOptionSeverity : _policy.missingOptionSeverity;
|
||||
|
||||
if (fatalConfig)
|
||||
LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!",
|
||||
if (isCritical)
|
||||
{
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!",
|
||||
name, _filename, name, Acore::ToString(def), envVarName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string configs = _filename;
|
||||
if (!_moduleConfigFiles.empty())
|
||||
configs += " or module config";
|
||||
|
||||
LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
name, configs, name, def, envVarName);
|
||||
}
|
||||
}
|
||||
@ -433,7 +586,8 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
LOG_ERROR("server.loading", "> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
LogWithSeverity(_policy.valueErrorSeverity, _filename,
|
||||
"> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
name, Acore::ToString(def));
|
||||
}
|
||||
|
||||
@ -447,7 +601,6 @@ template<>
|
||||
std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std::string const& def, bool showLogs /*= true*/) const
|
||||
{
|
||||
auto const& itr = _configOptions.find(name);
|
||||
bool fatalConfig = false;
|
||||
bool notFound = itr == _configOptions.end();
|
||||
auto envVarName = GetEnvVarName(name);
|
||||
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
|
||||
@ -466,23 +619,23 @@ std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
for (std::string s : _fatalConfigOptions)
|
||||
if (s == name)
|
||||
{
|
||||
fatalConfig = true;
|
||||
break;
|
||||
}
|
||||
bool isCritical = _criticalConfigOptions.find(name) != _criticalConfigOptions.end();
|
||||
ConfigSeverity severity = isCritical ? _policy.criticalOptionSeverity : _policy.missingOptionSeverity;
|
||||
|
||||
if (fatalConfig)
|
||||
LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!",
|
||||
if (isCritical)
|
||||
{
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!",
|
||||
name, _filename, name, def, envVarName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string configs = _filename;
|
||||
if (!_moduleConfigFiles.empty())
|
||||
configs += " or module config";
|
||||
|
||||
LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
name, configs, name, def, envVarName);
|
||||
}
|
||||
}
|
||||
@ -509,7 +662,8 @@ bool ConfigMgr::GetOption<bool>(std::string const& name, bool const& def, bool s
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
LOG_ERROR("server.loading", "> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
LogWithSeverity(_policy.valueErrorSeverity, _filename,
|
||||
"> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
name, def ? "true" : "false");
|
||||
}
|
||||
|
||||
@ -558,17 +712,27 @@ std::string const ConfigMgr::GetConfigPath()
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConfigMgr::Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList /*= {}*/)
|
||||
void ConfigMgr::Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList /*= {}*/, ConfigPolicy policy /*= {}*/)
|
||||
{
|
||||
_filename = initFileName;
|
||||
_args = std::move(args);
|
||||
_policy = policy;
|
||||
|
||||
if (char const* env = std::getenv("AC_CONFIG_POLICY"))
|
||||
_policy = ApplyPolicyString(_policy, env);
|
||||
|
||||
_policy = ApplyPolicyFromArgs(_policy, _args);
|
||||
|
||||
_additonalFiles.clear();
|
||||
_moduleConfigFiles.clear();
|
||||
|
||||
// Add modules config if exist
|
||||
if (!modulesConfigList.empty())
|
||||
{
|
||||
for (auto const& itr : Acore::Tokenize(modulesConfigList, ',', false))
|
||||
{
|
||||
_additonalFiles.emplace_back(itr);
|
||||
if (!itr.empty())
|
||||
_additonalFiles.emplace_back(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,29 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
enum class ConfigSeverity : uint8_t
|
||||
{
|
||||
Skip,
|
||||
Warn,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
||||
|
||||
struct ConfigPolicy
|
||||
{
|
||||
ConfigSeverity defaultSeverity = ConfigSeverity::Warn;
|
||||
ConfigSeverity missingFileSeverity = ConfigSeverity::Error;
|
||||
ConfigSeverity missingOptionSeverity = ConfigSeverity::Warn;
|
||||
ConfigSeverity criticalOptionSeverity = ConfigSeverity::Fatal;
|
||||
ConfigSeverity unknownOptionSeverity = ConfigSeverity::Error;
|
||||
ConfigSeverity valueErrorSeverity = ConfigSeverity::Error;
|
||||
};
|
||||
|
||||
class ConfigMgr
|
||||
{
|
||||
ConfigMgr() = default;
|
||||
@ -32,7 +51,7 @@ class ConfigMgr
|
||||
public:
|
||||
bool LoadAppConfigs(bool isReload = false);
|
||||
bool LoadModulesConfigs(bool isReload = false, bool isNeedPrintInfo = true);
|
||||
void Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList = {});
|
||||
void Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList = {}, ConfigPolicy policy = {});
|
||||
|
||||
static ConfigMgr* instance();
|
||||
|
||||
|
||||
@ -211,13 +211,16 @@ void Log::ReadLoggersFromConfig()
|
||||
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, {});
|
||||
appenders[appender->getId()].reset(appender);
|
||||
|
||||
Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR);
|
||||
Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_WARN);
|
||||
rootLogger->addAppender(appender->getId(), appender);
|
||||
loggers[LOGGER_ROOT].reset(rootLogger);
|
||||
|
||||
Logger* serverLogger = new Logger("server", LOG_LEVEL_INFO);
|
||||
serverLogger->addAppender(appender->getId(), appender);
|
||||
loggers["server"].reset(serverLogger);
|
||||
|
||||
highestLogLevel = LOG_LEVEL_INFO;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -278,7 +278,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile)
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
variables_map variablesMap;
|
||||
|
||||
|
||||
@ -423,7 +423,7 @@ bool StartDB()
|
||||
MySQL::Library_Init();
|
||||
|
||||
// Load databases
|
||||
DatabaseLoader loader("server.worldserver", DatabaseLoader::DATABASE_NONE, AC_MODULES_LIST);
|
||||
DatabaseLoader loader("server.worldserver", DatabaseLoader::DATABASE_MASK_ALL, AC_MODULES_LIST);
|
||||
loader
|
||||
.AddDatabase(LoginDatabase, "Login")
|
||||
.AddDatabase(CharacterDatabase, "Character")
|
||||
@ -433,7 +433,7 @@ bool StartDB()
|
||||
return false;
|
||||
|
||||
///- Get the realm Id from the configuration file
|
||||
realm.Id.Realm = sConfigMgr->GetOption<uint32>("RealmID", 0);
|
||||
realm.Id.Realm = sConfigMgr->GetOption<uint32>("RealmID", 1);
|
||||
if (!realm.Id.Realm)
|
||||
{
|
||||
LOG_ERROR("server.worldserver", "Realm ID not defined in configuration file");
|
||||
@ -710,7 +710,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_CORE_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_CORE_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
options_description win("Windows platform specific options");
|
||||
|
||||
@ -24,6 +24,24 @@
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <thread>
|
||||
#include <string_view>
|
||||
namespace
|
||||
{
|
||||
std::string const EMPTY_DATABASE_INFO;
|
||||
std::string const LOGIN_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_auth";
|
||||
std::string const WORLD_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_world";
|
||||
std::string const CHARACTER_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_characters";
|
||||
std::string const& GetDefaultDatabaseInfo(std::string_view name)
|
||||
{
|
||||
if (name == "Login")
|
||||
return LOGIN_DATABASE_INFO_DEFAULT;
|
||||
if (name == "World")
|
||||
return WORLD_DATABASE_INFO_DEFAULT;
|
||||
if (name == "Character")
|
||||
return CHARACTER_DATABASE_INFO_DEFAULT;
|
||||
return EMPTY_DATABASE_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseLoader::DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask, std::string_view modulesList)
|
||||
: _logger(logger),
|
||||
@ -38,7 +56,8 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
|
||||
_open.push([this, name, updatesEnabledForThis, &pool]() -> bool
|
||||
{
|
||||
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", "");
|
||||
std::string const& defaultDatabaseInfo = GetDefaultDatabaseInfo(name);
|
||||
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", defaultDatabaseInfo);
|
||||
if (dbString.empty())
|
||||
{
|
||||
LOG_ERROR(_logger, "Database {} not specified in configuration file!", name);
|
||||
|
||||
@ -109,8 +109,8 @@ bool StartDB()
|
||||
|
||||
DatabaseLoader loader =
|
||||
modules.empty() ? DatabaseLoader("dbimport") :
|
||||
(modules == "all") ? DatabaseLoader("dbimport", DatabaseLoader::DATABASE_NONE, AC_MODULES_LIST) :
|
||||
DatabaseLoader("dbimport", DatabaseLoader::DATABASE_NONE, modules);
|
||||
(modules == "all") ? DatabaseLoader("dbimport", DatabaseLoader::DATABASE_MASK_ALL, AC_MODULES_LIST) :
|
||||
DatabaseLoader("dbimport", DatabaseLoader::DATABASE_MASK_ALL, modules);
|
||||
|
||||
loader
|
||||
.AddDatabase(LoginDatabase, "Login")
|
||||
@ -140,7 +140,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile)
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_DB_IMPORT_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_DB_IMPORT_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
variables_map variablesMap;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user