chore(userspace,unit_tests): support loading config files from directories.

The files inside the folder will be loaded in lexicographic order,
like we do for rules_file.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
Federico Di Pierro
2024-04-08 09:53:07 +02:00
committed by poiana
parent 5e51828509
commit df220e3c3b
2 changed files with 121 additions and 35 deletions

View File

@@ -116,31 +116,43 @@ public:
throw std::runtime_error(
"Config error: '" + configs_key + "' directive tried to recursively include main config file: " + path + ".");
}
if (std::filesystem::exists(include_file_path) && std::filesystem::is_regular_file(include_file_path))
if (std::filesystem::exists(include_file_path))
{
auto loaded_nodes = load_from_file_int(include_file_path.string());
for(auto n : loaded_nodes)
if (std::filesystem::is_regular_file(include_file_path))
{
/*
* To avoid recursion hell,
* we don't support `configs_files` directives from included config files
* (that use load_from_file_int recursively).
*/
const auto &key = n.first.Scalar();
if (key == configs_key)
include_config_file(include_file_path.string());
}
else if (std::filesystem::is_directory(include_file_path))
{
std::vector<std::string> v;
const auto it_options = std::filesystem::directory_options::follow_directory_symlink
| std::filesystem::directory_options::skip_permission_denied;
for (auto const& dir_entry : std::filesystem::directory_iterator(include_file_path, it_options))
{
throw std::runtime_error(
"Config error: '" + configs_key + "' directive in included config file " + include_file + ".");
if (std::filesystem::is_regular_file(dir_entry.path()))
{
v.push_back(dir_entry.path().string());
}
// We don't support nested directories
else
{
falco_logger::log(falco_logger::level::WARNING, "Included config file has wrong type: " + dir_entry.path().string());
}
std::sort(v.begin(), v.end());
for (const auto &f : v)
{
include_config_file(f);
}
}
// We allow to override keys.
// We don't need to use `get_node()` here,
// since key is a top-level one.
m_root[key] = n.second;
}
else
{
falco_logger::log(falco_logger::level::WARNING, "Included config entry has wrong type: " + include_file_path.string());
}
}
else
{
falco_logger::log(falco_logger::level::WARNING, "Included config file unexistent or wrong type: " + include_file_path.string());
falco_logger::log(falco_logger::level::WARNING, "Included config entry unexistent: " + include_file_path.string());
}
}
}
@@ -210,6 +222,29 @@ private:
return root;
}
void include_config_file(const std::string& include_file_path)
{
auto loaded_nodes = load_from_file_int(include_file_path);
for(auto n : loaded_nodes)
{
/*
* To avoid recursion hell,
* we don't support `configs_files` directives from included config files
* (that use load_from_file_int recursively).
*/
const auto &key = n.first.Scalar();
if (key == configs_key)
{
throw std::runtime_error(
"Config error: '" + configs_key + "' directive in included config file " + include_file_path + ".");
}
// We allow to override keys.
// We don't need to use `get_node()` here,
// since key is a top-level one.
m_root[key] = n.second;
}
}
/*
* When loading a yaml file,
* we immediately pre process all scalar values through a visitor private API,