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
/// This is class conveys the configuration control information
/// described by the following JSON text:
///
-/// "ConfigCtl" :
+/// "config-ctl" :
/// {
/// "config-databases":
/// [
--- /dev/null
+// 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 <config.h>
+
+#include <cc/dhcp_config_error.h>
+#include <config/config_ctl_parser.h>
+#include <database/dbaccess_parser.h>
+#include <string>
+
+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<data::ElementPtr>& 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
+
--- /dev/null
+// 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 <cc/data.h>
+#include <cc/simple_parser.h>
+#include <config/config_ctl_info.h>
+
+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
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)
--- /dev/null
+// 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 <config.h>
+#include <cc/dhcp_config_error.h>
+#include <config/config_ctl_parser.h>
+#include <exceptions/exceptions.h>
+
+#include <gtest/gtest.h>
+
+#include <sstream>
+#include <iostream>
+
+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;
+ }
+}