diff options
| author | Per Larsson <[email protected]> | 2021-11-25 10:49:23 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2021-11-25 10:49:23 +0100 |
| commit | c4968d460be263ff5761a1ebd7f79b5e77dc91d2 (patch) | |
| tree | a4cb578e3a58466b71c2de2af935b3934ac130ea /zenserver/config.cpp | |
| parent | Merge branch 'main' of https://github.com/EpicGames/zen (diff) | |
| download | zen-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.cpp | 180 |
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>()); } } } |