From: Francis Dupont Date: Fri, 1 Dec 2017 15:19:33 +0000 (+0100) Subject: [5351] Checkpoint: todo servers, doc, host including DB X-Git-Tag: trac5444_base~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=237de10009ce68f4b0043641415393f4d086ba39;p=thirdparty%2Fkea.git [5351] Checkpoint: todo servers, doc, host including DB --- diff --git a/src/bin/dhcp4/dhcp4_lexer.ll b/src/bin/dhcp4/dhcp4_lexer.ll index 82bd35ead6..3f9027a4d6 100644 --- a/src/bin/dhcp4/dhcp4_lexer.ll +++ b/src/bin/dhcp4/dhcp4_lexer.ll @@ -582,7 +582,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::dhcp::Parser4Context::INTERFACES_CONFIG: case isc::dhcp::Parser4Context::LEASE_DATABASE: case isc::dhcp::Parser4Context::HOSTS_DATABASE: - case isc::dhcp::Parser4Context::HOOKS_LIBRARIES: case isc::dhcp::Parser4Context::SUBNET4: case isc::dhcp::Parser4Context::POOLS: case isc::dhcp::Parser4Context::SHARED_NETWORK: @@ -604,7 +603,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::dhcp::Parser4Context::INTERFACES_CONFIG: case isc::dhcp::Parser4Context::LEASE_DATABASE: case isc::dhcp::Parser4Context::HOSTS_DATABASE: - case isc::dhcp::Parser4Context::HOOKS_LIBRARIES: case isc::dhcp::Parser4Context::SUBNET4: case isc::dhcp::Parser4Context::POOLS: case isc::dhcp::Parser4Context::SHARED_NETWORK: diff --git a/src/bin/dhcp4/dhcp4_parser.yy b/src/bin/dhcp4/dhcp4_parser.yy index 4a8d54b0f9..e31f1570cf 100644 --- a/src/bin/dhcp4/dhcp4_parser.yy +++ b/src/bin/dhcp4/dhcp4_parser.yy @@ -760,13 +760,11 @@ sub_hooks_library: LCURLY_BRACKET { hooks_params: hooks_param | hooks_params COMMA hooks_param + | unknown_map_entry ; hooks_param: library | parameters - | user_context - | comment - | unknown_map_entry ; library: LIBRARY { diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll index b89595fa8b..c83ae03285 100644 --- a/src/bin/dhcp6/dhcp6_lexer.ll +++ b/src/bin/dhcp6/dhcp6_lexer.ll @@ -812,7 +812,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::dhcp::Parser6Context::INTERFACES_CONFIG: case isc::dhcp::Parser6Context::LEASE_DATABASE: case isc::dhcp::Parser6Context::HOSTS_DATABASE: - case isc::dhcp::Parser6Context::HOOKS_LIBRARIES: case isc::dhcp::Parser6Context::SUBNET6: case isc::dhcp::Parser6Context::SHARED_NETWORK: case isc::dhcp::Parser6Context::OPTION_DEF: @@ -836,7 +835,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::dhcp::Parser6Context::INTERFACES_CONFIG: case isc::dhcp::Parser6Context::LEASE_DATABASE: case isc::dhcp::Parser6Context::HOSTS_DATABASE: - case isc::dhcp::Parser6Context::HOOKS_LIBRARIES: case isc::dhcp::Parser6Context::SUBNET6: case isc::dhcp::Parser6Context::SHARED_NETWORK: case isc::dhcp::Parser6Context::OPTION_DEF: diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy index de8a416ea6..3b8bef3e2a 100644 --- a/src/bin/dhcp6/dhcp6_parser.yy +++ b/src/bin/dhcp6/dhcp6_parser.yy @@ -753,13 +753,11 @@ sub_hooks_library: LCURLY_BRACKET { hooks_params: hooks_param | hooks_params COMMA hooks_param + | unknown_map_entry ; hooks_param: library | parameters - | user_context - | comment - | unknown_map_entry ; library: LIBRARY { diff --git a/src/lib/dhcpsrv/cfg_db_access.cc b/src/lib/dhcpsrv/cfg_db_access.cc index e93631dc7b..53ae5001c4 100644 --- a/src/lib/dhcpsrv/cfg_db_access.cc +++ b/src/lib/dhcpsrv/cfg_db_access.cc @@ -65,12 +65,12 @@ CfgDbAccess::getAccessString(const std::string& access_string) const { return (s.str()); } -ElementPtr -CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) { - ElementPtr result = Element::createMap(); +void +CfgDbAccess::toElementDbAccessString(const std::string& dbaccess, + ElementPtr map) { // Code from DatabaseConnection::parse if (dbaccess.empty()) { - return (result); + return; } std::vector tokens; boost::split(tokens, dbaccess, boost::is_any_of(std::string("\t "))); @@ -86,7 +86,7 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) { int64_t int_value; try { int_value = boost::lexical_cast(value); - result->set(keyword, Element::create(int_value)); + map->set(keyword, Element::create(int_value)); } catch (...) { isc_throw(ToElementError, "invalid DB access " << "integer parameter: " @@ -95,9 +95,9 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) { } else if ((keyword == "persist") || (keyword == "readonly")) { if (value == "true") { - result->set(keyword, Element::create(true)); + map->set(keyword, Element::create(true)); } else if (value == "false") { - result->set(keyword, Element::create(false)); + map->set(keyword, Element::create(false)); } else { isc_throw(ToElementError, "invalid DB access " << "boolean parameter: " @@ -110,7 +110,7 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) { (keyword == "name") || (keyword == "contact_points") || (keyword == "keyspace")) { - result->set(keyword, Element::create(value)); + map->set(keyword, Element::create(value)); } else { isc_throw(ToElementError, "unknown DB access parameter: " << keyword << "=" << value); @@ -120,6 +120,23 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) { << ", expected format is name=value"); } } +} + +ElementPtr +CfgLeaseDbAccess::toElement() const { + ElementPtr result = Element::createMap(); + // Add user context + contextToElement(result); + CfgDbAccess::toElementDbAccessString(lease_db_access_, result); + return (result); +} + +ElementPtr +CfgHostDbAccess::toElement() const { + ElementPtr result = Element::createMap(); + // Add user context + contextToElement(result); + CfgDbAccess::toElementDbAccessString(host_db_access_, result); return (result); } diff --git a/src/lib/dhcpsrv/cfg_db_access.h b/src/lib/dhcpsrv/cfg_db_access.h index 2c87e4dafc..b74e94cc7f 100644 --- a/src/lib/dhcpsrv/cfg_db_access.h +++ b/src/lib/dhcpsrv/cfg_db_access.h @@ -8,6 +8,7 @@ #define CFG_DBACCESS_H #include +#include #include #include @@ -19,7 +20,7 @@ namespace dhcp { /// /// The database access strings use the same format as the strings /// passed to the @ref isc::dhcp::LeaseMgrFactory::create function. -class CfgDbAccess { +class CfgDbAccess : public UserContext { public: /// @brief Constructor. @@ -67,9 +68,10 @@ public: /// @brief Unparse an access string /// /// @param dbaccess the database access string - /// @return a pointer to configuration - static - isc::data::ElementPtr toElementDbAccessString(const std::string& dbaccess); + /// @param map the element map where the access string is unparse + static void + toElementDbAccessString(const std::string& dbaccess, + isc::data::ElementPtr map); protected: @@ -106,9 +108,7 @@ struct CfgLeaseDbAccess : public CfgDbAccess, public isc::data::CfgToElement { /// @ref isc::data::CfgToElement::toElement /// /// @result a pointer to a configuration - virtual isc::data::ElementPtr toElement() const { - return (CfgDbAccess::toElementDbAccessString(lease_db_access_)); - } + virtual isc::data::ElementPtr toElement() const; }; struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement { @@ -120,12 +120,9 @@ struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement { /// @ref isc::data::CfgToElement::toElement /// /// @result a pointer to a configuration - virtual isc::data::ElementPtr toElement() const { - return (CfgDbAccess::toElementDbAccessString(host_db_access_)); - } + virtual isc::data::ElementPtr toElement() const; }; } } - #endif // CFG_DBACCESS_H diff --git a/src/lib/dhcpsrv/cfg_duid.cc b/src/lib/dhcpsrv/cfg_duid.cc index fffae1aa7e..4eebc10e09 100644 --- a/src/lib/dhcpsrv/cfg_duid.cc +++ b/src/lib/dhcpsrv/cfg_duid.cc @@ -77,6 +77,8 @@ CfgDUID::create(const std::string& duid_file_path) const { ElementPtr CfgDUID::toElement() const { ElementPtr result = Element::createMap(); + // Set user context + contextToElement(result); // The type item is required std::string duid_type = "LLT"; switch (type_) { diff --git a/src/lib/dhcpsrv/cfg_duid.h b/src/lib/dhcpsrv/cfg_duid.h index dec70221f5..e93738eb04 100644 --- a/src/lib/dhcpsrv/cfg_duid.h +++ b/src/lib/dhcpsrv/cfg_duid.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -26,7 +27,7 @@ namespace dhcp { /// generate. It also allows for overriding entire default DUID or parts of /// it via configuration file. This class holds the DUID configuration /// specified in the server configuration file. -class CfgDUID : public isc::data::CfgToElement { +class CfgDUID : public UserContext, public isc::data::CfgToElement { public: /// @brief Constructor. diff --git a/src/lib/dhcpsrv/cfg_iface.cc b/src/lib/dhcpsrv/cfg_iface.cc index 8aad5eca52..ebb64f2dc8 100644 --- a/src/lib/dhcpsrv/cfg_iface.cc +++ b/src/lib/dhcpsrv/cfg_iface.cc @@ -441,6 +441,9 @@ ElementPtr CfgIface::toElement() const { ElementPtr result = Element::createMap(); + // Set user context + contextToElement(result); + // Set interfaces ElementPtr ifaces = Element::createList(); if (wildcard_used_) { diff --git a/src/lib/dhcpsrv/cfg_iface.h b/src/lib/dhcpsrv/cfg_iface.h index 57344c2911..6b36045d43 100644 --- a/src/lib/dhcpsrv/cfg_iface.h +++ b/src/lib/dhcpsrv/cfg_iface.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -126,7 +127,7 @@ public: /// to which it is bound. It is allowed to select multiple addresses on the /// particular interface explicitly, e.g. "eth0/192.168.8.1", /// "eth0/192.168.8.2". -class CfgIface : public isc::data::CfgToElement { +class CfgIface : public UserContext, public isc::data::CfgToElement { public: /// @brief Socket type used by the DHCPv4 server. diff --git a/src/lib/dhcpsrv/d2_client_cfg.cc b/src/lib/dhcpsrv/d2_client_cfg.cc index 14c45a5bc3..12718cf7ad 100644 --- a/src/lib/dhcpsrv/d2_client_cfg.cc +++ b/src/lib/dhcpsrv/d2_client_cfg.cc @@ -222,6 +222,8 @@ D2ClientConfig::toText() const { ElementPtr D2ClientConfig::toElement() const { ElementPtr result = Element::createMap(); + // Set user context + contextToElement(result); // Set enable-updates result->set("enable-updates", Element::create(enable_updates_)); // Set qualifying-suffix diff --git a/src/lib/dhcpsrv/d2_client_cfg.h b/src/lib/dhcpsrv/d2_client_cfg.h index 99a357ca19..b9e3b8a7a2 100644 --- a/src/lib/dhcpsrv/d2_client_cfg.h +++ b/src/lib/dhcpsrv/d2_client_cfg.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -48,7 +49,7 @@ public: /// parameters associated with DHCP-DDNS and acting as a client of D2. /// Instances of this class may be constructed through configuration parsing. /// -class D2ClientConfig : public isc::data::CfgToElement { +class D2ClientConfig : public UserContext, public isc::data::CfgToElement { public: /// @brief Default configuration constants. /// @todo For now these are hard-coded as configuration layer cannot diff --git a/src/lib/dhcpsrv/host.cc b/src/lib/dhcpsrv/host.cc index 573047bdaf..0df727130f 100644 --- a/src/lib/dhcpsrv/host.cc +++ b/src/lib/dhcpsrv/host.cc @@ -409,6 +409,8 @@ Host::toElement4() const { // Prepare the map ElementPtr map = Element::createMap(); + // Set the user context + contextToElement(map); // Set the identifier Host::IdentifierType id_type = getIdentifierType(); if (id_type == Host::IDENT_HWADDR) { diff --git a/src/lib/dhcpsrv/host.h b/src/lib/dhcpsrv/host.h index 1b3552429b..f4e99af17c 100644 --- a/src/lib/dhcpsrv/host.h +++ b/src/lib/dhcpsrv/host.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -171,7 +172,7 @@ typedef std::pair IPv6ResrvRange; /// - disable IPv4 reservation without a need to set it to the 0.0.0.0 address /// Note that the last three operations are mainly required for managing /// host reservations which will be implemented later. -class Host { +class Host : public UserContext { public: /// @brief Type of the host identifier. diff --git a/src/lib/dhcpsrv/logging.cc b/src/lib/dhcpsrv/logging.cc index d072bf8e98..6fad9354b5 100644 --- a/src/lib/dhcpsrv/logging.cc +++ b/src/lib/dhcpsrv/logging.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -52,6 +52,12 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) { // Remove default destinations as we are going to replace them. info.clearDestinations(); + // Get user context + isc::data::ConstElementPtr user_context = entry->get("user-context"); + if (user_context) { + info.setContext(user_context); + } + // Get a name isc::data::ConstElementPtr name_ptr = entry->get("name"); if (!name_ptr) { diff --git a/src/lib/dhcpsrv/logging_info.cc b/src/lib/dhcpsrv/logging_info.cc index d052273c25..ff39f3a886 100644 --- a/src/lib/dhcpsrv/logging_info.cc +++ b/src/lib/dhcpsrv/logging_info.cc @@ -159,6 +159,8 @@ LoggingInfo::toSpec() const { ElementPtr LoggingInfo::toElement() const { ElementPtr result = Element::createMap(); + // Set user context + contextToElement(result); // Set name result->set("name", Element::create(name_)); // Set output_options if not empty diff --git a/src/lib/dhcpsrv/logging_info.h b/src/lib/dhcpsrv/logging_info.h index 5dd5a11257..d74fb4f16d 100644 --- a/src/lib/dhcpsrv/logging_info.h +++ b/src/lib/dhcpsrv/logging_info.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,7 @@ namespace dhcp { /// /// This structure is used to keep log4cplus configuration parameters. struct LoggingDestination : public isc::data::CfgToElement { +public: /// @brief defines logging destination output /// @@ -71,7 +73,8 @@ struct LoggingDestination : public isc::data::CfgToElement { /// "severity": "WARN", /// "debuglevel": 99 /// }, -struct LoggingInfo : public isc::data::CfgToElement { +class LoggingInfo : public UserContext, public isc::data::CfgToElement { +public: /// @brief logging name std::string name_; diff --git a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc index e4231dc1e2..db54bbd137 100644 --- a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc +++ b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc @@ -56,6 +56,7 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db, int64_t lfc_interval = 0; int64_t timeout = 0; int64_t port = 0; + ConstElementPtr user_context; // 2. Update the copy with the passed keywords. BOOST_FOREACH(ConfigPair param, database_config->mapValue()) { try { @@ -78,6 +79,9 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db, values_copy[param.first] = boost::lexical_cast(port); + } else if (param.first == "user-context") { + user_context = param.second; + } else { values_copy[param.first] = param.second->stringValue(); } @@ -158,6 +162,9 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db, cfg_db->setHostDbAccessString(getDbAccessString()); } + if (user_context) { + cfg_db->setContext(user_context); + } } // Create the database access string diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 06b97e4858..4f5c5f8fdd 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -1246,6 +1246,12 @@ D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) { << client_config->getPosition() << ")"); } + // Add user context + ConstElementPtr user_context = client_config->get("user-context"); + if (user_context) { + new_config->setContext(user_context); + } + return(new_config); } diff --git a/src/lib/dhcpsrv/parsers/duid_config_parser.cc b/src/lib/dhcpsrv/parsers/duid_config_parser.cc index 4e0674b358..5817bafe7e 100644 --- a/src/lib/dhcpsrv/parsers/duid_config_parser.cc +++ b/src/lib/dhcpsrv/parsers/duid_config_parser.cc @@ -74,6 +74,12 @@ DUIDConfigParser::parse(const CfgDUIDPtr& cfg, if (duid_configuration->contains(param)) { cfg->setPersist(getBoolean(duid_configuration, param)); } + + param = "user-context"; + ConstElementPtr user_context = duid_configuration->get("user-context"); + if (user_context) { + cfg->setContext(user_context); + } } catch (const DhcpConfigError&) { throw; } catch (const std::exception& ex) { diff --git a/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc b/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc index bfa50a199c..c5559d810d 100644 --- a/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc +++ b/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc @@ -88,6 +88,11 @@ IfacesConfigParser::parse(const CfgIfacePtr& cfg, } } + if (element.first == "user-context") { + cfg->setContext(element.second); + continue; + } + // This should never happen as the input produced by the parser // see (src/bin/dhcpX/dhcpX_parser.yy) should not produce any // other parameter, so this case is only to catch bugs in diff --git a/src/lib/dhcpsrv/tests/cfg_db_access_unittest.cc b/src/lib/dhcpsrv/tests/cfg_db_access_unittest.cc index cc8361ae50..4b86a32fd4 100644 --- a/src/lib/dhcpsrv/tests/cfg_db_access_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_db_access_unittest.cc @@ -19,6 +19,7 @@ using namespace isc; using namespace isc::dhcp; using namespace isc::dhcp::test; using namespace isc::test; +using namespace isc::data; namespace { @@ -51,6 +52,12 @@ TEST(CfgDbAccessTest, setLeaseDbAccessString) { // Additional parameters are not in lease_db_access_ runToElementTest(expected, CfgLeaseDbAccess(cfg)); + // Add and check user context + std::string user_context = "{ \"foo\": \"bar\" }"; + cfg.setContext(Element::fromJSON(user_context)); + expected = "{ \"user-context\": { \"foo\": \"bar\" }, \"type\": \"mysql\" }"; + runToElementTest(expected, CfgLeaseDbAccess(cfg)); + // If access string is empty, no parameters will be appended. ASSERT_NO_THROW(cfg.setLeaseDbAccessString("")); EXPECT_TRUE(cfg.getLeaseDbAccessString().empty()); @@ -75,6 +82,12 @@ TEST(CfgDbAccessTest, setHostDbAccessString) { // Additional parameters are not in host_db_access_ runToElementTest(expected, CfgHostDbAccess(cfg)); + // Add and check user context + std::string user_context = "{ \"foo\": \"bar\" }"; + cfg.setContext(Element::fromJSON(user_context)); + expected = "{ \"user-context\": { \"foo\": \"bar\" }, \"type\": \"mysql\" }"; + runToElementTest(expected, CfgHostDbAccess(cfg)); + // If access string is empty, no parameters will be appended. ASSERT_NO_THROW(cfg.setHostDbAccessString("")); EXPECT_TRUE(cfg.getHostDbAccessString().empty()); diff --git a/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc b/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc index df9c7daf77..d0109333a1 100644 --- a/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc @@ -22,6 +22,7 @@ using namespace isc; using namespace isc::dhcp; using namespace isc::test; +using namespace isc::data; namespace { @@ -94,6 +95,7 @@ TEST_F(CfgDUIDTest, defaults) { EXPECT_EQ(0, cfg_duid.getTime()); EXPECT_EQ(0, cfg_duid.getEnterpriseId()); EXPECT_TRUE(cfg_duid.persist()); + EXPECT_FALSE(cfg_duid.getContext()); std::string expected = "{ \"type\": \"LLT\",\n" "\"identifier\": \"\",\n" @@ -114,6 +116,8 @@ TEST_F(CfgDUIDTest, setValues) { ASSERT_NO_THROW(cfg_duid.setTime(32100)); ASSERT_NO_THROW(cfg_duid.setEnterpriseId(10)); ASSERT_NO_THROW(cfg_duid.setPersist(false)); + std::string user_context = "{ \"comment\": \"foo\" }"; + ASSERT_NO_THROW(cfg_duid.setContext(Element::fromJSON(user_context))); // Check that values have been set correctly. EXPECT_EQ(DUID::DUID_EN, cfg_duid.getType()); @@ -122,8 +126,12 @@ TEST_F(CfgDUIDTest, setValues) { EXPECT_EQ(32100, cfg_duid.getTime()); EXPECT_EQ(10, cfg_duid.getEnterpriseId()); EXPECT_FALSE(cfg_duid.persist()); + ASSERT_TRUE(cfg_duid.getContext()); + EXPECT_EQ(user_context, cfg_duid.getContext()->str()); - std::string expected = "{ \"type\": \"EN\",\n" + std::string expected = "{\n" + " \"comment\": \"foo\",\n" + " \"type\": \"EN\",\n" " \"identifier\": \"ABCDEF\",\n" " \"htype\": 100,\n" " \"time\": 32100,\n" diff --git a/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc b/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc index efea58beda..de68db8b86 100644 --- a/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc @@ -15,6 +15,7 @@ using namespace isc; using namespace isc::dhcp; using namespace isc::dhcp::test; using namespace isc::test; +using namespace isc::data; namespace { @@ -368,10 +369,13 @@ TEST_F(CfgIfaceTest, unparse) { EXPECT_NO_THROW(cfg4.use(AF_INET, "*")); EXPECT_NO_THROW(cfg4.use(AF_INET, "eth0")); EXPECT_NO_THROW(cfg4.use(AF_INET, "eth1/192.0.2.3")); + std::string comment = "{ \"comment\": \"foo\" }"; + EXPECT_NO_THROW(cfg4.setContext(Element::fromJSON(comment))); // Check unparse std::string expected = - "{ \"interfaces\": [ \"*\", \"eth0\", \"eth1/192.0.2.3\" ], " + "{ \"comment\": \"foo\", " + "\"interfaces\": [ \"*\", \"eth0\", \"eth1/192.0.2.3\" ], " "\"re-detect\": false }"; runToElementTest(expected, cfg4); @@ -380,9 +384,12 @@ TEST_F(CfgIfaceTest, unparse) { EXPECT_NO_THROW(cfg6.use(AF_INET6, "*")); EXPECT_NO_THROW(cfg6.use(AF_INET6, "eth1")); EXPECT_NO_THROW(cfg6.use(AF_INET6, "eth0/2001:db8:1::1")); + comment = "{ \"comment\": \"bar\" }"; + EXPECT_NO_THROW(cfg6.setContext(Element::fromJSON(comment))); expected = - "{ \"interfaces\": [ \"*\", \"eth1\", \"eth0/2001:db8:1::1\" ], " + "{ \"comment\": \"bar\", " + "\"interfaces\": [ \"*\", \"eth1\", \"eth0/2001:db8:1::1\" ], " "\"re-detect\": false }"; runToElementTest(expected, cfg6); } diff --git a/src/lib/dhcpsrv/tests/d2_client_unittest.cc b/src/lib/dhcpsrv/tests/d2_client_unittest.cc index 8bf3d4a86f..856f4f775d 100644 --- a/src/lib/dhcpsrv/tests/d2_client_unittest.cc +++ b/src/lib/dhcpsrv/tests/d2_client_unittest.cc @@ -18,6 +18,7 @@ using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::util; using namespace isc::test; +using namespace isc::data; using namespace isc; namespace { @@ -101,6 +102,11 @@ TEST(D2ClientConfigTest, constructorsAndAccessors) { ASSERT_TRUE(d2_client_config); + // Add user context + std::string user_context = "{ \"comment\": \"foo\" }"; + EXPECT_FALSE(d2_client_config->getContext()); + d2_client_config->setContext(Element::fromJSON(user_context)); + // Verify that the accessors return the expected values. EXPECT_EQ(d2_client_config->getEnableUpdates(), enable_updates); @@ -119,12 +125,16 @@ TEST(D2ClientConfigTest, constructorsAndAccessors) { EXPECT_EQ(d2_client_config->getGeneratedPrefix(), generated_prefix); EXPECT_EQ(d2_client_config->getQualifyingSuffix(), qualifying_suffix); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ(d2_client_config->getContext()->str(), user_context); + // Verify that toText called by << operator doesn't bomb. ASSERT_NO_THROW(std::cout << "toText test:" << std::endl << *d2_client_config << std::endl); // Verify what toElement returns. std::string expected = "{\n" + "\"comment\": \"foo\",\n" "\"enable-updates\": true,\n" "\"server-ip\": \"127.0.0.1\",\n" "\"server-port\": 477,\n" diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index bbcb7edb7d..9ce068d667 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc @@ -1819,7 +1819,8 @@ TEST_F(ParseConfigTest, validD2Config) { " \"override-client-update\" : true, " " \"replace-client-name\" : \"when-present\", " " \"generated-prefix\" : \"test.prefix\", " - " \"qualifying-suffix\" : \"test.suffix.\" " + " \"qualifying-suffix\" : \"test.suffix.\", " + " \"user-context\": { \"foo\": \"bar\" } " " }" "}"; @@ -1845,6 +1846,8 @@ TEST_F(ParseConfigTest, validD2Config) { EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); // Verify that the configuration object unparses. ConstElementPtr expected; @@ -1871,7 +1874,8 @@ TEST_F(ParseConfigTest, validD2Config) { " \"override-client-update\" : false, " " \"replace-client-name\" : \"never\", " " \"generated-prefix\" : \"\", " - " \"qualifying-suffix\" : \"\" " + " \"qualifying-suffix\" : \"\", " + " \"user-context\": { \"foo\": \"bar\" } " " }" "}"; @@ -1896,6 +1900,8 @@ TEST_F(ParseConfigTest, validD2Config) { EXPECT_EQ(D2ClientConfig::RCM_NEVER, d2_client_config->getReplaceClientNameMode()); EXPECT_EQ("", d2_client_config->getGeneratedPrefix()); EXPECT_EQ("", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); ASSERT_NO_THROW(expected = Element::fromJSON(config_str2)->get("dhcp-ddns")); ASSERT_TRUE(expected); diff --git a/src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc b/src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc index dff3a84c52..bd17b032fa 100644 --- a/src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc @@ -107,7 +107,8 @@ TEST_F(IfacesConfigParserTest, toElement) { // Configuration with one interface. std::string config = - "{ \"interfaces\": [ \"eth0\" ], " + "{ \"user-context\": { \"foo\": \"bar\" }, " + " \"interfaces\": [ \"eth0\" ], " " \"dhcp-socket-type\": \"udp\"," " \"outbound-interface\": \"use-routing\", " " \"re-detect\": false }"; diff --git a/src/lib/dhcpsrv/tests/logging_info_unittest.cc b/src/lib/dhcpsrv/tests/logging_info_unittest.cc index f7474c94ee..f778765066 100644 --- a/src/lib/dhcpsrv/tests/logging_info_unittest.cc +++ b/src/lib/dhcpsrv/tests/logging_info_unittest.cc @@ -12,6 +12,7 @@ using namespace isc::dhcp; using namespace isc::test; +using namespace isc::data; namespace { @@ -71,7 +72,8 @@ TEST_F(LoggingInfoTest, defaults) { ASSERT_EQ(1, info_non_verbose.destinations_.size()); EXPECT_EQ("stdout", info_non_verbose.destinations_[0].output_); - std::string header = "{\n" + std::string header = "{\n"; + std::string begin = "\"name\": \"kea\",\n" "\"output_options\": [ {\n" " \"output\": \"stdout\",\n \"maxsize\": 10240000,\n" @@ -79,7 +81,17 @@ TEST_F(LoggingInfoTest, defaults) { "\"severity\": \""; std::string dbglvl = "\",\n\"debuglevel\": "; std::string trailer = "\n}\n"; - std::string expected = header + "INFO" + dbglvl + "0" + trailer; + std::string expected = header + begin + "INFO" + dbglvl + "0" + trailer; + runToElementTest(expected, info_non_verbose); + + // Add a user context + std::string comment = "\"comment\": \"foo\""; + std::string user_context = "{ " + comment + " }"; + EXPECT_FALSE(info_non_verbose.getContext()); + info_non_verbose.setContext(Element::fromJSON(user_context)); + ASSERT_TRUE(info_non_verbose.getContext()); + EXPECT_EQ(user_context, info_non_verbose.getContext()->str()); + expected = header + comment + ",\n" + begin + "INFO" + dbglvl + "0" + trailer; runToElementTest(expected, info_non_verbose); CfgMgr::instance().setVerbose(true); @@ -94,7 +106,15 @@ TEST_F(LoggingInfoTest, defaults) { EXPECT_EQ(10240000, info_verbose.destinations_[0].maxsize_); EXPECT_EQ(1, info_verbose.destinations_[0].maxver_); - expected = header + "DEBUG" + dbglvl + "99" + trailer; + expected = header + begin + "DEBUG" + dbglvl + "99" + trailer; + runToElementTest(expected, info_verbose); + + // User comment again + EXPECT_FALSE(info_verbose.getContext()); + info_verbose.setContext(Element::fromJSON(user_context)); + ASSERT_TRUE(info_verbose.getContext()); + EXPECT_EQ(user_context, info_verbose.getContext()->str()); + expected = header + comment + ",\n" + begin + "DEBUG" + dbglvl + "99" + trailer; runToElementTest(expected, info_verbose); } diff --git a/src/lib/testutils/user_context_utils.cc b/src/lib/testutils/user_context_utils.cc index fc01075cd7..e6eb52b334 100644 --- a/src/lib/testutils/user_context_utils.cc +++ b/src/lib/testutils/user_context_utils.cc @@ -211,7 +211,7 @@ EP extractComments1(EP element) { if (user_context->size() > 0) { result->set("user-context", user_context); } - result->combine_set("comment", comment); + result->combine_set("comment", copy(comment, 0)); } return (result);