mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-05 19:06:44 +00:00
new(unit_tests,userspace/falco): support loading and merging configs files when used from cmdline option.
Also, moved core logic from yaml_helper to falco_configuration class. Finally, updated tests. Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
parent
faabd41d9e
commit
e840a4ada0
@ -37,8 +37,6 @@ static std::string sample_yaml =
|
||||
" - elem2\n"
|
||||
" - elem3\n";
|
||||
|
||||
static std::vector<std::string> loaded_conf_files;
|
||||
|
||||
TEST(Configuration, configuration_exceptions)
|
||||
{
|
||||
yaml_helper conf;
|
||||
@ -137,8 +135,10 @@ TEST(Configuration, configuration_config_files_secondary_fail)
|
||||
outfile << conf_yaml_2;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_ANY_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_ANY_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@ -184,29 +184,31 @@ TEST(Configuration, configuration_config_files_ok)
|
||||
outfile << conf_yaml_4;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2 + conf_3
|
||||
ASSERT_EQ(loaded_conf_files.size(), 3);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(conf.is_defined("base_value.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(conf.is_defined("foo2"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(conf.is_defined("foo3"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo3", ""), "bar3");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(conf.is_defined("base_value_3.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value_3.name", ""), "foo3");
|
||||
ASSERT_FALSE(conf.is_defined("base_value_4.id")); // conf_4 is not included
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo3"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo3", ""), "bar3");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value_3.name", ""), "foo3");
|
||||
ASSERT_FALSE(falco_config.config.is_defined("base_value_4.id")); // conf_4 is not included
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@ -255,24 +257,26 @@ TEST(Configuration, configuration_config_files_relative_main)
|
||||
outfile << conf_yaml_3;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file(temp_main.string(), loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init(temp_main.string(), loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2 + conf_3
|
||||
ASSERT_EQ(loaded_conf_files.size(), 3);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(conf.is_defined("base_value.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(conf.is_defined("foo2"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(conf.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
|
||||
std::filesystem::remove(temp_main.string());
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@ -310,22 +314,24 @@ TEST(Configuration, configuration_config_files_override)
|
||||
outfile << conf_yaml_3;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2 + conf_3
|
||||
ASSERT_EQ(loaded_conf_files.size(), 3);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 3); // overridden!
|
||||
ASSERT_FALSE(conf.is_defined("base_value.name")); // no more present since entire `base_value` block was overridden
|
||||
ASSERT_TRUE(conf.is_defined("foo2"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_FALSE(conf.is_defined("base_value_3.id")); // not defined
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 3); // overridden!
|
||||
ASSERT_FALSE(falco_config.config.is_defined("base_value.name")); // no more present since entire `base_value` block was overridden
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_FALSE(falco_config.config.is_defined("base_value_3.id")); // not defined
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@ -334,7 +340,7 @@ TEST(Configuration, configuration_config_files_override)
|
||||
|
||||
TEST(Configuration, configuration_config_files_unexistent)
|
||||
{
|
||||
/* Test that including an unexistent file throws an exception */
|
||||
/* Test that including an unexistent file just skips it */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_5.yaml\n"
|
||||
@ -346,8 +352,18 @@ TEST(Configuration, configuration_config_files_unexistent)
|
||||
outfile << main_conf_yaml;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_ANY_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main
|
||||
ASSERT_EQ(loaded_conf_files.size(), 1);
|
||||
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
@ -374,22 +390,24 @@ TEST(Configuration, configuration_config_files_scalar_configs_files)
|
||||
outfile << conf_yaml_2;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2
|
||||
ASSERT_EQ(loaded_conf_files.size(), 2);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(conf.is_defined("base_value.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(conf.is_defined("foo2"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@ -409,18 +427,20 @@ TEST(Configuration, configuration_config_files_empty_configs_files)
|
||||
outfile << main_conf_yaml;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main
|
||||
ASSERT_EQ(loaded_conf_files.size(), 1);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(conf.is_defined("base_value.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
@ -439,8 +459,10 @@ TEST(Configuration, configuration_config_files_self)
|
||||
outfile << main_conf_yaml;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_ANY_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_ANY_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
@ -491,31 +513,80 @@ TEST(Configuration, configuration_config_files_directory)
|
||||
outfile << conf_yaml_4;
|
||||
outfile.close();
|
||||
|
||||
yaml_helper conf;
|
||||
ASSERT_NO_THROW(conf.load_from_file("main.yaml", loaded_conf_files));
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2 + conf_3.
|
||||
// test/foo is not parsed.
|
||||
ASSERT_EQ(loaded_conf_files.size(), 3);
|
||||
|
||||
ASSERT_TRUE(conf.is_defined("foo"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(conf.is_defined("base_value.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(conf.is_defined("base_value.name"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(conf.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(conf.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(conf.is_defined("foo2"));
|
||||
ASSERT_EQ(conf.get_scalar<std::string>("foo2", ""), "bar3");
|
||||
ASSERT_FALSE(conf.is_defined("foo4"));
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar3");
|
||||
ASSERT_FALSE(falco_config.config.is_defined("foo4"));
|
||||
|
||||
std::filesystem::remove("main");
|
||||
std::filesystem::remove_all(std::filesystem::temp_directory_path()/"test");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_cmdline)
|
||||
{
|
||||
/* Test that we support including configs files from cmdline option */
|
||||
const std::string main_conf_yaml =
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
outfile.close();
|
||||
|
||||
outfile.open("conf_2.yaml");
|
||||
outfile << conf_yaml_2;
|
||||
outfile.close();
|
||||
|
||||
// Pass "configs_files=..." cmdline option
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back((yaml_helper::configs_key+"=conf_2.yaml"));
|
||||
|
||||
std::vector<std::string> loaded_conf_files;
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init("main.yaml", loaded_conf_files, cmdline_config_options));
|
||||
|
||||
// main + conf_2
|
||||
ASSERT_EQ(loaded_conf_files.size(), 2);
|
||||
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_environment_variables)
|
||||
{
|
||||
// Set an environment variable for testing purposes
|
||||
|
@ -93,9 +93,10 @@ void falco_configuration::init(const std::vector<std::string>& cmdline_options)
|
||||
void falco_configuration::init(const std::string& conf_filename, std::vector<std::string>& loaded_conf_files,
|
||||
const std::vector<std::string> &cmdline_options)
|
||||
{
|
||||
loaded_conf_files.clear();
|
||||
try
|
||||
{
|
||||
config.load_from_file(conf_filename, loaded_conf_files);
|
||||
config.load_from_file(conf_filename);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
@ -103,6 +104,7 @@ void falco_configuration::init(const std::string& conf_filename, std::vector<std
|
||||
throw e;
|
||||
}
|
||||
init_cmdline_options(cmdline_options);
|
||||
merge_configs_files(conf_filename, loaded_conf_files);
|
||||
load_yaml(conf_filename);
|
||||
}
|
||||
|
||||
@ -111,6 +113,54 @@ std::string falco_configuration::dump()
|
||||
return config.dump();
|
||||
}
|
||||
|
||||
void falco_configuration::merge_configs_files(const std::string& config_name, std::vector<std::string>& loaded_config_files)
|
||||
{
|
||||
// Load configs files to be included and merge them into current config
|
||||
loaded_config_files.push_back(config_name);
|
||||
const auto ppath = std::filesystem::path(config_name);
|
||||
// Parse files to be included
|
||||
std::vector<std::string> include_files;
|
||||
config.get_sequence<std::vector<std::string>>(include_files, yaml_helper::configs_key);
|
||||
for(const std::string& include_file : include_files)
|
||||
{
|
||||
auto include_file_path = std::filesystem::path(include_file);
|
||||
if (include_file_path == ppath)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"Config error: '" + yaml_helper::configs_key + "' directive tried to recursively include main config file: " + config_name + ".");
|
||||
}
|
||||
if (!std::filesystem::exists(include_file_path))
|
||||
{
|
||||
// Same we do for rules_file: just skip the entry.
|
||||
continue;
|
||||
}
|
||||
if (std::filesystem::is_regular_file(include_file_path))
|
||||
{
|
||||
config.include_config_file(include_file_path.string());
|
||||
loaded_config_files.push_back(include_file);
|
||||
}
|
||||
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))
|
||||
{
|
||||
if (std::filesystem::is_regular_file(dir_entry.path()))
|
||||
{
|
||||
v.push_back(dir_entry.path().string());
|
||||
}
|
||||
}
|
||||
std::sort(v.begin(), v.end());
|
||||
for (const auto &f : v)
|
||||
{
|
||||
config.include_config_file(f);
|
||||
loaded_config_files.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void falco_configuration::load_engine_config(const std::string& config_name)
|
||||
{
|
||||
// Set driver mode if not already set.
|
||||
@ -608,12 +658,5 @@ void falco_configuration::set_cmdline_option(const std::string &opt)
|
||||
throw std::logic_error("Error parsing config option \"" + opt + "\". Must be of the form key=val or key.subkey=val");
|
||||
}
|
||||
|
||||
if (keyval.first.rfind(yaml_helper::configs_key, 0) == 0)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "Ignoring '-o " + yaml_helper::configs_key + "' directive: cannot be overridden by cmdline.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
config.set_scalar(keyval.first, keyval.second);
|
||||
}
|
||||
config.set_scalar(keyval.first, keyval.second);
|
||||
}
|
||||
|
@ -163,7 +163,12 @@ public:
|
||||
replay_config m_replay = {};
|
||||
gvisor_config m_gvisor = {};
|
||||
|
||||
// Needed by tests
|
||||
yaml_helper config;
|
||||
|
||||
private:
|
||||
void merge_configs_files(const std::string& config_name, std::vector<std::string>& loaded_config_files);
|
||||
|
||||
void load_yaml(const std::string& config_name);
|
||||
|
||||
void load_engine_config(const std::string& config_name);
|
||||
@ -177,8 +182,6 @@ private:
|
||||
* are supported and only scalar values are supported.
|
||||
*/
|
||||
void set_cmdline_option(const std::string& spec);
|
||||
|
||||
yaml_helper config;
|
||||
};
|
||||
|
||||
namespace YAML {
|
||||
|
@ -92,50 +92,31 @@ public:
|
||||
/**
|
||||
* Load the YAML document from the given file path.
|
||||
*/
|
||||
void load_from_file(const std::string& path, std::vector<std::string>& loaded_config_files)
|
||||
void load_from_file(const std::string& path)
|
||||
{
|
||||
loaded_config_files.clear();
|
||||
m_root = load_from_file_int(path);
|
||||
}
|
||||
|
||||
m_root = load_from_file_int(path, loaded_config_files);
|
||||
|
||||
const auto ppath = std::filesystem::path(path);
|
||||
// Parse files to be included
|
||||
std::vector<std::string> include_files;
|
||||
get_sequence<std::vector<std::string>>(include_files, configs_key);
|
||||
for(const std::string& include_file : include_files)
|
||||
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)
|
||||
{
|
||||
auto include_file_path = std::filesystem::path(include_file);
|
||||
if (include_file_path == ppath)
|
||||
/*
|
||||
* 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 tried to recursively include main config file: " + path + ".");
|
||||
}
|
||||
if (!std::filesystem::exists(include_file_path))
|
||||
{
|
||||
throw std::runtime_error("Included config entry not existent: " + include_file_path.string());
|
||||
}
|
||||
if (std::filesystem::is_regular_file(include_file_path))
|
||||
{
|
||||
include_config_file(include_file_path.string(), loaded_config_files);
|
||||
}
|
||||
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))
|
||||
{
|
||||
if (std::filesystem::is_regular_file(dir_entry.path()))
|
||||
{
|
||||
v.push_back(dir_entry.path().string());
|
||||
}
|
||||
}
|
||||
std::sort(v.begin(), v.end());
|
||||
for (const auto &f : v)
|
||||
{
|
||||
include_config_file(f, loaded_config_files);
|
||||
}
|
||||
"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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,37 +185,13 @@ public:
|
||||
private:
|
||||
YAML::Node m_root;
|
||||
|
||||
YAML::Node load_from_file_int(const std::string& path, std::vector<std::string>& loaded_config_files)
|
||||
YAML::Node load_from_file_int(const std::string& path)
|
||||
{
|
||||
auto root = YAML::LoadFile(path);
|
||||
pre_process_env_vars(root);
|
||||
loaded_config_files.push_back(path);
|
||||
return root;
|
||||
}
|
||||
|
||||
void include_config_file(const std::string& include_file_path, std::vector<std::string>& loaded_config_files)
|
||||
{
|
||||
auto loaded_nodes = load_from_file_int(include_file_path, loaded_config_files);
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user