From 07e75c55e0c0a1a9b188d3ab339c014363c32865 Mon Sep 17 00:00:00 2001 From: Tomek Mrugalski Date: Tue, 15 Mar 2016 10:36:48 +0100 Subject: [PATCH] [4297] Hooks documentation updated. --- src/lib/hooks/hooks_user.dox | 133 +++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/src/lib/hooks/hooks_user.dox b/src/lib/hooks/hooks_user.dox index ad6ade972a..2c59aeddff 100644 --- a/src/lib/hooks/hooks_user.dox +++ b/src/lib/hooks/hooks_user.dox @@ -1271,4 +1271,137 @@ int load() { } @endcode + +@subsection hooksdgHooksConfig Configuring Hooks Libraries + +Sometimes it is useful for the hook library to have some configuration parameters. +This capability was introduced in Kea 1.1. This is often convenient to follow +generic Kea configuration approach rather than invent your own configuration +logic. Consider the following example: + +@code +"hooks-libraries": [ + { + "library": "/opt/first.so" + }, + { + "library": "/opt/second.so", + "parameters": { + } + }, + { + "library": "/opt/third.so", + "parameters": { + "mail": "spam@example.com", + "floor": 13, + "debug": false, + "users": [ "alice", "bob", "charlie" ], + "languages": { + "french": "bonjour", + "klingon": "yl'el" + } + } + } +] +@endcode + +This example has three hook libraries configured. The first and and second have +no parameters. Note that parameters map is optional, but it's perfectly ok to +specify it as an empty map. The third library is more interesting. It has five +parameters specified. The first one called 'mail' is a string. The second one +is an integer and the third one is boolean. Fourth and fifth parameters are +slightly more complicated as they are a list and a map respectively. JSON +structures can be nested if necessary, e.g. you can have a list, which contains +maps, maps that contain maps that contain other maps etc. Any valid JSON +structure can be repesented. One important limitation here is that the top +level "parameters" structure must either be a map or not present at all. + +Those parameters can be accessed in load() method. Passed isc::hooks::LibraryHandle +object has a method called getParameter that returns an instance of +isc::data::ConstElementPtr or NULL if there was no parameter specified. This pointer +will point to an object derived from isc::data::Element class. For detailed +explanation how to use those objects, see isc::data::Element class. + +Here's a brief overview of how to use those elements: + + - x = getParameter("mail") will return instance of isc::data::StringElement. The content + can be accessed with x->stringValue() and will return std::string. + - x = getParameter("floor") will return an instance of isc::data::IntElement. + The content can be accessed with x->intValue() and will return int. + - x = getParameter("debug") will return an instance of isc::data::BoolElement. + Its value can be accessed with x->boolValue() and will return bool. + - x = getParameter("users") will return an instance of isc::data::ListElement. + Its content can be accessed with the following methods: + x->size(), x->get(index) + - x = getParameter("watch-list") will return an instance of isc::data::MapElement. + Its content can be accessed with the following methods: + x->find("klingon"), x->contains("french"), x->size() + +Keep in mind that the user can structure his config file incorrectly. +Remember to check if the structure has expected type before using type specific +method. For example calling stringValue on IntElement will throw an exception. +You can do this by calling isc::data::Element::getType. + +Here's an example that obtains all of the parameters specified above. +If you want to get nested elemented, Element::get(index) and Element::find(name) +will return ElementPtr, which can be iterated in similar manner. + +@code +int load(LibraryHandle& handle) { + ConstElementPtr mail = handle.getParameter("mail"); + ConstElementPtr floor = handle.getParameter("floor"); + ConstElementPtr debug = handle.getParameter("debug"); + ConstElementPtr users = handle.getParameter("users"); + ConstElementPtr lang = handle.getParameter("languages"); + + // String handling example + if (!mail) { + // Handle missing 'mail' parameter here. + return (1); + } + if (mail->getType() != Element::string) { + // Handle incorrect 'mail' parameter here. + return (1); + } + std::string mail_str = mail->stringValue(); + + // In the following examples safety checks are omitted for clarity. + // Make sure you do it properly similar to mail example above + // or you risk dereferencing NULL pointer or at least throwing + // an exception! + + // Integer handling example + int floor_num = floor->intValue(); + + // Boolean handling example + bool debug_flag = debug->boolValue(); + + // List handling example + std::cout << "There are " << users->size() << " users defined." << std::endl; + for (int i = 0; i < users->size(); i++) { + ConstElementPtr user = users->get(i); + std::cout << "User " << user->stringValue() << std::endl; + } + + // Map handling example + std::cout << "There are " << lang->size() << " languages defined." << std::endl; + if (lang->contains("french")) { + std::cout << "One of them is French!" << std::endl; + } + ConstElementPtr greeting = lang->find("klingon"); + if (greeting) { + std::cout << "Lt. Worf says " << greeting->stringValue() << std::endl; + } + + // All validation steps were successful. The library has all the parameters + // it needs, so we should report a success. + return (0); +} +@endcode + +A good sources of examples could be unit-tests in file src/lib/cc/tests/data_unittests.cc +which are dedicated to isc::data::Element testing and src/lib/hooks/tests/callout_params_library.cc, +which is an example library used in testing. This library expects exactly 3 parameters: +svalue (which is a string), ivalue (which is an integer) and bvalue (which is a boolean). + */ -- 2.47.2