because the parameters specified for the library (or the files those
parameters point to) may have changed.
+Since Kea-2.7.5, the server is able to load hooks specified only by name, if
+they reside in the default install location (the path is OS specific).
+
+::
+
+ "hooks-libraries": [
+ {
+ "library": "first_custom_hooks_example.so"
+ },
+ {
+ "library": "second_custom_hooks_example.so"
+ }
+ ]
+
+This snipper (on Ubuntu 24.04) is equivalent to:
+
+::
+
+ "hooks-libraries": [
+ {
+ "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/first_custom_hooks_example.so"
+ },
+ {
+ "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/second_custom_hooks_example.so"
+ }
+ ]
+
Libraries may have additional parameters that are not mandatory, in the
sense that there may be libraries that do not require them. However, for any
given library there is often a requirement to specify a certain
#include <exceptions/exceptions.h>
#include <hooks/hooks_parser.h>
#include <hooks/hooks_manager.h>
+#include <util/filesystem.h>
#include <testutils/gtest_utils.h>
#include <testutils/test_to_element.h>
using namespace isc::dhcp::test;
using namespace isc::hooks;
using namespace isc::test;
+using namespace isc::util::file;
namespace {
ParseConfigTest()
:family_(AF_INET6) {
reset_context();
+ HooksLibrariesParser::default_hooks_path_ = string(DEFAULT_HOOKS_PATH);
}
~ParseConfigTest() {
reset_context();
CfgMgr::instance().clear();
+ HooksLibrariesParser::default_hooks_path_ = string(DEFAULT_HOOKS_PATH);
}
/// @brief Parses a configuration.
EXPECT_EQ(CALLOUT_LIBRARY_1, hooks_libraries[0]);
}
+// hooks-libraries element that contains a single library with relative path.
+TEST_F(ParseConfigTest, oneHooksLibraryRelativePath) {
+ // Check that no libraries are currently loaded
+ vector<string> hooks_libraries = HooksManager::getLibraryNames();
+ EXPECT_TRUE(hooks_libraries.empty());
+
+ Path path(CALLOUT_LIBRARY_1);
+
+ HooksLibrariesParser::default_hooks_path_ = path.parentPath();
+
+ // Configuration with hooks-libraries set to a single library.
+ string config = setHooksLibrariesConfig(path.filename().c_str());
+
+ // Verify that the configuration string parses.
+ const int rcode = parseConfiguration(config);
+ ASSERT_TRUE(rcode == 0) << error_text_;
+
+ config = setHooksLibrariesConfig(CALLOUT_LIBRARY_1);
+
+ // Verify that the configuration object unparses.
+ ConstElementPtr expected;
+ ASSERT_NO_THROW(expected =
+ Element::fromJSON(config)->get("hooks-libraries"));
+ ASSERT_TRUE(expected);
+ const HooksConfig& cfg =
+ CfgMgr::instance().getStagingCfg()->getHooksConfig();
+ runToElementTest<HooksConfig>(expected, cfg);
+
+ // Check that the parser recorded a single library.
+ isc::hooks::HookLibsCollection libraries = getLibraries();
+ ASSERT_EQ(1, libraries.size());
+ EXPECT_EQ(CALLOUT_LIBRARY_1, libraries[0].first);
+
+ // Check that the change was propagated to the hooks manager.
+ hooks_libraries = HooksManager::getLibraryNames();
+ ASSERT_EQ(1, hooks_libraries.size());
+ EXPECT_EQ(CALLOUT_LIBRARY_1, hooks_libraries[0]);
+}
+
// hooks-libraries element that contains two libraries
TEST_F(ParseConfigTest, twoHooksLibraries) {
// Check that no libraries are currently loaded
// @todo use the flat style, split into list and item
+string HooksLibrariesParser::default_hooks_path_ = string(DEFAULT_HOOKS_PATH);
+
void
HooksLibrariesParser::parse(HooksConfig& libraries, ConstElementPtr value) {
// Initialize.
entry_item.second->getPosition() << ")");
}
+ // If only the name of the library was provided, add the full path.
+ if (libname.find("/") == string::npos) {
+ libname = HooksLibrariesParser::default_hooks_path_ + "/" + libname;
+ }
+
// Note we have found the library name.
lib_found = true;
continue;