- Add ability to set list element that only has keys in Translator::setItem.
- Explicitly set list elements in case they contain only keys which can
be more common now that data is a key since it is likely one can have
entries that only have code, space, and data.
- Handle no data as empty data when setting, and empty data as no data
when getting. This avoids the need to add an empty "data" element to
all options that lack it in all-options.json so that the unit tests
pass. But this goes to show that data-less entries may be encountered
in production as well, so more importantly this caters to that
scenario.
- Adjust data in kea4/all-options.json to not contain singlequotes.
There was only one occurrence of it. This is a limitation related
to unit testing only. Opened issue 3216 about it.
- Add missing tests that are not strictly related to the data key, but
they are related to option data:
- TranslatorOptionDataListTestv6.getEmpty
- TranslatorOptionDataListTestv4.get
- TranslatorOptionDataListTestv6.setEmpty
- TranslatorOptionDataListTestv4.set
- Add unit tests:
- TranslatorOptionDataListTestv4.optionsSameCodeAndSpace
- TranslatorOptionDataListTestv6.optionsSameCodeAndSpace
- Add snippet that tests setting of list element with keys only in
TranslatorTest.setItem.
// Type: string
{
"code": 56,
- "data": "Error: here's a DHCPNAK!",
+ "data": "Error: here is a DHCPNAK!",
"name": "dhcp-message"
},
#include <yang/translator_option_data.h>
#include <yang/yang_models.h>
+#include <sysrepo-cpp/utils/exception.hpp>
+
using namespace std;
using namespace isc;
using namespace isc::data;
}; // TranslatorOptionDataListTestv6
// This test verifies that an empty option data list can be properly
-// translated from YANG to JSON.
+// translated from YANG to JSON for v4.
TEST_F(TranslatorOptionDataListTestv4, getEmpty) {
// Get the option data list and check if it is empty.
const string& xpath = "/kea-dhcp4-server:config";
ASSERT_FALSE(options);
}
+// This test verifies that an empty option data list can be properly
+// translated from YANG to JSON for v6.
+TEST_F(TranslatorOptionDataListTestv6, getEmpty) {
+ // Get the option data list and check if it is empty.
+ const string& xpath = "/kea-dhcp6-server:config";
+ ConstElementPtr options;
+ EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_FALSE(options);
+}
+
+// This test verifies that one option data can be properly translated
+// from YANG to JSON for v4.
+TEST_F(TranslatorOptionDataListTestv4, get) {
+ // Create the option code 100.
+ const string& xpath = "/kea-dhcp4-server:config";
+ const string& xoption = xpath + "/option-data[code='100'][space='dns'][data='12121212']";
+ const string& xformat = xoption + "/csv-format";
+ const string& xalways = xoption + "/always-send";
+ const string& xnever = xoption + "/never-send";
+ string const s_false("false");
+ ASSERT_NO_THROW_LOG(sess_->setItem(xformat, s_false));
+ ASSERT_NO_THROW_LOG(sess_->setItem(xalways, s_false));
+ ASSERT_NO_THROW_LOG(sess_->setItem(xnever, s_false));
+ sess_->applyChanges();
+
+ // Get the option data.
+ ConstElementPtr option;
+ EXPECT_NO_THROW_LOG(option = translator_->getOptionDataFromAbsoluteXpath(xoption));
+ ASSERT_TRUE(option);
+ EXPECT_EQ("{"
+ " \"always-send\": false,"
+ " \"code\": 100,"
+ " \"csv-format\": false,"
+ " \"data\": \"12121212\","
+ " \"never-send\": false,"
+ " \"space\": \"dns\""
+ " }",
+ option->str());
+
+ // Get the option data list.
+ ConstElementPtr options;
+ EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(options);
+ ASSERT_EQ(Element::list, options->getType());
+ EXPECT_EQ(1, options->size());
+ EXPECT_TRUE(option->equals(*options->get(0)));
+}
+
// This test verifies that one option data can be properly translated
-// from YANG to JSON.
+// from YANG to JSON for v6.
TEST_F(TranslatorOptionDataListTestv6, get) {
// Create the option code 100.
const string& xpath = "/kea-dhcp6-server:config";
- const string& xoption = xpath + "/option-data[code='100'][space='dns']";
+ const string& xoption = xpath + "/option-data[code='100'][space='dns'][data='12121212']";
const string& xformat = xoption + "/csv-format";
- const string& xdata = xoption + "/data";
const string& xalways = xoption + "/always-send";
const string& xnever = xoption + "/never-send";
string const s_false("false");
ASSERT_NO_THROW_LOG(sess_->setItem(xformat, s_false));
- string const s_data("12121212");
- ASSERT_NO_THROW_LOG(sess_->setItem(xdata, s_data));
ASSERT_NO_THROW_LOG(sess_->setItem(xalways, s_false));
ASSERT_NO_THROW_LOG(sess_->setItem(xnever, s_false));
sess_->applyChanges();
}
// This test verifies that an empty option data list can be properly
-// translated from JSON to YANG.
+// translated from JSON to YANG for v4.
TEST_F(TranslatorOptionDataListTestv4, setEmpty) {
// Set empty list.
const string& xpath = "/kea-dhcp4-server:config";
ASSERT_FALSE(options);
}
+// This test verifies that an empty option data list can be properly
+// translated from JSON to YANG for v6.
+TEST_F(TranslatorOptionDataListTestv6, setEmpty) {
+ // Set empty list.
+ const string& xpath = "/kea-dhcp6-server:config";
+ ConstElementPtr options = Element::createList();
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ options.reset();
+ EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_FALSE(options);
+}
+
// This test verifies that one option data can be properly translated
-// from JSON to YANG.
+// from JSON to YANG for v4.
+TEST_F(TranslatorOptionDataListTestv4, set) {
+ // Negative tests.
+ string const xpath("/kea-dhcp4-server:config");
+ string const xoption(xpath + "/option-data[code='100'][space='dns'][data='12121212']");
+ string const s_code("15");
+ string const s_space("dhcp4");
+ string const s_data("12121212");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/code", s_code), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/code' to "
+ "'15': SR_ERR_INVAL_ARG");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/space", s_space), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/space' to "
+ "'dhcp4': SR_ERR_INVAL_ARG");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/data", s_data), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/data' to "
+ "'12121212': SR_ERR_INVAL_ARG");
+
+ // Setting the list element directly should work.
+ EXPECT_NO_THROW_LOG(sess_->setItem(xoption, std::nullopt));
+
+ // Set one option data.
+ ElementPtr options = Element::createList();
+ ElementPtr option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("csv-format", Element::create(false));
+ option->set("data", Element::create("12121212"));
+ option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
+ options->add(option);
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ ConstElementPtr got;
+ EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(got);
+ ASSERT_EQ(1, got->size());
+ EXPECT_TRUE(option->equals(*got->get(0)));
+}
+
+// This test verifies that one option data can be properly translated
+// from JSON to YANG for v6.
TEST_F(TranslatorOptionDataListTestv6, set) {
+ // Negative tests.
+ string const xpath("/kea-dhcp6-server:config");
+ string const xoption(xpath + "/option-data[code='100'][space='dns'][data='12121212']");
+ string const s_code("15");
+ string const s_space("dhcp6");
+ string const s_data("12121212");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/code", s_code), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/code' to "
+ "'15': SR_ERR_INVAL_ARG");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/space", s_space), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/space' to "
+ "'dhcp6': SR_ERR_INVAL_ARG");
+ EXPECT_THROW_MSG(sess_->setItem(xoption + "/data", s_data), sysrepo::Error,
+ "Session::setItem: Couldn't set "
+ "'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/data' to "
+ "'12121212': SR_ERR_INVAL_ARG");
+
+ // Setting the list element directly should work.
+ EXPECT_NO_THROW_LOG(sess_->setItem(xoption, std::nullopt));
+
// Set one option data.
- const string& xpath = "/kea-dhcp6-server:config";
ElementPtr options = Element::createList();
ElementPtr option = Element::createMap();
option->set("code", Element::create(100));
EXPECT_TRUE(option->equals(*got->get(0)));
}
+// This test verifies that multiple options of smae code and space but different data can be
+// configured for v4.
+TEST_F(TranslatorOptionDataListTestv4, optionsSameCodeAndSpace) {
+ string const xpath("/kea-dhcp4-server:config");
+
+ // Set one option data.
+ ElementPtr options = Element::createList();
+ ElementPtr option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("csv-format", Element::create(false));
+ option->set("data", Element::create("12121212"));
+ option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
+ options->add(option);
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("csv-format", Element::create(false));
+ option->set("data", Element::create("34343434"));
+ option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
+ options->add(option);
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ ConstElementPtr got;
+ EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(got);
+ EXPECT_EQ(2, got->size());
+ EXPECT_TRUE(options->equals(*got));
+
+ // Now with keys only.
+ options = Element::createList();
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("data", Element::create("56565656"));
+ options->add(option);
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("data", Element::create("78787878"));
+ options->add(option);
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(got);
+ EXPECT_EQ(4, got->size());
+ EXPECT_TRUE(options->get(0)->equals(*got->get(2)));
+ EXPECT_TRUE(options->get(1)->equals(*got->get(3)));
+}
+
+// This test verifies that multiple options of smae code and space but different data can be
+// configured for v6.
+TEST_F(TranslatorOptionDataListTestv6, optionsSameCodeAndSpace) {
+ string const xpath("/kea-dhcp6-server:config");
+
+ // Set one option data.
+ ElementPtr options = Element::createList();
+ ElementPtr option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("csv-format", Element::create(false));
+ option->set("data", Element::create("12121212"));
+ option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
+ options->add(option);
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("csv-format", Element::create(false));
+ option->set("data", Element::create("34343434"));
+ option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
+ options->add(option);
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ ConstElementPtr got;
+ EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(got);
+ EXPECT_EQ(2, got->size());
+ EXPECT_TRUE(options->equals(*got));
+
+ // Now with keys only.
+ options = Element::createList();
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("data", Element::create("56565656"));
+ options->add(option);
+ option = Element::createMap();
+ option->set("code", Element::create(100));
+ option->set("space", Element::create("dns"));
+ option->set("data", Element::create("78787878"));
+ options->add(option);
+ EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
+
+ // Get it back.
+ EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
+ ASSERT_TRUE(got);
+ EXPECT_EQ(4, got->size());
+ EXPECT_TRUE(options->get(0)->equals(*got->get(2)));
+ EXPECT_TRUE(options->get(1)->equals(*got->get(3)));
+}
+
} // namespace
ElementPtr element;
string xpath;
+ optional<DataNode> data_node;
+
+ // List.
+ xpath = "/keatest-module:list[key='value']";
+ element = Element::create("value");
+ EXPECT_NO_THROW_LOG(translator->setItem(xpath, ElementPtr(), LeafBaseType::Unknown));
+ EXPECT_NO_THROW_LOG(translator->setItem(xpath, ElementPtr(), LeafBaseType::Unknown));
+ EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath + "/key"));
+ ASSERT_TRUE(data_node);
+ EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath + "/key"));
+ ASSERT_TRUE(data_node);
+ ASSERT_EQ(LeafBaseType::String, data_node->schema().asLeaf().valueType().base());
+ EXPECT_EQ(element->stringValue(), string(data_node->asTerm().valueStr()));
// String.
- optional<DataNode> data_node;
xpath = "/keatest-module:main/string";
element = Element::create("str");
EXPECT_NO_THROW_LOG(translator->setItem(xpath, element, LeafBaseType::String));
{ "/kea-dhcp4-server:config/subnet4[id='111']/id",
"111", libyang::LeafBaseType::Uint32, false },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']",
+ "option-data[code='100'][space='dns'][data='12121212']",
std::nullopt, libyang::LeafBaseType::Unknown, false },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/code",
+ "option-data[code='100'][space='dns'][data='12121212']/code",
"100", libyang::LeafBaseType::Uint8, false },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/space",
+ "option-data[code='100'][space='dns'][data='12121212']/space",
"dns", libyang::LeafBaseType::String, false },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/data",
- "12121212", libyang::LeafBaseType::String, true },
+ "option-data[code='100'][space='dns'][data='12121212']/data",
+ "12121212", libyang::LeafBaseType::String, false },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/csv-format",
+ "option-data[code='100'][space='dns'][data='12121212']/csv-format",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/always-send",
+ "option-data[code='100'][space='dns'][data='12121212']/always-send",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
- "option-data[code='100'][space='dns']/never-send",
+ "option-data[code='100'][space='dns'][data='12121212']/never-send",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']",
"2001:db8::1:0/112", libyang::LeafBaseType::String, true },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']",
+ "option-data[code='100'][space='dns'][data='12121212']",
std::nullopt, libyang::LeafBaseType::Unknown, false },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/code",
+ "option-data[code='100'][space='dns'][data='12121212']/code",
"100", libyang::LeafBaseType::Uint16, false },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/space",
+ "option-data[code='100'][space='dns'][data='12121212']/space",
"dns", libyang::LeafBaseType::String, false },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/data",
- "12121212", libyang::LeafBaseType::String, true },
+ "option-data[code='100'][space='dns'][data='12121212']/data",
+ "12121212", libyang::LeafBaseType::String, false },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/csv-format",
+ "option-data[code='100'][space='dns'][data='12121212']/csv-format",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/always-send",
+ "option-data[code='100'][space='dns'][data='12121212']/always-send",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp6-server:config/subnet6[id='111']/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
- "option-data[code='100'][space='dns']/never-send",
+ "option-data[code='100'][space='dns'][data='12121212']/never-send",
"false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp6-server:config/subnet6[id='111']/subnet",
"2001:db8::/48", libyang::LeafBaseType::String, true },
}
void
-Translator::setItem(const string& xpath, ConstElementPtr elem, LeafBaseType type) {
+Translator::setItem(const string& xpath,
+ ConstElementPtr const elem,
+ LeafBaseType const type) {
optional<string> const value(translateToYang(elem, type));
try {
session_.setItem(xpath, value);
for (LeafBaseType const& i :
{LeafBaseType::Bits, LeafBaseType::Empty, LeafBaseType::Enum, LeafBaseType::IdentityRef,
LeafBaseType::InstanceIdentifier, LeafBaseType::Leafref, LeafBaseType::String,
- LeafBaseType::Union, LeafBaseType::Unknown}) {
+ LeafBaseType::Union}) {
result.emplace(i, [](string const& value) -> ElementPtr const {
return Element::create(value);
});
#include <yang/netconf_error.h>
#include <sysrepo-cpp/Connection.hpp>
+#include <sysrepo-cpp/Enum.hpp>
#include <sysrepo-cpp/Session.hpp>
#include <unordered_map>
/// @param elem The JSON element.
/// @param type The sysrepo type.
void setItem(const std::string& xpath,
- isc::data::ConstElementPtr elem,
- libyang::LeafBaseType type);
+ isc::data::ConstElementPtr const elem,
+ libyang::LeafBaseType const type);
/// @brief Get an element from given ElementPtr node and set it in sysrepo
/// at given xpath.
void
TranslatorHost::setHostKea(string const& xpath, ConstElementPtr elem) {
- // Skip keys "identifier" and "identifier-type".
+ // Set the list element. This is important in case we have no other elements except the keys.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip keys "identifier" and "identifier-type" since they were set with the
+ // list element in the call above with the LeafBaseType::Unknown parameter.
checkAndSetLeaf(elem, xpath, "hostname", LeafBaseType::String);
void
TranslatorLogger::setLoggerKea(string const& xpath, ConstElementPtr elem) {
- // Skip key "name".
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip key "name" since it was set with the list element in the call above
+ // with the LeafBaseType::Unknown parameter.
checkAndSetLeaf(elem, xpath, "debuglevel", LeafBaseType::Uint8);
checkAndSetLeaf(elem, xpath, "severity", LeafBaseType::Enum);
TranslatorOptionData::getOptionDataKea(DataNode const& data_node) {
ElementPtr result = Element::createMap();
+ // Code and space must exist.
getMandatoryLeaf(result, data_node, "code");
getMandatoryLeaf(result, data_node, "space");
+ // Data must exist according to the YANG module too, but empty data is considered no data.
+ ElementPtr const& x(getItem(data_node, "data"));
+ if (x && !x->stringValue().empty()) {
+ result->set("data", x);
+ }
+
checkAndGetLeaf(result, data_node, "always-send");
checkAndGetLeaf(result, data_node, "csv-format");
- checkAndGetLeaf(result, data_node, "data");
checkAndGetLeaf(result, data_node, "name");
checkAndGetLeaf(result, data_node, "never-send");
void
TranslatorOptionData::setOptionDataKea(string const& xpath,
ConstElementPtr elem) {
- // Skip keys "code" and "space".
+ // Set the list element. This is important in case we have no other elements except the keys.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip keys "code", "space", and "data" since they were set with the
+ // list element in the call above with the LeafBaseType::Unknown parameter.
checkAndSetLeaf(elem, xpath, "always-send", LeafBaseType::Bool);
checkAndSetLeaf(elem, xpath, "csv-format", LeafBaseType::Bool);
- checkAndSetLeaf(elem, xpath, "data", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "name", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "never-send", LeafBaseType::Bool);
ConstElementPtr elem) {
for (size_t i = 0; i < elem->size(); ++i) {
ElementPtr option = elem->getNonConst(i);
+
+ // Code and space must exist in the input.
if (!option->contains("code")) {
isc_throw(BadValue, "option data without code: " << option->str());
}
unsigned code = static_cast<unsigned>(option->get("code")->intValue());
if (!option->contains("space")) {
- isc_throw(BadValue, "option data without space: " <<option->str());
+ isc_throw(BadValue, "option data without space: " << option->str());
}
string space = option->get("space")->stringValue();
+
+ // Data must exist according to the YANG module too, but no data in the input is allowed and
+ // converted to an empty string.
+ string data;
+ if (option->contains("data")) {
+ data = option->get("data")->stringValue();
+ }
+
ostringstream keys;
- keys << xpath << "/option-data[code='" << code
- << "'][space='" << space << "']";
+ keys << xpath << "/option-data[code='" << code <<
+ "'][space='" << space <<
+ "'][data='" << data << "']";
setOptionData(keys.str(), option);
}
}
/// @code
/// /kea-dhcp6-server:config (container)
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns'] (list instance)
+/// option-data[code='100'][space='dns'][data='12121212'] (list instance)
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/code = 100
+/// option-data[code='100'][space='dns'][data='12121212']/code = 100
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/space = dns
+/// option-data[code='100'][space='dns'][data='12121212']/space = dns
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/data = 12121212
+/// option-data[code='100'][space='dns'][data='12121212']/csv-format = false
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/csv-format = false
+/// option-data[code='100'][space='dns'][data='12121212']/always-send = false
/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/always-send = false
-/// /kea-dhcp6-server:config/
-/// option-data[code='100'][space='dns']/never-send = false
+/// option-data[code='100'][space='dns'][data='12121212']/never-send = false
/// @endcode
/// @brief A translator class for converting an option data between
void
TranslatorOptionDef::setOptionDefKea(string const& xpath,
ConstElementPtr elem) {
- // Skip keys "code" and "space".
+ // Set the list element. This is important in case we have no other elements except the keys.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip keys "code" and "space" since they were set with the
+ // list element in the call above with the LeafBaseType::Unknown parameter.
setMandatoryLeaf(elem, xpath, "name", LeafBaseType::String);
setMandatoryLeaf(elem, xpath, "type", LeafBaseType::String);
void
TranslatorPool::setPoolKea(string const& xpath, ConstElementPtr elem) {
- // Skip keys "start-address" and "end-address".
+ // Set the list element. This is important in case we have no other elements except the keys.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip keys "start-address" and "end-address" since they were set with the
+ // list element in the call above with the LeafBaseType::Unknown parameter.
ConstElementPtr pool = elem->get("pool");
if (!pool) {
TranslatorSharedNetwork::setSharedNetworkKea(string const& xpath,
ConstElementPtr elem,
string const& subsel) {
- // Skip key "name".
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip key "name" since it was set with the list element in the call above
+ // with the LeafBaseType::Unknown parameter.
checkAndSetLeaf(elem, xpath, "allocator", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "cache-max-age", LeafBaseType::Uint32);
void
TranslatorSubnet::setSubnetIetf6(string const& xpath, ConstElementPtr elem) {
- /// Skip key "id".
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip key "id" since it was set with the list element in the call above
+ // with the LeafBaseType::Unknown parameter.
setMandatoryDivergingLeaf(elem, xpath, "subnet", "network-prefix", LeafBaseType::String);
void
TranslatorSubnet::setSubnetKea(string const& xpath, ConstElementPtr elem) {
- /// Skip key "id".
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+
+ // Skip key "id" since it was set with the list element in the call above
+ // with the LeafBaseType::Unknown parameter.
ConstElementPtr subnet = elem->get("subnet");
if (!subnet) {