Skip to content

Commit

Permalink
[irods#95] Refactor configuration loading
Browse files Browse the repository at this point in the history
  • Loading branch information
SwooshyCueb committed Nov 7, 2022
1 parent 98d69fc commit d60e395
Showing 1 changed file with 93 additions and 67 deletions.
160 changes: 93 additions & 67 deletions libirods_rule_engine_plugin-audit_amqp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@
#include <proton/sender.hpp>
#include <proton/session.hpp>

// nlohmann includes
// misc includes
#include <nlohmann/json.hpp>

// fmt includes
#include <fmt/core.h>
#include <fmt/compile.h>

Expand All @@ -45,6 +43,7 @@
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <chrono>
#include <map>
#include <fstream>
Expand All @@ -54,11 +53,20 @@ namespace
{

// NOLINTBEGIN(cert-err58-cpp, cppcoreguidelines-avoid-non-const-global-variables)
std::string audit_pep_regex_to_match{"audit_.*"};
std::string audit_amqp_topic{"irods_audit_messages"};
std::string audit_amqp_location{"localhost:5672"};
std::string log_path_prefix{"/tmp"};
bool test_mode = false;
const std::string_view default_pep_regex_to_match{"audit_.*"};
const std::string_view default_amqp_url{"localhost:5672/irods_audit_messages"};

const std::string_view default_log_path_prefix{"/tmp"};
const bool default_test_mode = false;

std::string audit_pep_regex_to_match;
std::string audit_amqp_url;

std::string log_path_prefix;
bool test_mode;

bool warned_amqp_options = false;

std::ofstream log_file_ofstream;

std::mutex audit_plugin_mutex;
Expand Down Expand Up @@ -96,21 +104,18 @@ namespace
{
public:
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
send_handler(const std::string& _message_body, const std::string& _location, const std::string& _topic)
: _amqp_location(_location)
, _amqp_topic(_topic)
send_handler(const std::string& _message_body, const std::string& _url)
: _amqp_url(_url)
, _message(_message_body)
, _message_sent(false)
{
message.content_type("application/json");
_message.content_type("application/json");
}

void on_container_start(proton::container& container) override
{
proton::connection_options conn_opts;
container.open_sender(
fmt::format(FMT_COMPILE("{0:s}/{1:s}"), _amqp_location, _amqp_topic),
conn_opts);
container.open_sender(_amqp_url, conn_opts);
}

void on_sendable(proton::sender& _sender) override
Expand Down Expand Up @@ -172,8 +177,7 @@ namespace
}

private:
const std::string& _amqp_location;
const std::string& _amqp_topic;
const std::string& _amqp_url;
proton::message _message;
bool _message_sent;
}; // class send_handler
Expand Down Expand Up @@ -228,60 +232,80 @@ namespace
}
}

// NOLINTNEXTLINE(readability-function-cognitive-complexity)
BOOST_FORCEINLINE void set_default_configs()
{
audit_pep_regex_to_match = default_pep_regex_to_match;
audit_amqp_url = default_amqp_url;
test_mode = default_test_mode;
log_path_prefix = default_log_path_prefix;
}

auto get_re_configs(const std::string& _instance_name) -> irods::error
{
try {
const auto& rule_engines = irods::get_server_property<const nlohmann::json&>(
std::vector<std::string>{irods::KW_CFG_PLUGIN_CONFIGURATION, irods::KW_CFG_PLUGIN_TYPE_RULE_ENGINE});
for (const auto& rule_engine : rule_engines) {
const auto& inst_name = rule_engine.at(irods::KW_CFG_INSTANCE_NAME).get_ref<const std::string&>();
if (inst_name == _instance_name) {
if (rule_engine.count(irods::KW_CFG_PLUGIN_SPECIFIC_CONFIGURATION) > 0) {
const auto& plugin_spec_cfg = rule_engine.at(irods::KW_CFG_PLUGIN_SPECIFIC_CONFIGURATION);
audit_pep_regex_to_match = plugin_spec_cfg.at("pep_regex_to_match").get<std::string>();
audit_amqp_topic = plugin_spec_cfg.at("amqp_topic").get<std::string>();
audit_amqp_location = plugin_spec_cfg.at("amqp_location").get<std::string>();

// look for a test mode setting. if it doesn't exist just keep test_mode at false.
// if test_mode = true and log_path_prefix isn't set just leave the default
const auto test_mode_cfg = plugin_spec_cfg.find("test_mode");
if (test_mode_cfg != plugin_spec_cfg.end()) {
const auto& test_mode_str = test_mode_cfg->get_ref<const std::string&>();
test_mode = boost::iequals(test_mode_str, "true");
if (test_mode) {
const auto log_path_prefix_cfg = plugin_spec_cfg.find("log_path_prefix");
if (log_path_prefix_cfg != plugin_spec_cfg.end()) {
log_path_prefix = log_path_prefix_cfg->get<std::string>();
}
}
}

// look for amqp_options and log a warning if it is present
const auto amqp_options_cfg = plugin_spec_cfg.find("amqp_options");
if (amqp_options_cfg != plugin_spec_cfg.end()) {
// clang-format off
log_re::warn({
{"rule_engine_plugin", rule_engine_name},
{"log_message", "Found amqp_options configuration setting. This setting is no longer "
"used and should be removed from the plugin configuration."},
{"instance_name", _instance_name},
});
// clang-format on
}
}
else {
// clang-format off
log_re::debug({
{"rule_engine_plugin", rule_engine_name},
{"log_message", "Using default plugin configuration"},
{"instance_name", _instance_name},
});
// clang-format on
}
if (inst_name != _instance_name) {
continue;
}

if (rule_engine.count(irods::KW_CFG_PLUGIN_SPECIFIC_CONFIGURATION) <= 0) {
set_default_configs();
// clang-format off
log_re::debug({
{"rule_engine_plugin", rule_engine_name},
{"log_message", "Using default plugin configuration"},
{"instance_name", _instance_name},
});
// clang-format on

return SUCCESS();
}

const auto& plugin_spec_cfg = rule_engine.at(irods::KW_CFG_PLUGIN_SPECIFIC_CONFIGURATION);

audit_pep_regex_to_match = plugin_spec_cfg.at("pep_regex_to_match").get<std::string>();

const auto& amqp_topic = plugin_spec_cfg.at("amqp_topic").get_ref<const std::string&>();
const auto& amqp_location = plugin_spec_cfg.at("amqp_location").get_ref<const std::string&>();
audit_amqp_url = fmt::format(FMT_STRING("{0:s}/{1:s}"), amqp_location, amqp_topic);

// test_mode is optional
const auto test_mode_cfg = plugin_spec_cfg.find("test_mode");
if (test_mode_cfg == plugin_spec_cfg.end()) {
test_mode = default_test_mode;
}
else {
const auto& test_mode_str = test_mode_cfg->get_ref<const std::string&>();
test_mode = boost::iequals(test_mode_str, "true");
}

// log_path_prefix is optional
const auto log_path_prefix_cfg = plugin_spec_cfg.find("log_path_prefix");
if (log_path_prefix_cfg == plugin_spec_cfg.end()) {
log_path_prefix = default_log_path_prefix;
}
else {
log_path_prefix = log_path_prefix_cfg->get<std::string>();
}

// look for amqp_options and log a warning if it is present
const auto amqp_options_cfg = plugin_spec_cfg.find("amqp_options");
if (amqp_options_cfg != plugin_spec_cfg.end() && !warned_amqp_options) {
// clang-format off
log_re::warn({
{"rule_engine_plugin", rule_engine_name},
{"log_message", "Found amqp_options configuration setting. This setting is no longer used and "
"should be removed from the plugin configuration."},
{"instance_name", _instance_name},
});
// clang-format on
warned_amqp_options = true;
}

return SUCCESS();
}
}
catch (const std::out_of_range& e) {
Expand Down Expand Up @@ -353,8 +377,8 @@ namespace
}

msg_str = json_obj.dump();
send_handler s(msg_str, audit_amqp_location, audit_amqp_topic); // NOLINT(readability-identifier-length)
proton::container(s).run();
send_handler handler(msg_str, audit_amqp_url);
proton::container(handler).run();

if (test_mode) {
log_file_ofstream.open(log_file);
Expand Down Expand Up @@ -405,8 +429,8 @@ namespace
}

msg_str = json_obj.dump();
send_handler s(msg_str, audit_amqp_location, audit_amqp_topic); // NOLINT(readability-identifier-length)
proton::container(s).run();
send_handler handler(msg_str, audit_amqp_url);
proton::container(handler).run();

if (test_mode) {
log_file_ofstream << msg_str << std::endl;
Expand Down Expand Up @@ -538,8 +562,8 @@ namespace
}

msg_str = json_obj.dump();
send_handler s(msg_str, audit_amqp_location, audit_amqp_topic); // NOLINT(readability-identifier-length)
proton::container(s).run();
send_handler handler(msg_str, audit_amqp_url);
proton::container(handler).run();

if (test_mode) {
log_file_ofstream << msg_str << std::endl;
Expand All @@ -558,6 +582,8 @@ using pluggable_rule_engine = irods::pluggable_rule_engine<irods::default_re_ctx

extern "C" auto plugin_factory(const std::string& _inst_name, const std::string& _context) -> pluggable_rule_engine*
{
set_default_configs();

const auto not_supported = [](auto&&...) { return ERROR(SYS_NOT_SUPPORTED, "Not supported."); };

auto* rule_engine = new irods::pluggable_rule_engine<irods::default_re_ctx>(_inst_name, _context);
Expand Down

0 comments on commit d60e395

Please sign in to comment.