1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00

initial config overriding on runtime

This commit is contained in:
jeff 2020-08-27 12:43:53 +00:00
parent e3bfe76f98
commit 5391e6a66a
10 changed files with 259 additions and 127 deletions

View file

@ -66,6 +66,10 @@ namespace llarp
void void
Configure(Config conf); Configure(Config conf);
/// handle SIGHUP
void
Reload();
bool bool
IsUp() const; IsUp() const;
@ -92,7 +96,7 @@ namespace llarp
makeRouter(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic); makeRouter(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic);
protected: protected:
std::unique_ptr<Config> config = nullptr; std::shared_ptr<Config> config = nullptr;
private: private:
void void

View file

@ -547,6 +547,18 @@ namespace llarp
"logging", "file", false, DefaultLogFile, AssignmentAcceptor(m_logFile)); "logging", "file", false, DefaultLogFile, AssignmentAcceptor(m_logFile));
} }
void
Config::Save() const
{
m_Parser.Save();
}
void
Config::Override(std::string section, std::string key, std::string value)
{
m_Parser.AddOverride(std::move(section), std::move(key), std::move(value));
}
bool bool
Config::Load(const fs::path fname, bool isRelay, fs::path defaultDataDir) Config::Load(const fs::path fname, bool isRelay, fs::path defaultDataDir)
{ {
@ -559,14 +571,13 @@ namespace llarp
ConfigDefinition conf; ConfigDefinition conf;
initializeConfig(conf, params); initializeConfig(conf, params);
addBackwardsCompatibleConfigOptions(conf); addBackwardsCompatibleConfigOptions(conf);
m_Parser.Clear();
ConfigParser parser; if (!m_Parser.LoadFile(fname))
if (!parser.LoadFile(fname))
{ {
return false; return false;
} }
parser.IterAll([&](std::string_view section, const SectionValues_t& values) { m_Parser.IterAll([&](std::string_view section, const SectionValues_t& values) {
for (const auto& pair : values) for (const auto& pair : values)
{ {
conf.addConfigValue(section, pair.first, pair.second); conf.addConfigValue(section, pair.first, pair.second);

View file

@ -224,6 +224,15 @@ namespace llarp
std::string std::string
generateBaseRouterConfig(fs::path defaultDataDir); generateBaseRouterConfig(fs::path defaultDataDir);
void
Save() const;
void
Override(std::string section, std::string key, std::string value);
private:
ConfigParser m_Parser;
}; };
void void

View file

@ -40,6 +40,7 @@ namespace llarp
void void
ConfigParser::Clear() ConfigParser::Clear()
{ {
m_Overrides.clear();
m_Config.clear(); m_Config.clear();
m_Data.clear(); m_Data.clear();
} }
@ -162,4 +163,32 @@ namespace llarp
return false; return false;
return visit(itr->second); return visit(itr->second);
} }
void
ConfigParser::AddOverride(std::string section, std::string key, std::string value)
{
m_Overrides[section].emplace(key, value);
}
void
ConfigParser::Save() const
{
// if we have no overrides keep the config the same on disk
if (m_Overrides.empty())
return;
std::ofstream ofs(m_FileName);
// write existing config data
ofs.write(m_Data.data(), m_Data.size());
// write overrides
ofs << std::endl << std::endl << "# overrides" << std::endl;
for (const auto& [section, values] : m_Overrides)
{
ofs << std::endl << "[" << section << "]" << std::endl;
for (const auto& [key, value] : values)
{
ofs << key << "=" << value << std::endl;
}
}
}
} // namespace llarp } // namespace llarp

View file

@ -40,12 +40,21 @@ namespace llarp
bool bool
VisitSection(const char* name, std::function<bool(const SectionValues_t&)> visit) const; VisitSection(const char* name, std::function<bool(const SectionValues_t&)> visit) const;
/// add a config option that is appended at the end of the config buffer with no comments
void
AddOverride(std::string section, std::string key, std::string value);
/// save config and any overrides to the file it was loaded from
void
Save() const;
private: private:
bool bool
Parse(); Parse();
std::vector<char> m_Data; std::vector<char> m_Data;
Config_impl_t m_Config; Config_impl_t m_Config;
Config_impl_t m_Overrides;
fs::path m_FileName; fs::path m_FileName;
}; };

View file

@ -33,7 +33,7 @@ namespace llarp
if (nullptr != config.get()) if (nullptr != config.get())
throw std::runtime_error("Config already exists"); throw std::runtime_error("Config already exists");
config = std::make_unique<Config>(std::move(conf)); config = std::make_shared<Config>(std::move(conf));
logic = std::make_shared<Logic>(); logic = std::make_shared<Logic>();
@ -85,7 +85,7 @@ namespace llarp
nodedb = std::make_unique<llarp_nodedb>( nodedb = std::make_unique<llarp_nodedb>(
nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); }); nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); });
if (!router->Configure(*config.get(), opts.isRouter, nodedb.get())) if (!router->Configure(config, opts.isRouter, nodedb.get()))
throw std::runtime_error("Failed to configure router"); throw std::runtime_error("Failed to configure router");
// must be done after router is made so we can use its disk io worker // must be done after router is made so we can use its disk io worker
@ -157,8 +157,17 @@ namespace llarp
{ {
SigINT(); SigINT();
} }
// TODO: Hot reloading would be kewl #ifndef _WIN32
// (it used to exist here, but wasn't maintained) if (sig == SIGHUP)
{
Reload();
}
#endif
}
void
Context::Reload()
{
} }
void void
@ -182,7 +191,7 @@ namespace llarp
Context::Close() Context::Close()
{ {
llarp::LogDebug("free config"); llarp::LogDebug("free config");
config.release(); config.reset();
llarp::LogDebug("free nodedb"); llarp::LogDebug("free nodedb");
nodedb.release(); nodedb.release();

View file

@ -1,6 +1,7 @@
#ifndef LLARP_ABSTRACT_ROUTER_HPP #ifndef LLARP_ABSTRACT_ROUTER_HPP
#define LLARP_ABSTRACT_ROUTER_HPP #define LLARP_ABSTRACT_ROUTER_HPP
#include <config/config.hpp>
#include <config/key_manager.hpp> #include <config/key_manager.hpp>
#include <memory> #include <memory>
#include <util/types.hpp> #include <util/types.hpp>
@ -134,6 +135,12 @@ namespace llarp
/// call function in disk io thread /// call function in disk io thread
virtual void QueueDiskIO(std::function<void(void)>) = 0; virtual void QueueDiskIO(std::function<void(void)>) = 0;
virtual std::shared_ptr<Config>
GetConfig() const
{
return nullptr;
}
virtual service::Context& virtual service::Context&
hiddenServiceContext() = 0; hiddenServiceContext() = 0;
@ -159,7 +166,7 @@ namespace llarp
Sign(Signature& sig, const llarp_buffer_t& buf) const = 0; Sign(Signature& sig, const llarp_buffer_t& buf) const = 0;
virtual bool virtual bool
Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb) = 0; Configure(std::shared_ptr<Config> conf, bool isRouter, llarp_nodedb* nodedb) = 0;
virtual bool virtual bool
IsServiceNode() const = 0; IsServiceNode() const = 0;

View file

@ -262,8 +262,10 @@ namespace llarp
} }
bool bool
Router::Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb) Router::Configure(std::shared_ptr<Config> c, bool isRouter, llarp_nodedb* nodedb)
{ {
m_Config = c;
auto& conf = *m_Config;
whitelistRouters = conf.lokid.whitelistRouters; whitelistRouters = conf.lokid.whitelistRouters;
if (whitelistRouters) if (whitelistRouters)
lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr); lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr);

View file

@ -353,7 +353,7 @@ namespace llarp
Close(); Close();
bool bool
Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb = nullptr) override; Configure(std::shared_ptr<Config> conf, bool isRouter, llarp_nodedb* nodedb = nullptr) override;
bool bool
StartRpcServer() override; StartRpcServer() override;
@ -499,6 +499,14 @@ namespace llarp
void void
AfterStopIssued(); AfterStopIssued();
std::shared_ptr<Config> m_Config;
std::shared_ptr<Config>
GetConfig() const override
{
return m_Config;
}
private: private:
std::atomic<bool> _stopping; std::atomic<bool> _stopping;
std::atomic<bool> _running; std::atomic<bool> _running;

View file

@ -110,7 +110,9 @@ namespace llarp::rpc
auto ftr = result.get_future(); auto ftr = result.get_future();
msg.send_reply(CreateJSONResponse(ftr.get())); msg.send_reply(CreateJSONResponse(ftr.get()));
}) })
.add_request_command("exit", [&](lokimq::Message& msg) { .add_request_command(
"exit",
[&](lokimq::Message& msg) {
HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) { HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) {
if (r->IsServiceNode()) if (r->IsServiceNode())
{ {
@ -236,6 +238,48 @@ namespace llarp::rpc
reply(CreateJSONResponse("OK")); reply(CreateJSONResponse("OK"));
}); });
}); });
})
.add_request_command("config", [&](lokimq::Message& msg) {
HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) {
{
const auto itr = obj.find("override");
if (itr != obj.end())
{
if (not itr->is_object())
{
reply(CreateJSONError(stringify("override is not an object")));
return;
}
for (const auto& [section, value] : itr->items())
{
if (not value.is_object())
{
reply(CreateJSONError(
stringify("failed to set [", section, "] section is not an object")));
return;
}
for (const auto& [key, value] : value.items())
{
if (not value.is_string())
{
reply(CreateJSONError(stringify(
"failed to set [", section, "]:", key, " value is not a string")));
return;
}
r->GetConfig()->Override(section, key, value.get<std::string>());
}
}
}
}
{
const auto itr = obj.find("reload");
if (itr != obj.end() and itr->get<bool>())
{
r->QueueDiskIO([conf = r->GetConfig()]() { conf->Save(); });
}
}
reply(CreateJSONResponse("OK"));
});
}); });
} }
} // namespace llarp::rpc } // namespace llarp::rpc