refactor: Replace all old instances of Config with New Config (#1627)

Fixes #1184 
Previous PR's found [here](https://github.com/XRPLF/clio/pull/1593) and
[here](https://github.com/XRPLF/clio/pull/1544)
This commit is contained in:
Peter Chen
2024-12-16 15:33:32 -08:00
committed by GitHub
parent b53cfd0ec1
commit 3c4903a339
103 changed files with 1624 additions and 898 deletions

View File

@@ -23,7 +23,12 @@
#include "util/TestHttpClient.hpp"
#include "util/TestWebSocketClient.hpp"
#include "util/TmpFile.hpp"
#include "util/config/Config.hpp"
#include "util/newconfig/Array.hpp"
#include "util/newconfig/ConfigDefinition.hpp"
#include "util/newconfig/ConfigFileJson.hpp"
#include "util/newconfig/ConfigValue.hpp"
#include "util/newconfig/Types.hpp"
#include "util/prometheus/Gauge.hpp"
#include "util/prometheus/Label.hpp"
#include "util/prometheus/Prometheus.hpp"
#include "web/AdminVerificationStrategy.hpp"
@@ -61,6 +66,7 @@
#include <vector>
using namespace util;
using namespace util::config;
using namespace web::impl;
using namespace web;
@@ -105,6 +111,30 @@ generateJSONDataOverload(std::string_view port)
));
}
inline ClioConfigDefinition
getParseServerConfig(boost::json::value val)
{
ConfigFileJson const jsonVal{val.as_object()};
auto config = ClioConfigDefinition{
{"server.ip", ConfigValue{ConfigType::String}},
{"server.port", ConfigValue{ConfigType::Integer}},
{"server.admin_password", ConfigValue{ConfigType::String}.optional()},
{"server.local_admin", ConfigValue{ConfigType::Boolean}.optional()},
{"server.ws_max_sending_queue_size", ConfigValue{ConfigType::Integer}.defaultValue(1500)},
{"log_tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")},
{"dos_guard.max_fetches", ConfigValue{ConfigType::Integer}},
{"dos_guard.sweep_interval", ConfigValue{ConfigType::Integer}},
{"dos_guard.max_connections", ConfigValue{ConfigType::Integer}},
{"dos_guard.max_requests", ConfigValue{ConfigType::Integer}},
{"dos_guard.whitelist.[]", Array{ConfigValue{ConfigType::String}.optional()}},
{"ssl_key_file", ConfigValue{ConfigType::String}.optional()},
{"ssl_cert_file", ConfigValue{ConfigType::String}.optional()},
};
auto const errors = config.parse(jsonVal);
[&]() { ASSERT_FALSE(errors.has_value()); }();
return config;
};
struct WebServerTest : NoLoggerFixture {
~WebServerTest() override
{
@@ -131,12 +161,12 @@ struct WebServerTest : NoLoggerFixture {
// this ctx is for dos timer
boost::asio::io_context ctxSync;
std::string const port = std::to_string(tests::util::generateFreePort());
Config cfg{generateJSONWithDynamicPort(port)};
ClioConfigDefinition cfg{getParseServerConfig(generateJSONWithDynamicPort(port))};
dosguard::WhitelistHandler whitelistHandler{cfg};
dosguard::DOSGuard dosGuard{cfg, whitelistHandler};
dosguard::IntervalSweepHandler sweepHandler{cfg, ctxSync, dosGuard};
Config cfgOverload{generateJSONDataOverload(port)};
ClioConfigDefinition cfgOverload{getParseServerConfig(generateJSONDataOverload(port))};
dosguard::WhitelistHandler whitelistHandlerOverload{cfgOverload};
dosguard::DOSGuard dosGuardOverload{cfgOverload, whitelistHandlerOverload};
dosguard::IntervalSweepHandler sweepHandlerOverload{cfgOverload, ctxSync, dosGuardOverload};
@@ -184,7 +214,7 @@ namespace {
template <class Executor>
std::shared_ptr<web::HttpServer<Executor>>
makeServerSync(
util::Config const& config,
util::config::ClioConfigDefinition const& config,
boost::asio::io_context& ioc,
web::dosguard::DOSGuardInterface& dosGuard,
std::shared_ptr<Executor> const& handler
@@ -213,7 +243,7 @@ makeServerSync(
TEST_F(WebServerTest, Http)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
auto const [status, res] = HttpSyncClient::post("localhost", port, R"({"Hello":1})");
EXPECT_EQ(res, R"({"Hello":1})");
@@ -233,7 +263,7 @@ TEST_F(WebServerTest, Ws)
TEST_F(WebServerTest, HttpInternalError)
{
auto e = std::make_shared<ExceptionExecutor>();
auto const e = std::make_shared<ExceptionExecutor>();
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
auto const [status, res] = HttpSyncClient::post("localhost", port, R"({})");
EXPECT_EQ(
@@ -273,31 +303,31 @@ TEST_F(WebServerTest, WsInternalErrorNotJson)
TEST_F(WebServerTest, IncompleteSslConfig)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto jsonConfig = generateJSONWithDynamicPort(port);
jsonConfig.as_object()["ssl_key_file"] = sslKeyFile.path;
auto const server = makeServerSync(Config{jsonConfig}, ctx, dosGuard, e);
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e);
EXPECT_EQ(server, nullptr);
}
TEST_F(WebServerTest, WrongSslConfig)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto jsonConfig = generateJSONWithDynamicPort(port);
jsonConfig.as_object()["ssl_key_file"] = sslKeyFile.path;
jsonConfig.as_object()["ssl_cert_file"] = "wrong_path";
auto const server = makeServerSync(Config{jsonConfig}, ctx, dosGuard, e);
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e);
EXPECT_EQ(server, nullptr);
}
TEST_F(WebServerTest, Https)
{
auto e = std::make_shared<EchoExecutor>();
cfg = Config{addSslConfig(generateJSONWithDynamicPort(port))};
auto const e = std::make_shared<EchoExecutor>();
cfg = getParseServerConfig(addSslConfig(generateJSONWithDynamicPort(port)));
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
auto const res = HttpsSyncClient::syncPost("localhost", port, R"({"Hello":1})");
EXPECT_EQ(res, R"({"Hello":1})");
@@ -306,7 +336,7 @@ TEST_F(WebServerTest, Https)
TEST_F(WebServerTest, Wss)
{
auto e = std::make_shared<EchoExecutor>();
cfg = Config{addSslConfig(generateJSONWithDynamicPort(port))};
cfg = getParseServerConfig(addSslConfig(generateJSONWithDynamicPort(port)));
auto server = makeServerSync(cfg, ctx, dosGuard, e);
WebServerSslSyncClient wsClient;
wsClient.connect("localhost", port);
@@ -317,7 +347,7 @@ TEST_F(WebServerTest, Wss)
TEST_F(WebServerTest, HttpRequestOverload)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto const server = makeServerSync(cfg, ctx, dosGuardOverload, e);
auto [status, res] = HttpSyncClient::post("localhost", port, R"({})");
EXPECT_EQ(res, "{}");
@@ -353,7 +383,7 @@ TEST_F(WebServerTest, WsRequestOverload)
TEST_F(WebServerTest, HttpPayloadOverload)
{
std::string const s100(100, 'a');
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
auto const [status, res] = HttpSyncClient::post("localhost", port, fmt::format(R"({{"payload":"{}"}})", s100));
EXPECT_EQ(
@@ -366,7 +396,7 @@ TEST_F(WebServerTest, HttpPayloadOverload)
TEST_F(WebServerTest, WsPayloadOverload)
{
std::string const s100(100, 'a');
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
WebSocketSyncClient wsClient;
wsClient.connect("localhost", port);
@@ -380,7 +410,7 @@ TEST_F(WebServerTest, WsPayloadOverload)
TEST_F(WebServerTest, WsTooManyConnection)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
// max connection is 2, exception should happen when the third connection is made
WebSocketSyncClient wsClient1;
@@ -504,15 +534,38 @@ struct WebServerAdminTestParams {
std::string expectedResponse;
};
inline ClioConfigDefinition
getParseAdminServerConfig(boost::json::value val)
{
ConfigFileJson const jsonVal{val.as_object()};
auto config = ClioConfigDefinition{
{"server.ip", ConfigValue{ConfigType::String}},
{"server.port", ConfigValue{ConfigType::Integer}},
{"server.admin_password", ConfigValue{ConfigType::String}.optional()},
{"server.local_admin", ConfigValue{ConfigType::Boolean}.optional()},
{"server.processing_policy", ConfigValue{ConfigType::String}.defaultValue("parallel")},
{"server.parallel_requests_limit", ConfigValue{ConfigType::Integer}.optional()},
{"server.ws_max_sending_queue_size", ConfigValue{ConfigType::Integer}.defaultValue(1500)},
{"ssl_cert_file", ConfigValue{ConfigType::String}.optional()},
{"ssl_key_file", ConfigValue{ConfigType::String}.optional()},
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"log_tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")}
};
auto const errors = config.parse(jsonVal);
[&]() { ASSERT_FALSE(errors.has_value()); }();
return config;
};
class WebServerAdminTest : public WebServerTest, public ::testing::WithParamInterface<WebServerAdminTestParams> {};
TEST_P(WebServerAdminTest, WsAdminCheck)
{
auto e = std::make_shared<AdminCheckExecutor>();
Config const serverConfig{boost::json::parse(GetParam().config)};
ClioConfigDefinition const serverConfig{getParseAdminServerConfig(boost::json::parse(GetParam().config))};
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e);
WebSocketSyncClient wsClient;
uint32_t const webServerPort = serverConfig.value<uint32_t>("server.port");
uint32_t const webServerPort = serverConfig.get<uint32_t>("server.port");
wsClient.connect("localhost", std::to_string(webServerPort), GetParam().headers);
std::string const request = "Why hello";
auto const res = wsClient.syncPost(request);
@@ -522,11 +575,11 @@ TEST_P(WebServerAdminTest, WsAdminCheck)
TEST_P(WebServerAdminTest, HttpAdminCheck)
{
auto e = std::make_shared<AdminCheckExecutor>();
Config const serverConfig{boost::json::parse(GetParam().config)};
auto const e = std::make_shared<AdminCheckExecutor>();
ClioConfigDefinition const serverConfig{getParseAdminServerConfig(boost::json::parse(GetParam().config))};
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e);
std::string const request = "Why hello";
uint32_t const webServerPort = serverConfig.value<uint32_t>("server.port");
uint32_t const webServerPort = serverConfig.get<uint32_t>("server.port");
auto const [status, res] =
HttpSyncClient::post("localhost", std::to_string(webServerPort), request, GetParam().headers);
@@ -616,8 +669,10 @@ TEST_F(WebServerTest, AdminErrorCfgTestBothAdminPasswordAndLocalAdminSet)
webServerPort
);
auto e = std::make_shared<AdminCheckExecutor>();
Config const serverConfig{boost::json::parse(JSONServerConfigWithBothAdminPasswordAndLocalAdmin)};
auto const e = std::make_shared<AdminCheckExecutor>();
ClioConfigDefinition const serverConfig{
getParseAdminServerConfig(boost::json::parse(JSONServerConfigWithBothAdminPasswordAndLocalAdmin))
};
EXPECT_THROW(web::make_HttpServer(serverConfig, ctx, dosGuardOverload, e), std::logic_error);
}
@@ -635,8 +690,10 @@ TEST_F(WebServerTest, AdminErrorCfgTestBothAdminPasswordAndLocalAdminFalse)
webServerPort
);
auto e = std::make_shared<AdminCheckExecutor>();
Config const serverConfig{boost::json::parse(JSONServerConfigWithNoAdminPasswordAndLocalAdminFalse)};
auto const e = std::make_shared<AdminCheckExecutor>();
ClioConfigDefinition const serverConfig{
getParseAdminServerConfig(boost::json::parse(JSONServerConfigWithNoAdminPasswordAndLocalAdminFalse))
};
EXPECT_THROW(web::make_HttpServer(serverConfig, ctx, dosGuardOverload, e), std::logic_error);
}
@@ -644,9 +701,11 @@ struct WebServerPrometheusTest : util::prometheus::WithPrometheus, WebServerTest
TEST_F(WebServerPrometheusTest, rejectedWithoutAdminPassword)
{
auto e = std::make_shared<EchoExecutor>();
auto const e = std::make_shared<EchoExecutor>();
uint32_t const webServerPort = tests::util::generateFreePort();
Config const serverConfig{boost::json::parse(JSONServerConfigWithAdminPassword(webServerPort))};
ClioConfigDefinition const serverConfig{
getParseAdminServerConfig(boost::json::parse(JSONServerConfigWithAdminPassword(webServerPort)))
};
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
auto const [status, res] = HttpSyncClient::get("localhost", std::to_string(webServerPort), "", "/metrics");
@@ -662,15 +721,18 @@ TEST_F(WebServerPrometheusTest, rejectedIfPrometheusIsDisabled)
"server":{{
"ip": "0.0.0.0",
"port": {},
"admin_password": "secret"
"admin_password": "secret",
"ws_max_sending_queue_size": 1500
}},
"prometheus": {{ "enabled": false }}
}})JSON",
webServerPort
);
auto e = std::make_shared<EchoExecutor>();
Config const serverConfig{boost::json::parse(JSONServerConfigWithDisabledPrometheus)};
auto const e = std::make_shared<EchoExecutor>();
ClioConfigDefinition const serverConfig{
getParseAdminServerConfig(boost::json::parse(JSONServerConfigWithDisabledPrometheus))
};
PrometheusService::init(serverConfig);
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
auto const [status, res] = HttpSyncClient::get(
@@ -692,8 +754,10 @@ TEST_F(WebServerPrometheusTest, validResponse)
uint32_t const webServerPort = tests::util::generateFreePort();
auto& testCounter = PrometheusService::counterInt("test_counter", util::prometheus::Labels());
++testCounter;
auto e = std::make_shared<EchoExecutor>();
Config const serverConfig{boost::json::parse(JSONServerConfigWithAdminPassword(webServerPort))};
auto const e = std::make_shared<EchoExecutor>();
ClioConfigDefinition const serverConfig{
getParseAdminServerConfig(boost::json::parse(JSONServerConfigWithAdminPassword(webServerPort)))
};
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
auto const [status, res] = HttpSyncClient::get(
"localhost",