From: Thomas Markwalder Date: Thu, 27 Sep 2018 14:27:27 +0000 (-0400) Subject: [#32,!23] Added ControlConfigParser to lib/config X-Git-Tag: 153-netconf-control-socket_base~4^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5422f05ec4d6654110449643abd03835a90f876f;p=thirdparty%2Fkea.git [#32,!23] Added ControlConfigParser to lib/config src/lib/config/config_ctl_parser.* - new files implementing ControlConfigParser src/lib/config/Makefile.am - added new files src/lib/config/tests/config_ctl_parser_unittests.cc - new file which tests new parser src/lib/config/tests/Makefile.am - added new file --- diff --git a/src/lib/config/Makefile.am b/src/lib/config/Makefile.am index 1f2203033e..62b613891d 100644 --- a/src/lib/config/Makefile.am +++ b/src/lib/config/Makefile.am @@ -20,6 +20,7 @@ libkea_cfgclient_la_SOURCES += base_command_mgr.cc base_command_mgr.h libkea_cfgclient_la_SOURCES += client_connection.cc client_connection.h libkea_cfgclient_la_SOURCES += command_mgr.cc command_mgr.h libkea_cfgclient_la_SOURCES += config_ctl_info.h config_ctl_info.cc +libkea_cfgclient_la_SOURCES += config_ctl_parser.h config_ctl_parser.cc libkea_cfgclient_la_SOURCES += config_log.h config_log.cc libkea_cfgclient_la_SOURCES += hooked_command_mgr.cc hooked_command_mgr.h libkea_cfgclient_la_SOURCES += timeouts.h diff --git a/src/lib/config/config_ctl_info.h b/src/lib/config/config_ctl_info.h index 7c940bcd49..b188e527fc 100644 --- a/src/lib/config/config_ctl_info.h +++ b/src/lib/config/config_ctl_info.h @@ -107,7 +107,7 @@ typedef std::vector ConfigDbInfoList; /// This is class conveys the configuration control information /// described by the following JSON text: /// -/// "ConfigCtl" : +/// "config-ctl" : /// { /// "config-databases": /// [ diff --git a/src/lib/config/config_ctl_parser.cc b/src/lib/config/config_ctl_parser.cc new file mode 100644 index 0000000000..aba1c59109 --- /dev/null +++ b/src/lib/config/config_ctl_parser.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2018 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 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include +#include +#include +#include + +using namespace isc; +using namespace isc::data; + +namespace isc { +namespace config { + +ConfigControlInfoPtr +ConfigControlParser::parse(const data::ConstElementPtr& config_control) { + ConfigControlInfoPtr ctl_info(new ConfigControlInfo()); + + try { + if (config_control->contains("config-databases")) { + const std::vector& db_list = + config_control->get("config-databases")->listValue(); + + for (auto db = db_list.cbegin(); db != db_list.end(); ++db) { + db::DbAccessParser parser; + std::string access_string; + parser.parse(access_string, *db); + // @todo do we still need access_string for this at all? + // can't we just use params directly and get rid of the + // string now that DatabaseConnection::toElement(map) exists? + ctl_info->addConfigDatabase(access_string); + } + } + +#if 0 + // @todo, should it have user_context and what about comment? + ConstElementPtr user_context = shared_network_data->get("user-context"); + if (user_context) { + shared_network->setContext(user_context); + } +#endif + + } catch (const isc::ConfigError&) { + // Position was already added + throw; + } catch (const std::exception& ex) { + isc_throw(ConfigError, ex.what() << " (" + << config_control->getPosition() << ")"); + } + + return (ctl_info); +} + +} // end of namespace isc::config +} // end of namespace isc + diff --git a/src/lib/config/config_ctl_parser.h b/src/lib/config/config_ctl_parser.h new file mode 100644 index 0000000000..5e254bf075 --- /dev/null +++ b/src/lib/config/config_ctl_parser.h @@ -0,0 +1,35 @@ +// Copyright (C) 2018 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 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef CONFIG_CONTROL_PARSER_H +#define CONFIG_CONTROL_PARSER_H + +#include +#include +#include + +namespace isc { +namespace config { + +/// @brief Implements parser for config control information, "config-control" +class ConfigControlParser : isc::data::SimpleParser { +public: + + /// @brief Parses a configuration control Element + /// + /// @param config_control Element holding the config control content + /// to be parsed. + /// + /// @return Pointer to newly created ConfigControlInfo instance + /// @throw DhcpConfigError when config control content is invalid. + ConfigControlInfoPtr + parse(const data::ConstElementPtr& config_control); +}; + +} // enf of namespace isc::config +} // end of namespace isc + +#endif // CONFIG_CONTROL_PARSER_H diff --git a/src/lib/config/tests/Makefile.am b/src/lib/config/tests/Makefile.am index 77330bf0dd..c98f7b6188 100644 --- a/src/lib/config/tests/Makefile.am +++ b/src/lib/config/tests/Makefile.am @@ -23,6 +23,7 @@ run_unittests_SOURCES = client_connection_unittests.cc run_unittests_SOURCES += run_unittests.cc run_unittests_SOURCES += command_mgr_unittests.cc run_unittests_SOURCES += config_ctl_info_unittests.cc +run_unittests_SOURCES += config_ctl_parser_unittests.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS) diff --git a/src/lib/config/tests/config_ctl_parser_unittests.cc b/src/lib/config/tests/config_ctl_parser_unittests.cc new file mode 100644 index 0000000000..845acd1d1a --- /dev/null +++ b/src/lib/config/tests/config_ctl_parser_unittests.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2018 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 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include + +#include + +#include +#include + +using namespace isc::config; +using namespace isc::data; + +// Verifies valid configurations are parsed correctly. The test +// uses round-trip comparison of configuration Elements to determine +// if parsing was correct. +TEST(ConfigCtlInfoParser, validConfigs) { + std::string configs[] = { + "{}", + + "{ \"config-databases\": [] }", + + "{ \"config-databases\": [ \n" + " { \n" + " \"type\": \"mysql\", \n" + " \"user\":\"tom\", \n" + " \"password\":\"terrific\" \n" + " }, \n" + " { \n" + " \"type\": \"postgresql\",\n" + " \"user\":\"bob\", \n" + " \"password\":\"wonder\" \n" + " } \n" + "] } \n" + }; + + for (auto config : configs) { + ConfigControlParser parser; + ConfigControlInfoPtr ctl_info; + + // Turn the JSON config into Elements. + ElementPtr source_elem; + ASSERT_NO_THROW (source_elem = Element::fromJSON(config)) << + " JSON error, test is broken: " << config; + + // Parse the Elements into a ConfigControlInfo. + ASSERT_NO_THROW(ctl_info = parser.parse(source_elem)); + ASSERT_TRUE(ctl_info); + + // Turn the newly constructed info instance back into elements. + ElementPtr parsed_elem; + ASSERT_NO_THROW(parsed_elem = ctl_info->toElement()); + + // When the config is empty, ControlConfigInfo::toElement still + // generates a map with an empty db list. Replace source for + // element comparison below. + if (source_elem->size() == 0) { + ASSERT_NO_THROW (source_elem = Element::fromJSON( + "{ \"config-databases\": [] }")); + } + + // The parsed element should match the source element. + EXPECT_TRUE(parsed_elem->equals(*source_elem)) << "config: " << config; + } +} + +// Verify that invalid configurations fail to parse gracefully. +TEST(ConfigCtlInfoParser, invalidConfigs) { + // Note that configurations are must be valid JSON, but invalid logically. + std::string configs[] = { + "{ \"config-databases\": \"not_list\" }", + "{ \"config-databases\": [ \n" + " { \n" + " \"bogus\": \"param\" \n" + " } \n" + "] } \n" + }; + + for (auto config : configs) { + ConfigControlParser parser; + + // Turn the JSON config into Elements. + ElementPtr source_elem; + ASSERT_NO_THROW (source_elem = Element::fromJSON(config)) << + " JSON error, test is broken: " << config; + + // Parse the Elements into a ConfigControlInfo. + ASSERT_THROW(parser.parse(source_elem), isc::ConfigError) + << "config: " << config; + } +}