central nginx manager

This commit is contained in:
Ned Wright
2025-01-13 12:35:42 +00:00
parent 35b2df729f
commit 6db87fc7fe
45 changed files with 390 additions and 130 deletions

View File

@@ -50,6 +50,7 @@ public:
bool bindRestServerSocket(struct sockaddr_in6 &addr, vector<uint16_t> port_range);
bool addRestCall(RestAction oper, const string &uri, unique_ptr<RestInit> &&init) override;
bool addGetCall(const string &uri, const function<string()> &cb) override;
bool addWildcardGetCall(const string &uri, const function<string(const string &)> &callback);
uint16_t getListeningPort() const override { return listening_port; }
Maybe<string> getSchema(const string &uri) const override;
Maybe<string> invokeRest(const string &uri, istream &in) const override;
@@ -67,6 +68,7 @@ private:
I_MainLoop *mainloop;
map<string, unique_ptr<RestInit>> rest_calls;
map<string, function<string()>> get_calls;
map<string, function<string(const string &)>> wildcard_get_calls;
uint16_t listening_port = 0;
vector<uint16_t> port_range;
};
@@ -128,11 +130,14 @@ RestServer::Impl::prepareConfiguration()
} else {
auto range_start = getPortConfig("Nano service API Port Range start");
auto range_end = getPortConfig("Nano service API Port Range end");
dbgAssert(range_start.ok() && range_end.ok()) << alert << "Rest port configuration was not provided";
dbgAssert(*range_start < *range_end)
<< alert
<< "Rest port range corrupted (lower bound higher then upper bound)";
if (!(range_start.ok() && range_end.ok()) || !(*range_start < *range_end)) {
dbgAssertOpt(range_start.ok() && range_end.ok()) << alert << "Rest port configuration was not provided";
dbgAssertOpt(*range_start < *range_end)
<< alert
<< "Rest port range corrupted (lower bound higher then upper bound)";
range_start = 0;
range_end = 1;
}
port_range.resize(*range_end - *range_start);
for (uint16_t i = 0, port = *range_start; i < port_range.size(); i++, port++) {
port_range[i] = port;
@@ -283,6 +288,13 @@ RestServer::Impl::addGetCall(const string &uri, const function<string()> &callba
return get_calls.emplace(uri, callback).second;
}
bool
RestServer::Impl::addWildcardGetCall(const string &uri, const function<string(const string&)> &callback)
{
if (rest_calls.find(uri) != rest_calls.end()) return false;
return wildcard_get_calls.emplace(uri, callback).second;
}
Maybe<string>
RestServer::Impl::getSchema(const string &uri) const
{
@@ -307,14 +319,26 @@ RestServer::Impl::invokeRest(const string &uri, istream &in) const
bool
RestServer::Impl::isGetCall(const string &uri) const
{
return get_calls.find(uri) != get_calls.end();
if (get_calls.find(uri) != get_calls.end()) return true;
for (const auto &wildcard : wildcard_get_calls) {
if (!uri.find(wildcard.first)) return true;
}
return false;
}
string
RestServer::Impl::invokeGet(const string &uri) const
{
auto instance = get_calls.find(uri);
return instance != get_calls.end() ? instance->second() : "";
if (instance != get_calls.end()) return instance->second();
for (const auto &wildcard : wildcard_get_calls) {
if (!uri.find(wildcard.first)) return wildcard.second(uri);
}
return "";
}
string
@@ -334,8 +358,8 @@ RestServer::Impl::changeActionToString(RestAction oper)
return "delete-";
}
default: {
dbgAssert(false) << alert << "Unknown REST action";
return "";
dbgAssertOpt(false) << alert << "Unknown REST action";
return "unknown-";
}
}
}

View File

@@ -4,5 +4,5 @@ link_directories(${ng_module_osrc_zlib_path}/lib)
add_unit_test(
rest_server_ut
"rest_schema_ut.cc;rest_must_param_ut.cc;rest_config_ut.cc"
"singleton;messaging;tenant_manager;rest;environment;-lz;shell_cmd;-lboost_filesystem;instance_awareness;-lz;debug_is;time_proxy;mainloop;agent_details;encryptor;event_is;metric;-lboost_context;-lboost_regex;-lboost_system;-lssl;-lcrypto;connkey"
"singleton;messaging;tenant_manager;rest;environment;-lz;shell_cmd;-lboost_filesystem;instance_awareness;-lz;version;debug_is;time_proxy;mainloop;agent_details;encryptor;event_is;metric;-lboost_context;-lboost_regex;-lboost_system;-lssl;-lcrypto;connkey"
)

View File

@@ -171,11 +171,16 @@ TEST_F(RestConfigTest, basic_flow)
auto i_rest = Singleton::Consume<I_RestApi>::from(rest_server);
ASSERT_TRUE(i_rest->addRestCall<TestServer>(RestAction::ADD, "test"));
ASSERT_TRUE(i_rest->addGetCall("stuff", [] () { return string("blabla"); }));
ASSERT_TRUE(
i_rest->addWildcardGetCall("api/", [] (const string &uri) { return uri.substr(uri.find_last_of('/') + 1); })
);
int file_descriptor1 = socket(AF_INET, SOCK_STREAM, 0);
EXPECT_NE(file_descriptor1, -1);
int file_descriptor2 = socket(AF_INET, SOCK_STREAM, 0);
EXPECT_NE(file_descriptor2, -1);
int file_descriptor3 = socket(AF_INET, SOCK_STREAM, 0);
EXPECT_NE(file_descriptor3, -1);
auto primary_port = getConfiguration<uint>("connection", "Nano service API Port Alternative");
struct sockaddr_in sa;
@@ -185,6 +190,7 @@ TEST_F(RestConfigTest, basic_flow)
int socket_enable = 1;
EXPECT_EQ(setsockopt(file_descriptor1, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
EXPECT_EQ(setsockopt(file_descriptor2, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
EXPECT_EQ(setsockopt(file_descriptor3, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
EXPECT_CALL(messaging, sendSyncMessage(_, _, _, _, _))
.WillRepeatedly(Return(HTTPResponse(HTTPStatusCode::HTTP_OK, "")));
@@ -203,6 +209,11 @@ TEST_F(RestConfigTest, basic_flow)
string msg2 = "POST /add-test HTTP/1.1\r\nContent-Length: 10\r\n\r\n{\"num\": 5}";
EXPECT_EQ(write(file_descriptor2, msg2.data(), msg2.size()), static_cast<int>(msg2.size()));
EXPECT_EQ(connect(file_descriptor3, (struct sockaddr*)&sa, sizeof(struct sockaddr)), 0)
<< "file_descriptor3 Error: "
<< strerror(errno);
string msg3 = "GET /api/123 HTTP/1.1\r\n\r\n";
EXPECT_EQ(write(file_descriptor3, msg3.data(), msg3.size()), static_cast<int>(msg3.size()));
while(!TestServer::g_num) {
mainloop->yield(true);
}
@@ -215,6 +226,14 @@ TEST_F(RestConfigTest, basic_flow)
mainloop->yield(true);
}
struct pollfd s_poll3;
s_poll3.fd = file_descriptor3;
s_poll3.events = POLLIN;
s_poll3.revents = 0;
while(poll(&s_poll3, 1, 0) <= 0) {
mainloop->yield(true);
}
mainloop->stopAll();
};
mainloop->addOneTimeRoutine(
@@ -233,6 +252,11 @@ TEST_F(RestConfigTest, basic_flow)
string(respose, 76),
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 6\r\n\r\nblabla"
);
EXPECT_EQ(read(file_descriptor3, respose, 1000), 73);
EXPECT_EQ(
string(respose, 73),
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 3\r\n\r\n123"
);
}
string