aboutsummaryrefslogtreecommitdiff
path: root/zenserver/config.cpp
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-11-25 10:49:23 +0100
committerPer Larsson <[email protected]>2021-11-25 10:49:23 +0100
commitc4968d460be263ff5761a1ebd7f79b5e77dc91d2 (patch)
treea4cb578e3a58466b71c2de2af935b3934ac130ea /zenserver/config.cpp
parentMerge branch 'main' of https://github.com/EpicGames/zen (diff)
downloadzen-c4968d460be263ff5761a1ebd7f79b5e77dc91d2.tar.xz
zen-c4968d460be263ff5761a1ebd7f79b5e77dc91d2.zip
Added support for loading Lua config file from CLI option and merged server/service config.
Diffstat (limited to 'zenserver/config.cpp')
-rw-r--r--zenserver/config.cpp180
1 files changed, 117 insertions, 63 deletions
diff --git a/zenserver/config.cpp b/zenserver/config.cpp
index 3e85daa9e..1e847ce3d 100644
--- a/zenserver/config.cpp
+++ b/zenserver/config.cpp
@@ -79,8 +79,10 @@ ParseUpstreamCachePolicy(std::string_view Options)
}
}
+void ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions);
+
void
-ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, ZenServiceConfig& ServiceConfig)
+ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
{
#if ZEN_WITH_HTTPSYS
const char* DefaultHttp = "httpsys";
@@ -91,22 +93,23 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
cxxopts::Options options("zenserver", "Zen Server");
options.add_options()("dedicated",
"Enable dedicated server mode",
- cxxopts::value<bool>(GlobalOptions.IsDedicated)->default_value("false"));
- options.add_options()("d, debug", "Enable debugging", cxxopts::value<bool>(GlobalOptions.IsDebug)->default_value("false"));
+ cxxopts::value<bool>(ServerOptions.IsDedicated)->default_value("false"));
+ options.add_options()("d, debug", "Enable debugging", cxxopts::value<bool>(ServerOptions.IsDebug)->default_value("false"));
options.add_options()("help", "Show command line help");
- options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(GlobalOptions.IsTest)->default_value("false"));
- options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(GlobalOptions.LogId));
- options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::filesystem::path>(GlobalOptions.DataDir));
- options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::filesystem::path>(GlobalOptions.ContentDir));
- options.add_options()("abslog", "Path to log file", cxxopts::value<std::filesystem::path>(GlobalOptions.AbsLogFile));
+ options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(ServerOptions.IsTest)->default_value("false"));
+ options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(ServerOptions.LogId));
+ options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::filesystem::path>(ServerOptions.DataDir));
+ options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::filesystem::path>(ServerOptions.ContentDir));
+ options.add_options()("abslog", "Path to log file", cxxopts::value<std::filesystem::path>(ServerOptions.AbsLogFile));
+ options.add_options()("config", "Path to Lua config file", cxxopts::value<std::filesystem::path>(ServerOptions.ConfigFile));
options
- .add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value<int>(GlobalOptions.OwnerPid), "<identifier>");
+ .add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value<int>(ServerOptions.OwnerPid), "<identifier>");
options.add_option("lifetime",
"",
"child-id",
"Specify id which can be used to signal parent",
- cxxopts::value<std::string>(GlobalOptions.ChildId),
+ cxxopts::value<std::string>(ServerOptions.ChildId),
"<identifier>");
#if ZEN_PLATFORM_WINDOWS
@@ -114,13 +117,13 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"install",
"Install zenserver as a Windows service",
- cxxopts::value<bool>(GlobalOptions.InstallService),
+ cxxopts::value<bool>(ServerOptions.InstallService),
"");
options.add_option("lifetime",
"",
"uninstall",
"Uninstall zenserver as a Windows service",
- cxxopts::value<bool>(GlobalOptions.UninstallService),
+ cxxopts::value<bool>(ServerOptions.UninstallService),
"");
#endif
@@ -128,14 +131,14 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"http",
"Select HTTP server implementation (asio|httpsys|null)",
- cxxopts::value<std::string>(GlobalOptions.HttpServerClass)->default_value(DefaultHttp),
+ cxxopts::value<std::string>(ServerOptions.HttpServerClass)->default_value(DefaultHttp),
"<http class>");
options.add_option("network",
"p",
"port",
"Select HTTP port",
- cxxopts::value<int>(GlobalOptions.BasePort)->default_value("1337"),
+ cxxopts::value<int>(ServerOptions.BasePort)->default_value("1337"),
"<port number>");
#if ZEN_ENABLE_MESH
@@ -143,7 +146,7 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"m",
"mesh",
"Enable mesh network",
- cxxopts::value<bool>(ServiceConfig.MeshEnabled)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.MeshEnabled)->default_value("false"),
"");
#endif
@@ -151,7 +154,7 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"crash",
"Simulate a crash",
- cxxopts::value<bool>(ServiceConfig.ShouldCrash)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.ShouldCrash)->default_value("false"),
"");
std::string UpstreamCachePolicyOptions;
@@ -166,105 +169,105 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"upstream-jupiter-url",
"URL to a Jupiter instance",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-url",
"URL to the OAuth provier",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthProvider)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthProvider)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-clientid",
"The OAuth client ID",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-clientsecret",
"The OAuth client secret",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-namespace",
"The Common Blob Store API namespace",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-namespace-ddc",
"The lecacy DDC namespace",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-prod",
"Enable Jupiter upstream caching using production settings",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseProductionSettings)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseProductionSettings)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-jupiter-dev",
"Enable Jupiter upstream caching using development settings",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-jupiter-use-legacy-ddc",
"Whether to store derived data using the legacy endpoint",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-zen-url",
"URL to remote Zen server. Use a comma separated list to choose the one with the best latency.",
- cxxopts::value<std::vector<std::string>>(ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls)->default_value(""),
+ cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Urls)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-zen-dns",
"DNS that resolves to one or more Zen server instance(s)",
- cxxopts::value<std::vector<std::string>>(ServiceConfig.UpstreamCacheConfig.ZenConfig.Dns)->default_value(""),
+ cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Dns)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-thread-count",
"Number of threads used for upstream procsssing",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"),
"");
options.add_option("cache",
"",
"upstream-stats",
"Collect performance metrics for upstream endpoints",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.StatsEnabled)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.StatsEnabled)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-connect-timeout-ms",
"Connect timeout in millisecond(s). Default 5000 ms.",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"),
"");
options.add_option("cache",
"",
"upstream-timeout-ms",
"Timeout in millisecond(s). Default 0 ms",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"),
"");
try
@@ -279,7 +282,16 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
exit(0);
}
- ServiceConfig.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions);
+ ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions);
+
+ if (!ServerOptions.ConfigFile.empty())
+ {
+ ParseConfigFile(ServerOptions.ConfigFile, ServerOptions);
+ }
+ else
+ {
+ ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions);
+ }
}
catch (cxxopts::OptionParseException& e)
{
@@ -288,32 +300,25 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
throw;
}
- if (GlobalOptions.DataDir.empty())
+ if (ServerOptions.DataDir.empty())
{
- GlobalOptions.DataDir = PickDefaultStateDirectory();
+ ServerOptions.DataDir = PickDefaultStateDirectory();
}
}
void
-ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& ServiceConfig)
+ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions)
{
using namespace fmt::literals;
- std::filesystem::path ConfigScript = DataRoot / "zen_cfg.lua";
- zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(ConfigScript.native().c_str());
+ zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(Path.native().c_str());
if (LuaScript)
{
sol::state lua;
- // Provide some context to help derive defaults
- lua.set("dataroot", DataRoot.native());
-
lua.open_libraries(sol::lib::base);
- // We probably want to limit the scope of this so the script won't see
- // any more than it needs to
-
lua.set_function("getenv", [&](const std::string env) -> sol::object {
std::wstring EnvVarValue;
size_t RequiredSize = 0;
@@ -345,14 +350,50 @@ ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& Serv
}
catch (std::exception& e)
{
- ZEN_ERROR("config failure: {}", e.what());
+ throw std::runtime_error("failed to load config script ('{}'): {}"_format(Path, e.what()).c_str());
+ }
- throw std::runtime_error("failed to run global config script ('{}'): {}"_format(ConfigScript, e.what()).c_str());
+ if (sol::optional<sol::table> ServerConfig = lua["server"])
+ {
+ if (ServerOptions.DataDir.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["datadir"])
+ {
+ ServerOptions.DataDir = Opt.value();
+ }
+ }
+
+ if (ServerOptions.ContentDir.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["contentdir"])
+ {
+ ServerOptions.ContentDir = Opt.value();
+ }
+ }
+
+ if (ServerOptions.AbsLogFile.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["abslog"])
+ {
+ ServerOptions.AbsLogFile = Opt.value();
+ }
+ }
+
+ ServerOptions.IsDebug = ServerConfig->get_or("debug", ServerOptions.IsDebug);
}
+ if (sol::optional<sol::table> NetworkConfig = lua["network"])
+ {
+ if (sol::optional<std::string> Opt = NetworkConfig.value()["httpserverclass"])
+ {
+ ServerOptions.HttpServerClass = Opt.value();
+ }
+
+ ServerOptions.BasePort = NetworkConfig->get_or<int>("port", ServerOptions.BasePort);
#if ZEN_ENABLE_MESH
- ServiceConfig.MeshEnabled = lua["mesh"]["enable"].get_or(ServiceConfig.MeshEnabled);
+ ServerOptions.MeshEnabled = NetworkConfig->get_or<bool>("meshenabled", ServerOptions.MeshEnabled);
#endif
+ }
auto UpdateStringValueFromConfig = [](const sol::table& Table, std::string_view Key, std::string& OutValue) {
// Update the specified config value unless it has been set, i.e. from command line
@@ -362,56 +403,69 @@ ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& Serv
}
};
- if (sol::optional<sol::table> StructuredCacheConfig = lua["structuredcache"])
+ if (sol::optional<sol::table> StructuredCacheConfig = lua["cache"])
{
- ServiceConfig.StructuredCacheEnabled = StructuredCacheConfig->get_or("enable", ServiceConfig.StructuredCacheEnabled);
+ ServerOptions.StructuredCacheEnabled = StructuredCacheConfig->get_or("enable", ServerOptions.StructuredCacheEnabled);
if (auto UpstreamConfig = StructuredCacheConfig->get<sol::optional<sol::table>>("upstream"))
{
- std::string Policy = UpstreamConfig->get_or("policy", std::string());
- ServiceConfig.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(Policy);
- ServiceConfig.UpstreamCacheConfig.UpstreamThreadCount = UpstreamConfig->get_or("upstreamthreadcount", 4);
+ std::string Policy = UpstreamConfig->get_or("policy", std::string());
+ ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(Policy);
+ ServerOptions.UpstreamCacheConfig.UpstreamThreadCount =
+ UpstreamConfig->get_or("upstreamthreadcount", ServerOptions.UpstreamCacheConfig.UpstreamThreadCount);
if (auto JupiterConfig = UpstreamConfig->get<sol::optional<sol::table>>("jupiter"))
{
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("url"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.Url);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.Url);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthprovider"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthProvider);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthProvider);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthclientid"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientId);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthclientsecret"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("namespace"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.Namespace);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("ddcnamespace"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.DdcNamespace);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace);
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings =
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings =
JupiterConfig->get_or("usedevelopmentsettings",
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings);
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc =
- JupiterConfig->get_or("uselegacyddc", ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc =
+ JupiterConfig->get_or("uselegacyddc", ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc);
};
if (auto ZenConfig = UpstreamConfig->get<sol::optional<sol::table>>("zen"))
{
if (auto Url = ZenConfig.value().get<sol::optional<std::string>>("url"))
{
- ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls.push_back(Url.value());
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Url.value());
}
else if (auto Urls = ZenConfig.value().get<sol::optional<sol::table>>("url"))
{
for (const auto& Kv : Urls.value())
{
- ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls.push_back(Kv.second.as<std::string>());
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Kv.second.as<std::string>());
+ }
+ }
+
+ if (auto Dns = ZenConfig.value().get<sol::optional<std::string>>("dns"))
+ {
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Dns.value());
+ }
+ else if (auto DnsArray = ZenConfig.value().get<sol::optional<sol::table>>("dns"))
+ {
+ for (const auto& Kv : DnsArray.value())
+ {
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Kv.second.as<std::string>());
}
}
}