Commit 29a504c8 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5351] checkpoint: added comment

parent 1bab6cda
......@@ -107,6 +107,10 @@
// It is intended to keep anything you may want to put there - comments,
// extra designations, floor or department names etc. These structures
// will be made available to Kea hooks.
// You can define multiple user-contexts in the same scope without
// the last one replacing previous values. A comment entry is
// translated into a user-context with a "comment" property so
// you can include comments inside the configuration itself.
"subnet4": [
{
"pools": [ {
......@@ -117,6 +121,8 @@
"user-context": {
"comment": "Our first subnet!"
}
// Equivalent using smart parser
// "comment": "Our first subnet!"
},
{
// This particular subnet has match-client-id value changed.
......
......@@ -86,6 +86,10 @@
// structures. You can put anything you want in the user-context
// as long as it is a valid JSON and it starts with a map (i.e.
// is enclosed by curly brackets).
// You can define multiple user-contexts in the same scope without
// the last one replacing previous values. A comment entry is
// translated into a user-context with a "comment" property so
// you can include comments inside the configuration itself.
"subnet6": [
{
"pools": [
......@@ -102,6 +106,8 @@
// Here's the user-context for the whole subnet.
"user-context": { "comment": "Floor one, west wing" },
// Equivalent using smart parser
// "comment": "Floor one, west wing",
// This defines PD (prefix delegation) pools. In this case
// we have only one pool. That consists of /64 prefixes
......
......@@ -4683,6 +4683,9 @@ autogenerated IDs are not stable across configuration changes.</para>
It should be noted that Kea will not use that information, but will
simply store and make it available to hook libraries. It is up to the
hook library to extract that information and make use of it.
The parser translates "comment" entries into a user-context
with the entry, this allows to attach comments inside the
configuration itself.
</para>
<para>
For more background information, see <xref linkend="user-context"/>.
......
......@@ -4650,6 +4650,9 @@ autogenerated IDs are not stable across configuration changes.
it just stores it, making it available to the hook
libraries. It is up to each hook library to extract the information
and make use of it.
The parser translates "comment" entries into a user-context
with the entry, this allows to attach comments inside the
configuration itself.
</para>
<para>
For more background information, see <xref linkend="user-context"/>.
......
......@@ -2543,6 +2543,14 @@ both the command and the response.
arbitrary complexity. Kea does not use that data on its own, simply stores
and makes it available for the hook libraries.
</para>
<para>
Usually when an entry is defined multiple times in the same scope
the last value is used overwriting previous values (silently:
this behavior should be fixed soon). With user contexts values
are combined at the first level, for instance multiple user context
with a "comment" entry gives an entry with the list of accumulated
values.
</para>
<para>
Another use case for user contexts may be storing comments and other
information that will be retained by Kea. Regular comments are discarded
......@@ -2550,6 +2558,13 @@ both the command and the response.
useful if you want your comments to survive config-set, config-get
operations for example.
</para>
<para>
The parser translates "comment" entries at locations user context
are valid into a user context with a "comment" entry. The pretty
print of a configuration does the opposite operation and puts
"comment" entries at the beginning of maps as it seems to be the
common usage.
</para>
<para>
As of Kea 1.3, the structures that allow user contexts are pools of all
types (addresses and prefixes) and subnets. These are supported in both
......
......@@ -80,10 +80,20 @@ Pool::toElement() const {
// Prepare the map
ElementPtr map = Element::createMap();
// Set user-context
// Set user-context extracting comment
ConstElementPtr context = getContext();
if (!isNull(context)) {
map->set("user-context", context);
if ((context->getType() == Element::map) &&
context->contains("comment")) {
ElementPtr copied = isc::data::copy(context);
map->set("comment", copied->get("comment"));
copied->remove("comment");
if (copied->size() > 0) {
map->set("user-context", copied);
}
} else {
map->set("user-context", context);
}
}
// Set pool options
......
......@@ -566,9 +566,20 @@ Subnet::toElement() const {
map->set("subnet", Element::create(toText()));
// Add user-context, but only if defined. Omit if it was not.
// Extract comment so it will be printed first.
ConstElementPtr ctx = getContext();
if (ctx) {
map->set("user-context", ctx);
if ((ctx->getType() == Element::map) &&
ctx->contains("comment")) {
ElementPtr copied = isc::data::copy(ctx);
map->set("comment",copied->get("comment"));
copied->remove("comment");
if (copied->size() > 0) {
map->set("user-context", copied);
}
} else {
map->set("user-context", ctx);
}
}
return (map);
......@@ -638,7 +649,17 @@ Subnet6::toElement() const {
// Set user-context
ConstElementPtr context = (*pool)->getContext();
if (!isNull(context)) {
pool_map->set("user-context", context);
if ((context->getType() == Element::map) &&
context->contains("comment")) {
ElementPtr copied = isc::data::copy(context);
pool_map->set("comment", copied->get("comment"));
copied->remove("comment");
if (copied->size() > 0) {
pool_map->set("user-context", copied);
}
} else {
pool_map->set("user-context", context);
}
}
// Set pool options
ConstCfgOptionPtr opts = (*pool)->getCfgOption();
......@@ -692,7 +713,17 @@ Subnet6::toElement() const {
// Set user-context
ConstElementPtr context = pdpool->getContext();
if (!isNull(context)) {
pool_map->set("user-context", context);
if ((context->getType() == Element::map) &&
context->contains("comment")) {
ElementPtr copied = isc::data::copy(context);
pool_map->set("comment", copied->get("comment"));
copied->remove("comment");
if (copied->size() > 0) {
pool_map->set("user-context", copied);
}
} else {
pool_map->set("user-context", context);
}
}
// Set pool options
ConstCfgOptionPtr opts = pdpool->getCfgOption();
......
......@@ -740,6 +740,11 @@ TEST(CfgSubnets4Test, unparseSubnet) {
subnet2->setRelayInfo(IOAddress("10.0.0.1"));
subnet3->setIface("eth1");
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"comment\": \"foo\" }");
subnet1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::createMap();
subnet2->setContext(ctx2);
cfg.add(subnet1);
cfg.add(subnet2);
cfg.add(subnet3);
......@@ -747,6 +752,7 @@ TEST(CfgSubnets4Test, unparseSubnet) {
// Unparse
std::string expected = "[\n"
"{\n"
" \"comment\": \"foo\",\n"
" \"id\": 123,\n"
" \"subnet\": \"192.0.2.0/26\",\n"
" \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
......@@ -780,6 +786,7 @@ TEST(CfgSubnets4Test, unparseSubnet) {
" \"4o6-interface-id\": \"\",\n"
" \"4o6-subnet\": \"\",\n"
" \"reservation-mode\": \"all\",\n"
" \"user-context\": {},\n"
" \"option-data\": [ ],\n"
" \"pools\": [ ]\n"
"},{\n"
......@@ -813,6 +820,12 @@ TEST(CfgSubnets4Test, unparsePool) {
Pool4Ptr pool1(new Pool4(IOAddress("192.0.2.1"), IOAddress("192.0.2.10")));
Pool4Ptr pool2(new Pool4(IOAddress("192.0.2.64"), 26));
std::string json1 = "{ \"comment\": \"foo\", \"version\": 1 }";
data::ElementPtr ctx1 = data::Element::fromJSON(json1);
pool1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::fromJSON("{ \"foo\": \"bar\" }");
pool2->setContext(ctx2);
subnet->addPool(pool1);
subnet->addPool(pool2);
cfg.add(subnet);
......@@ -837,11 +850,14 @@ TEST(CfgSubnets4Test, unparsePool) {
" \"option-data\": [],\n"
" \"pools\": [\n"
" {\n"
" \"comment\": \"foo\",\n"
" \"option-data\": [ ],\n"
" \"pool\": \"192.0.2.1-192.0.2.10\"\n"
" \"pool\": \"192.0.2.1-192.0.2.10\",\n"
" \"user-context\": { \"version\": 1 }\n"
" },{\n"
" \"option-data\": [ ],\n"
" \"pool\": \"192.0.2.64/26\"\n"
" \"pool\": \"192.0.2.64/26\"\n,"
" \"user-context\": { \"foo\": \"bar\" }\n"
" }\n"
" ]\n"
"} ]\n";
......
......@@ -439,6 +439,11 @@ TEST(CfgSubnets6Test, unparseSubnet) {
subnet2->setRelayInfo(IOAddress("2001:db8:ff::2"));
subnet3->setIface("eth1");
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"comment\": \"foo\" }");
subnet1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::createMap();
subnet2->setContext(ctx2);
cfg.add(subnet1);
cfg.add(subnet2);
cfg.add(subnet3);
......@@ -446,6 +451,7 @@ TEST(CfgSubnets6Test, unparseSubnet) {
// Unparse
std::string expected = "[\n"
"{\n"
" \"comment\": \"foo\",\n"
" \"id\": 123,\n"
" \"subnet\": \"2001:db8:1::/48\",\n"
" \"relay\": { \"ip-address\": \"::\" },\n"
......@@ -471,6 +477,7 @@ TEST(CfgSubnets6Test, unparseSubnet) {
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
" \"reservation-mode\": \"all\",\n"
" \"user-context\": { },\n"
" \"pools\": [ ],\n"
" \"pd-pools\": [ ],\n"
" \"option-data\": [ ]\n"
......@@ -504,6 +511,12 @@ TEST(CfgSubnets6Test, unparsePool) {
IOAddress("2001:db8:1::199")));
Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
std::string json1 = "{ \"comment\": \"foo\", \"version\": 1 }";
data::ElementPtr ctx1 = data::Element::fromJSON(json1);
pool1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::fromJSON("{ \"foo\": \"bar\" }");
pool2->setContext(ctx2);
subnet->addPool(pool1);
subnet->addPool(pool2);
cfg.add(subnet);
......@@ -522,10 +535,13 @@ TEST(CfgSubnets6Test, unparsePool) {
" \"reservation-mode\": \"all\",\n"
" \"pools\": [\n"
" {\n"
" \"comment\": \"foo\",\n"
" \"pool\": \"2001:db8:1::100-2001:db8:1::199\",\n"
" \"user-context\": { \"version\": 1 },\n"
" \"option-data\": [ ]\n"
" },{\n"
" \"pool\": \"2001:db8:1:1::/64\",\n"
" \"user-context\": { \"foo\": \"bar\" },\n"
" \"option-data\": [ ]\n"
" }\n"
" ],\n"
......@@ -548,6 +564,9 @@ TEST(CfgSubnets6Test, unparsePdPool) {
Pool6Ptr pdpool2(new Pool6(IOAddress("2001:db8:3::"), 48, 56,
IOAddress("2001:db8:3::"), 64));
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"foo\": [ \"bar\" ] }");
pdpool1->setContext(ctx1);
subnet->addPool(pdpool1);
subnet->addPool(pdpool2);
cfg.add(subnet);
......@@ -570,6 +589,7 @@ TEST(CfgSubnets6Test, unparsePdPool) {
" \"prefix\": \"2001:db8:2::\",\n"
" \"prefix-len\": 48,\n"
" \"delegated-len\": 64,\n"
" \"user-context\": { \"foo\": [ \"bar\" ] },\n"
" \"option-data\": [ ]\n"
" },{\n"
" \"prefix\": \"2001:db8:3::\",\n"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment