From: Marcin Siodelski Date: Mon, 3 Jun 2019 11:22:47 +0000 (+0200) Subject: [#641,!352] Implemented db::Server class and data::ServerTag. X-Git-Tag: Kea-1.6.0-beta2~319 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e27a76ada35a0810abd7a29730cdce222ac4e3f;p=thirdparty%2Fkea.git [#641,!352] Implemented db::Server class and data::ServerTag. --- diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index 5fb6626606..9a747fc651 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -10,6 +10,7 @@ libkea_cc_la_SOURCES += element_value.h libkea_cc_la_SOURCES += cfg_to_element.h dhcp_config_error.h libkea_cc_la_SOURCES += command_interpreter.cc command_interpreter.h libkea_cc_la_SOURCES += json_feed.cc json_feed.h +libkea_cc_la_SOURCES += server_tag.cc server_tag.h libkea_cc_la_SOURCES += simple_parser.cc simple_parser.h libkea_cc_la_SOURCES += stamped_element.cc stamped_element.h libkea_cc_la_SOURCES += stamped_value.cc stamped_value.h @@ -31,6 +32,7 @@ libkea_cc_include_HEADERS = \ dhcp_config_error.h \ element_value.h \ json_feed.h \ + server_tag.h \ simple_parser.h \ stamped_element.h \ stamped_value.h \ diff --git a/src/lib/cc/server_tag.cc b/src/lib/cc/server_tag.cc new file mode 100644 index 0000000000..931d2561d4 --- /dev/null +++ b/src/lib/cc/server_tag.cc @@ -0,0 +1,36 @@ +// Copyright (C) 2019 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 + +namespace isc { +namespace data { + +std::string ServerTag::ALL = "all"; + +ServerTag::ServerTag() + : tag_(ALL) { +} + +ServerTag::ServerTag(const std::string& tag) + : tag_(util::str::trim(tag)) { + if (tag_.empty()) { + isc_throw(BadValue, "server-tag must not be empty"); + + } else if (tag_.length() > 256) { + isc_throw(BadValue, "server-tag must not be longer than 256 characters"); + } +} + +bool +ServerTag::amAll() const { + return (tag_ == ALL); +} + +} // end of namespace isc::data +} // end of namespace isc diff --git a/src/lib/cc/server_tag.h b/src/lib/cc/server_tag.h new file mode 100644 index 0000000000..95502ae898 --- /dev/null +++ b/src/lib/cc/server_tag.h @@ -0,0 +1,58 @@ +// Copyright (C) 2019 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 SERVER_TAG_H +#define SERVER_TAG_H + +#include + +namespace isc { +namespace data { + +/// @brief Represents a server tag. +/// +/// The server tag is a label identifying a server or all servers which +/// configuration is stored in the database. The label "all" is reserved +/// and it means "all servers". A configuration object in the database +/// associated with this server tag belongs to all servers. The server +/// tag must not be empty and must not be longer than 256 characters +/// (excluding leading and terminating whitespaces, which are trimmed). +class ServerTag { +public: + + /// @brief Server tag for all servers as text. + static std::string ALL; + + /// @brief Default constructor. + /// + /// Creates server tag for all servers. + ServerTag(); + + /// @brief Constructor. + /// + /// @param tag server tag provided as string. + explicit ServerTag(const std::string& tag); + + /// @brief Checks if the server tag is set to "all servers". + /// + /// @return true if the server tag is set to all servers, false + /// otherwise. + bool amAll() const; + /// @brief Returns server tag as string. + std::string get() const { + return (tag_); + } + +private: + + /// @brief Holds server tag as string. + std::string tag_; +}; + +} // end of namespace isc::data +} // end of namespace isc + +#endif // SERVER_TAG_H diff --git a/src/lib/cc/stamped_element.cc b/src/lib/cc/stamped_element.cc index 01bd7e172b..49a586f70e 100644 --- a/src/lib/cc/stamped_element.cc +++ b/src/lib/cc/stamped_element.cc @@ -23,6 +23,16 @@ StampedElement::updateModificationTime() { setModificationTime(boost::posix_time::second_clock::local_time()); } +std::string +StampedElement:: getServerTag() const { + return (server_tag_.get()); +} + +bool +StampedElement::allServers() const { + return (server_tag_.amAll()); +} + ElementPtr StampedElement::getMetadata() const { ElementPtr metadata = Element::createMap(); diff --git a/src/lib/cc/stamped_element.h b/src/lib/cc/stamped_element.h index ae67026cff..1f877b51ce 100644 --- a/src/lib/cc/stamped_element.h +++ b/src/lib/cc/stamped_element.h @@ -8,7 +8,9 @@ #define STAMPED_ELEMENT_H #include +#include #include +#include #include #include @@ -69,15 +71,22 @@ public: /// @brief Sets new server tag. /// - /// @param server_tag + /// @param server_tag new server tag. + /// @throw BadValue if the server tag length exceeds 256 characters. void setServerTag(const std::string& server_tag) { - server_tag_ = server_tag; + server_tag_ = ServerTag(server_tag); } /// @brief Returns server tag. - std::string getServerTag() const { - return (server_tag_); - } + /// + /// @return Server tag as string. + std::string getServerTag() const; + + /// @brief Checks if the stamped element is for all servers. + /// + /// @return true if the stamped element is associated with all servers, + /// false otherwise. + bool allServers() const; /// @brief Returns an object representing metadata to be returned /// with objects from the configuration backend. @@ -97,7 +106,7 @@ private: boost::posix_time::ptime timestamp_; /// @brief Holds server tag. - std::string server_tag_; + ServerTag server_tag_; }; } // end of namespace isc::data diff --git a/src/lib/cc/tests/Makefile.am b/src/lib/cc/tests/Makefile.am index 31a5d5e25d..b02a87b401 100644 --- a/src/lib/cc/tests/Makefile.am +++ b/src/lib/cc/tests/Makefile.am @@ -19,6 +19,7 @@ run_unittests_SOURCES += data_unittests.cc run_unittests_SOURCES += data_file_unittests.cc run_unittests_SOURCES += element_value_unittests.cc run_unittests_SOURCES += json_feed_unittests.cc +run_unittests_SOURCES += server_tag_unittest.cc run_unittests_SOURCES += simple_parser_unittest.cc run_unittests_SOURCES += stamped_element_unittest.cc run_unittests_SOURCES += stamped_value_unittest.cc diff --git a/src/lib/cc/tests/server_tag_unittest.cc b/src/lib/cc/tests/server_tag_unittest.cc new file mode 100644 index 0000000000..95cfd4f393 --- /dev/null +++ b/src/lib/cc/tests/server_tag_unittest.cc @@ -0,0 +1,85 @@ +// Copyright (C) 2019 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 + +using namespace isc; +using namespace isc::data; + +namespace { + +// This test verifies that the constructors of the ServerTag class +// work properly. +TEST(ServerTagTest, constructors) { + boost::scoped_ptr tag; + + { + SCOPED_TRACE("default constructor for all servers"); + ASSERT_NO_THROW(tag.reset(new ServerTag())); + EXPECT_EQ(ServerTag::ALL, tag->get()); + EXPECT_TRUE(tag->amAll()); + } + + { + SCOPED_TRACE("all servers"); + ASSERT_NO_THROW(tag.reset(new ServerTag(ServerTag::ALL))); + EXPECT_EQ(ServerTag::ALL, tag->get()); + EXPECT_TRUE(tag->amAll()); + } + + { + SCOPED_TRACE("no whitespace"); + ASSERT_NO_THROW(tag.reset(new ServerTag("xyz"))); + EXPECT_EQ("xyz", tag->get()); + EXPECT_FALSE(tag->amAll()); + } + + { + SCOPED_TRACE("leading whitespace"); + ASSERT_NO_THROW(tag.reset(new ServerTag(" left"))); + EXPECT_EQ("left", tag->get()); + EXPECT_FALSE(tag->amAll()); + } + + { + SCOPED_TRACE("terminating whitespace"); + ASSERT_NO_THROW(tag.reset(new ServerTag("right "))); + EXPECT_EQ("right", tag->get()); + EXPECT_FALSE(tag->amAll()); + } + + { + SCOPED_TRACE("leading and terminating whitespace"); + ASSERT_NO_THROW(tag.reset(new ServerTag(" both left-right "))); + EXPECT_EQ("both left-right", tag->get()); + EXPECT_FALSE(tag->amAll()); + } +} + +// This test verifies that malformed server tags are rejected. +TEST(ServerTagTest, malformed) { + { + SCOPED_TRACE("empty tag"); + EXPECT_THROW(ServerTag(""), BadValue); + } + + { + SCOPED_TRACE("only whitespaces"); + EXPECT_THROW(ServerTag(" "), BadValue); + } + + { + SCOPED_TRACE("too long tag, max is 256"); + EXPECT_THROW(ServerTag(std::string(257, 'c')), BadValue); + } +} + +} diff --git a/src/lib/cc/tests/stamped_element_unittest.cc b/src/lib/cc/tests/stamped_element_unittest.cc index c67fded804..22121c7366 100644 --- a/src/lib/cc/tests/stamped_element_unittest.cc +++ b/src/lib/cc/tests/stamped_element_unittest.cc @@ -23,8 +23,8 @@ TEST(StampedElementTest, create) { // Default identifier is 0. EXPECT_EQ(0, element.getId()); - // Default server tag is empty. - EXPECT_TRUE(element.getServerTag().empty()); + // Default server tag is 'all'. + EXPECT_EQ(ServerTag::ALL, element.getServerTag()); // Checking that the delta between now and the timestamp is within // 5s range should be sufficient. diff --git a/src/lib/database/Makefile.am b/src/lib/database/Makefile.am index e716c418ce..519c4e6482 100644 --- a/src/lib/database/Makefile.am +++ b/src/lib/database/Makefile.am @@ -18,6 +18,7 @@ libkea_database_la_SOURCES += dbaccess_parser.h dbaccess_parser.cc libkea_database_la_SOURCES += db_exceptions.h libkea_database_la_SOURCES += db_log.cc db_log.h libkea_database_la_SOURCES += db_messages.cc db_messages.h +libkea_database_la_SOURCES += server.cc server.h libkea_database_la_SOURCES += server_selector.h libkea_database_la_LIBADD = $(top_builddir)/src/lib/cc/libkea-cc.la @@ -73,4 +74,5 @@ libkea_database_include_HEADERS = \ db_exceptions.h \ db_log.h \ db_messages.h \ + server.h \ server_selector.h diff --git a/src/lib/database/server.cc b/src/lib/database/server.cc new file mode 100644 index 0000000000..2bdee22f5f --- /dev/null +++ b/src/lib/database/server.cc @@ -0,0 +1,34 @@ +// Copyright (C) 2019 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 + +using namespace isc::db; +using namespace isc::data; + +namespace isc { +namespace db { + +Server::Server(const ServerTag& tag, const std::string& description) + : StampedElement(), description_(description) { + + if (description_.length() > 65536) { + isc_throw(BadValue, "server description must not be longer than" + " 65536 characters"); + } + + setServerTag(tag.get()); +} + +ServerPtr +Server::create(const ServerTag& tag, const std::string& description) { + return (boost::make_shared(tag, description)); +} + +} // end of namespace isc::db +} // end of namespace isc diff --git a/src/lib/database/server.h b/src/lib/database/server.h new file mode 100644 index 0000000000..4162d1b499 --- /dev/null +++ b/src/lib/database/server.h @@ -0,0 +1,70 @@ +// Copyright (C) 2019 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 DB_SERVER_H +#define DB_SERVER_H + +#include +#include +#include + +namespace isc { +namespace db { + +class Server; + +/// @brief Shared pointer to the @c Server class. +typedef boost::shared_ptr ServerPtr; + +/// @brief Represents information about the Kea server in the database. +/// +/// The configuration backend holds the information about the servers +/// for which the backend holds the configuration information. The +/// information includes the server tag (unique name), server description +/// provided by the administrator and the metadata. +/// +/// This class extends the base class with the server description field. +class Server : public data::StampedElement { +private: + + /// @brief Private constructor. + /// + /// @param tag server tag. + /// @param server description. + Server(const data::ServerTag& tag, const std::string& description); + +public: + + /// @brief Factory function to be used to create an instance of the + /// @c Server object. + /// + /// @param tag server tag. + /// @param server description. + /// + /// @return Pointer to the server instance. + /// @throw BadValue if the server tag exceeds 256 characters or the + /// description exceeds 65536 characters. + static ServerPtr create(const data::ServerTag& tag, + const std::string& description = ""); + + /// @brief Returns the description of the server. + /// + /// @return Description of the server or an empty string if no + /// description was specified. + std::string getDescription() const { + return (description_); + } + +private: + + /// @brief Description of the server. + std::string description_; +}; + +} // end of namespace isc::db +} // end of namespace isc + +#endif // DB_SERVER_H diff --git a/src/lib/database/tests/Makefile.am b/src/lib/database/tests/Makefile.am index c05c29ce92..f8548924ef 100644 --- a/src/lib/database/tests/Makefile.am +++ b/src/lib/database/tests/Makefile.am @@ -24,6 +24,7 @@ libdatabase_unittests_SOURCES += backend_selector_unittest.cc libdatabase_unittests_SOURCES += database_connection_unittest.cc libdatabase_unittests_SOURCES += dbaccess_parser_unittest.cc libdatabase_unittests_SOURCES += run_unittests.cc +libdatabase_unittests_SOURCES += server_unittest.cc libdatabase_unittests_SOURCES += server_selector_unittest.cc libdatabase_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) diff --git a/src/lib/database/tests/server_unittest.cc b/src/lib/database/tests/server_unittest.cc new file mode 100644 index 0000000000..ac1e512579 --- /dev/null +++ b/src/lib/database/tests/server_unittest.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2019 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; +using namespace isc::db; + +namespace { + +TEST(ServerTest, constructor) { + ServerPtr server; + + ASSERT_NO_THROW( + server = Server::create(ServerTag("xyz"), "my first server") + ); + ASSERT_TRUE(server); + EXPECT_EQ("xyz", server->getServerTag()); + EXPECT_EQ("my first server", server->getDescription()); +} + +TEST(ServerTest, tooLongDescription) { + EXPECT_THROW(Server::create(ServerTag("xyz"), std::string(65537, 'c')), + BadValue); +} + +}