Skip to content

Commit

Permalink
refactor(Core): Source config more aggressively from env, rephrase a …
Browse files Browse the repository at this point in the history
…few of the messages (azerothcore#17114)

* refactor(Core): Let modules source config from env

* create a cache of configs from env

* Update src/common/Configuration/Config.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/common/Configuration/Config.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* enforce new function name

---------

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>
  • Loading branch information
michaeldelago and Kitzunu authored Sep 20, 2023
1 parent c4c5e0b commit b1c92f4
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 38 deletions.
89 changes: 61 additions & 28 deletions src/common/Configuration/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace
std::vector<std::string> _additonalFiles;
std::vector<std::string> _args;
std::unordered_map<std::string /*name*/, std::string /*value*/> _configOptions;
std::unordered_map<std::string /*name*/, std::string /*value*/> _envVarCache;
std::mutex _configLock;

// Check system configs like *server.conf*
Expand Down Expand Up @@ -120,7 +121,7 @@ namespace
auto const& itr = fileConfigs.find(confOption);
if (itr != fileConfigs.end())
{
PrintError(file, "> Config::LoadFile: Dublicate key name '{}' in config file '{}'", confOption, file);
PrintError(file, "> Config::LoadFile: Duplicate key name '{}' in config file '{}'", confOption, file);
return true;
}

Expand Down Expand Up @@ -283,9 +284,14 @@ namespace
return result;
}

std::string GetEnvVarName(std::string const& configName)
{
return "AC_" + IniKeyToEnvVarKey(configName);
}

Optional<std::string> EnvVarForIniKey(std::string const& key)
{
std::string envKey = "AC_" + IniKeyToEnvVarKey(key);
std::string envKey = GetEnvVarName(key);
char* val = std::getenv(envKey.c_str());
if (!val)
return std::nullopt;
Expand Down Expand Up @@ -330,6 +336,29 @@ bool ConfigMgr::Reload()
return true;
}

// Check the _envVarCache if the env var is there
// if not, check the env for the value
Optional<std::string> GetEnvFromCache(std::string const& configName, std::string const& envVarName)
{
auto foundInCache = _envVarCache.find(envVarName);
Optional<std::string> foundInEnv;
// If it's not in the cache
if (foundInCache == _envVarCache.end())
{
// Check the env itself
foundInEnv = EnvVarForIniKey(configName);
if (foundInEnv)
{
// If it's found in the env, put it in the cache
_envVarCache.emplace(envVarName, *foundInEnv);
}
// Return the result of checking env
return foundInEnv;
}

return foundInCache->second;
}

std::vector<std::string> ConfigMgr::OverrideWithEnvVariablesIfAny()
{
std::lock_guard<std::mutex> lock(_configLock);
Expand Down Expand Up @@ -357,28 +386,30 @@ template<class T>
T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLogs /*= true*/) const
{
std::string strValue;

auto const& itr = _configOptions.find(name);
if (itr == _configOptions.end())
bool notFound = itr == _configOptions.end();
auto envVarName = GetEnvVarName(name);
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
if (envVar)
{
Optional<std::string> envVar = EnvVarForIniKey(name);
if (!envVar)
// If showLogs and this key/value pair wasn't found in the currently saved config
if (showLogs && (notFound || itr->second != envVar->c_str()))
{
if (showLogs)
{
LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file.",
name, _filename, name, Acore::ToString(def));
}

return def;
LOG_INFO("server.loading", "> Config: Found config value '{}' from environment variable '{}'.", name, envVarName );
AddKey(name, envVar->c_str(), "ENVIRONMENT", false, false);
}

strValue = *envVar;
}
else if (notFound)
{
if (showLogs)
{
LOG_WARN("server.loading", "Missing property {} in config file {}, recovered with environment '{}' value.",
name, _filename, envVar->c_str());
LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
name, _filename, name, Acore::ToString(def), envVarName);
}

strValue = *envVar;
return def;
}
else
{
Expand All @@ -404,24 +435,26 @@ 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);
if (itr == _configOptions.end())
bool notFound = itr == _configOptions.end();
auto envVarName = GetEnvVarName(name);
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
if (envVar)
{
Optional<std::string> envVar = EnvVarForIniKey(name);
if (envVar)
// If showLogs and this key/value pair wasn't found in the currently saved config
if (showLogs && (notFound || itr->second != envVar->c_str()))
{
if (showLogs)
{
LOG_WARN("server.loading", "Missing property {} in config file {}, recovered with environment '{}' value.",
name, _filename, envVar->c_str());
}

return *envVar;
LOG_INFO("server.loading", "> Config: Found config value '{}' from environment variable '{}'.", name, envVarName);
AddKey(name, *envVar, "ENVIRONMENT", false, false);
}

return *envVar;
}
else if (notFound)
{
if (showLogs)
{
LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file.",
name, _filename, name, def);
LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
name, _filename, name, def, envVarName);
}

return def;
Expand Down
5 changes: 0 additions & 5 deletions src/server/apps/authserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ int main(int argc, char** argv)
if (!sConfigMgr->LoadAppConfigs())
return 1;

std::vector<std::string> overriddenKeys = sConfigMgr->OverrideWithEnvVariablesIfAny();

// Init logging
sLog->RegisterAppender<AppenderDB>();
sLog->Initialize(nullptr);
Expand All @@ -103,9 +101,6 @@ int main(int argc, char** argv)
LOG_INFO("server.authserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
});

for (std::string const& key : overriddenKeys)
LOG_INFO("server.authserver", "Configuration field {} was overridden with environment variable.", key);

OpenSSLCrypto::threadsSetup();

std::shared_ptr<void> opensslHandle(nullptr, [](void*) { OpenSSLCrypto::threadsCleanup(); });
Expand Down
5 changes: 0 additions & 5 deletions src/server/apps/worldserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,6 @@ int main(int argc, char** argv)
if (!sConfigMgr->LoadAppConfigs())
return 1;

std::vector<std::string> overriddenKeys = sConfigMgr->OverrideWithEnvVariablesIfAny();

std::shared_ptr<Acore::Asio::IoContext> ioContext = std::make_shared<Acore::Asio::IoContext>();

// Init all logs
Expand All @@ -205,9 +203,6 @@ int main(int argc, char** argv)
LOG_INFO("server.worldserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
});

for (std::string const& key : overriddenKeys)
LOG_INFO("server.worldserver", "Configuration field {} was overridden with environment variable.", key);

OpenSSLCrypto::threadsSetup();

std::shared_ptr<void> opensslHandle(nullptr, [](void*) { OpenSSLCrypto::threadsCleanup(); });
Expand Down

0 comments on commit b1c92f4

Please sign in to comment.