2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-02 15:05:16 +00:00

[master] Merge branch 'trac2184'

(conflicts purely in generated files, regenerated them)
Conflicts:
	doc/guide/bind10-guide.html
	doc/guide/bind10-guide.txt
	doc/guide/bind10-messages.html
This commit is contained in:
Jelte Jansen
2012-08-13 16:57:13 +02:00
8 changed files with 234 additions and 82 deletions

File diff suppressed because one or more lines are too long

View File

@@ -968,9 +968,18 @@ Chapter 8. Authoritative Server
> config set data_sources/classes/IN[1]/params { "example.org": "/path/to/example.org", "example.com": "/path/to/example.com" } > config set data_sources/classes/IN[1]/params { "example.org": "/path/to/example.org", "example.com": "/path/to/example.com" }
> config commit > config commit
Unfortunately, due to current technical limitations, the params must be Initially, a map value has to be set, but this value may be an empty map.
set as one JSON blob, it can't be edited in bindctl. To reload a zone, you After that, key/value pairs can be added with 'config add' and keys can be
the same command as above. removed with 'config remove'. The initial value may be an empty map, but
it has to be set before zones are added or removed.
> config set data_sources/classes/IN[1]/params {}
> config add data_sources/classes/IN[1]/params another.example.org /path/to/another.example.org
> config add data_sources/classes/IN[1]/params another.example.com /path/to/another.example.com
> config remove data_sources/classes/IN[1]/params another.example.org
bindctl. To reload a zone, you the same command as above.
Note Note

View File

@@ -1611,8 +1611,19 @@ can use various data source backends.
&gt; <userinput>config set data_sources/classes/IN[1]/params { "example.org": "/path/to/example.org", "example.com": "/path/to/example.com" }</userinput> &gt; <userinput>config set data_sources/classes/IN[1]/params { "example.org": "/path/to/example.org", "example.com": "/path/to/example.com" }</userinput>
&gt; <userinput>config commit</userinput></screen> &gt; <userinput>config commit</userinput></screen>
Unfortunately, due to current technical limitations, the params must Initially, a map value has to be set, but this value may be an
be set as one JSON blob, it can't be edited in empty map. After that, key/value pairs can be added with 'config
add' and keys can be removed with 'config remove'. The initial
value may be an empty map, but it has to be set before zones are
added or removed.
<screen>
&gt; <userinput>config set data_sources/classes/IN[1]/params {}</userinput>
&gt; <userinput>config add data_sources/classes/IN[1]/params another.example.org /path/to/another.example.org</userinput>
&gt; <userinput>config add data_sources/classes/IN[1]/params another.example.com /path/to/another.example.com</userinput>
&gt; <userinput>config remove data_sources/classes/IN[1]/params another.example.org</userinput>
</screen>
<command>bindctl</command>. To reload a zone, you the same command <command>bindctl</command>. To reload a zone, you the same command
as above. as above.
</para> </para>

View File

@@ -1,4 +1,4 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Messages Manual</title><link rel="stylesheet" type="text/css" href="./bind10-guide.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"><meta name="description" content="BIND 10 is a Domain Name System (DNS) suite managed by Internet Systems Consortium (ISC). It includes DNS libraries and modular components for controlling authoritative and recursive DNS servers. This is the messages manual for BIND 10 version 20120712. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Messages Manual"><div class="titlepage"><div><div><h1 class="title"><a name="idp25824"></a>BIND 10 Messages Manual</h1></div><div><p class="releaseinfo">This is the messages manual for BIND 10 version <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Messages Manual</title><link rel="stylesheet" href="./bind10-guide.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><meta name="description" content="BIND 10 is a Domain Name System (DNS) suite managed by Internet Systems Consortium (ISC). It includes DNS libraries and modular components for controlling authoritative and recursive DNS servers. This is the messages manual for BIND 10 version 20120712. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Messages Manual"><div class="titlepage"><div><div><h1 class="title"><a name="idp74800"></a>BIND 10 Messages Manual</h1></div><div><p class="releaseinfo">This is the messages manual for BIND 10 version
20120712.</p></div><div><p class="copyright">Copyright <20> 2011-2012 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by 20120712.</p></div><div><p class="copyright">Copyright <20> 2011-2012 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by
Internet Systems Consortium (ISC). It includes DNS libraries Internet Systems Consortium (ISC). It includes DNS libraries
and modular components for controlling authoritative and and modular components for controlling authoritative and

View File

@@ -6,6 +6,15 @@
"item_type": "any", "item_type": "any",
"item_optional": false, "item_optional": false,
"item_default": "asdf" "item_default": "asdf"
},
{ "item_name": "item2",
"item_type": "any",
"item_optional": true
},
{ "item_name": "item3",
"item_type": "any",
"item_optional": true,
"item_default": null
} }
] ]
} }

View File

@@ -521,7 +521,7 @@ class UIModuleCCSession(MultiConfigData):
if not cur_list: if not cur_list:
cur_list = [] cur_list = []
if value is None: if value is None and "list_item_spec" in module_spec:
if "item_default" in module_spec["list_item_spec"]: if "item_default" in module_spec["list_item_spec"]:
value = module_spec["list_item_spec"]["item_default"] value = module_spec["list_item_spec"]["item_default"]
@@ -572,8 +572,14 @@ class UIModuleCCSession(MultiConfigData):
if module_spec is None: if module_spec is None:
raise isc.cc.data.DataNotFoundError("Unknown item " + str(identifier)) raise isc.cc.data.DataNotFoundError("Unknown item " + str(identifier))
# for type any, we determine the 'type' by what value is set
# (which would be either list or dict)
cur_value, _ = self.get_value(identifier)
type_any = module_spec['item_type'] == 'any'
# the specified element must be a list or a named_set # the specified element must be a list or a named_set
if 'list_item_spec' in module_spec: if 'list_item_spec' in module_spec or\
(type_any and type(cur_value) == list):
value = None value = None
# in lists, we might get the value with spaces, making it # in lists, we might get the value with spaces, making it
# the third argument. In that case we interpret both as # the third argument. In that case we interpret both as
@@ -583,11 +589,12 @@ class UIModuleCCSession(MultiConfigData):
value_str += set_value_str value_str += set_value_str
value = isc.cc.data.parse_value_str(value_str) value = isc.cc.data.parse_value_str(value_str)
self._add_value_to_list(identifier, value, module_spec) self._add_value_to_list(identifier, value, module_spec)
elif 'named_set_item_spec' in module_spec: elif 'named_set_item_spec' in module_spec or\
(type_any and type(cur_value) == dict):
item_name = None item_name = None
item_value = None item_value = None
if value_str is not None: if value_str is not None:
item_name = isc.cc.data.parse_value_str(value_str) item_name = value_str
if set_value_str is not None: if set_value_str is not None:
item_value = isc.cc.data.parse_value_str(set_value_str) item_value = isc.cc.data.parse_value_str(set_value_str)
else: else:
@@ -643,12 +650,23 @@ class UIModuleCCSession(MultiConfigData):
if value_str is not None: if value_str is not None:
value = isc.cc.data.parse_value_str(value_str) value = isc.cc.data.parse_value_str(value_str)
if 'list_item_spec' in module_spec: # for type any, we determine the 'type' by what value is set
if value is not None: # (which would be either list or dict)
cur_value, _ = self.get_value(identifier)
type_any = module_spec['item_type'] == 'any'
# there's two forms of 'remove from list'; the remove-value-from-list
# form, and the 'remove-by-index' form. We can recognize the second
# case by value is None
if 'list_item_spec' in module_spec or\
(type_any and type(cur_value) == list) or\
value is None:
if not type_any and value is not None:
isc.config.config_data.check_type(module_spec['list_item_spec'], value) isc.config.config_data.check_type(module_spec['list_item_spec'], value)
self._remove_value_from_list(identifier, value) self._remove_value_from_list(identifier, value)
elif 'named_set_item_spec' in module_spec: elif 'named_set_item_spec' in module_spec or\
self._remove_value_from_named_set(identifier, value) (type_any and type(cur_value) == dict):
self._remove_value_from_named_set(identifier, value_str)
else: else:
raise isc.cc.data.DataNotFoundError(str(identifier) + " is not a list or a named_set") raise isc.cc.data.DataNotFoundError(str(identifier) + " is not a list or a named_set")

View File

@@ -204,6 +204,9 @@ def find_spec_part(element, identifier, strict_identifier = True):
# always want the 'full' spec of the item # always want the 'full' spec of the item
for id_part in id_parts[:-1]: for id_part in id_parts[:-1]:
cur_el = _find_spec_part_single(cur_el, id_part) cur_el = _find_spec_part_single(cur_el, id_part)
# As soon as we find 'any', return that
if cur_el["item_type"] == "any":
return cur_el
if strict_identifier and spec_part_is_list(cur_el) and\ if strict_identifier and spec_part_is_list(cur_el) and\
not isc.cc.data.identifier_has_list_index(id_part): not isc.cc.data.identifier_has_list_index(id_part):
raise isc.cc.data.DataNotFoundError(id_part + raise isc.cc.data.DataNotFoundError(id_part +
@@ -553,7 +556,6 @@ class MultiConfigData:
if 'item_default' in spec: if 'item_default' in spec:
# one special case, named_set # one special case, named_set
if spec['item_type'] == 'named_set': if spec['item_type'] == 'named_set':
print("is " + id_part + " in named set?")
return spec['item_default'] return spec['item_default']
else: else:
return spec['item_default'] return spec['item_default']
@@ -582,6 +584,14 @@ class MultiConfigData:
value = self.get_default_value(identifier) value = self.get_default_value(identifier)
if value is not None: if value is not None:
return value, self.DEFAULT return value, self.DEFAULT
else:
# get_default_value returns None for both
# the cases where there is no default, and where
# it is set to null, so we need to catch the latter
spec_part = self.find_spec_part(identifier)
if spec_part and 'item_default' in spec_part and\
spec_part['item_default'] is None:
return None, self.DEFAULT
return None, self.NONE return None, self.NONE
def _append_value_item(self, result, spec_part, identifier, all, first = False): def _append_value_item(self, result, spec_part, identifier, all, first = False):
@@ -742,6 +752,8 @@ class MultiConfigData:
# list # list
cur_list = cur_value cur_list = cur_value
for list_index in list_indices: for list_index in list_indices:
if type(cur_list) != list:
raise isc.cc.data.DataTypeError(id + " is not a list")
if list_index >= len(cur_list): if list_index >= len(cur_list):
raise isc.cc.data.DataNotFoundError("No item " + raise isc.cc.data.DataNotFoundError("No item " +
str(list_index) + " in " + id_part) str(list_index) + " in " + id_part)

View File

@@ -920,8 +920,8 @@ class TestUIModuleCCSession(unittest.TestCase):
def spec_file(self, file): def spec_file(self, file):
return self.data_path + os.sep + file return self.data_path + os.sep + file
def create_uccs2(self, fake_conn): def create_uccs(self, fake_conn, specfile="spec2.spec"):
module_spec = isc.config.module_spec_from_file(self.spec_file("spec2.spec")) module_spec = isc.config.module_spec_from_file(self.spec_file(specfile))
fake_conn.set_get_answer('/module_spec', { module_spec.get_module_name(): module_spec.get_full_spec()}) fake_conn.set_get_answer('/module_spec', { module_spec.get_module_name(): module_spec.get_full_spec()})
fake_conn.set_get_answer('/config_data', { 'version': BIND10_CONFIG_DATA_VERSION }) fake_conn.set_get_answer('/config_data', { 'version': BIND10_CONFIG_DATA_VERSION })
return UIModuleCCSession(fake_conn) return UIModuleCCSession(fake_conn)
@@ -989,7 +989,7 @@ class TestUIModuleCCSession(unittest.TestCase):
def test_add_remove_value(self): def test_add_remove_value(self):
fake_conn = fakeUIConn() fake_conn = fakeUIConn()
uccs = self.create_uccs2(fake_conn) uccs = self.create_uccs(fake_conn)
self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, 1, "a") self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, 1, "a")
self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, "no_such_item", "a") self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, "no_such_item", "a")
@@ -1020,6 +1020,88 @@ class TestUIModuleCCSession(unittest.TestCase):
self.assertRaises(isc.cc.data.DataTypeError, self.assertRaises(isc.cc.data.DataTypeError,
uccs.remove_value, "Spec2/item5", None) uccs.remove_value, "Spec2/item5", None)
# Check that the difference between no default and default = null
# is recognized
def test_default_null(self):
fake_conn = fakeUIConn()
uccs = self.create_uccs(fake_conn, "spec40.spec")
(value, status) = uccs.get_value("/Spec40/item2")
self.assertIsNone(value)
self.assertEqual(uccs.NONE, status)
(value, status) = uccs.get_value("/Spec40/item3")
self.assertIsNone(value)
self.assertEqual(uccs.DEFAULT, status)
# Test adding and removing values for type = any
def test_add_remove_value_any(self):
fake_conn = fakeUIConn()
uccs = self.create_uccs(fake_conn, "spec40.spec")
# Test item set of basic types
items = [ 1234, "foo", True, False ]
items_as_str = [ '1234', 'foo', 'true', 'false' ]
def test_fails():
self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, "Spec40/item1", "foo")
self.assertRaises(isc.cc.data.DataNotFoundError, uccs.add_value, "Spec40/item1", "foo", "bar")
self.assertRaises(isc.cc.data.DataNotFoundError, uccs.remove_value, "Spec40/item1", "foo")
self.assertRaises(isc.cc.data.DataTypeError, uccs.remove_value, "Spec40/item1[0]", None)
# A few helper functions to perform a number of tests
# (to repeat the same test for nested data)
def check_list(identifier):
for item in items_as_str:
uccs.add_value(identifier, item)
self.assertEqual((items, 1), uccs.get_value(identifier))
# Removing from list should work in both ways
uccs.remove_value(identifier, "foo")
uccs.remove_value(identifier + "[1]", None)
self.assertEqual(([1234, False], 1), uccs.get_value(identifier))
# As should item indexing
self.assertEqual((1234, 1), uccs.get_value(identifier + "[0]"))
self.assertEqual((False, 1), uccs.get_value(identifier + "[1]"))
def check_named_set(identifier):
for item in items_as_str:
# use string version as key as well
uccs.add_value(identifier, item, item)
self.assertEqual((1234, 1), uccs.get_value(identifier + "/1234"))
self.assertEqual((True, 1), uccs.get_value(identifier + "/true"))
for item in items_as_str:
# use string version as key as well
uccs.remove_value(identifier, item)
# should fail when set to value of primitive type
for item in items:
uccs.set_value("Spec40/item1", item)
test_fails()
# When set to list, add and remove should work, and its elements
# should be considered of type 'any' themselves.
uccs.set_value("Spec40/item1", [])
check_list("Spec40/item1")
# When set to dict, it should have the behaviour of a named set
uccs.set_value("Spec40/item1", {})
check_named_set("Spec40/item1")
# And, or course, we may need nesting.
uccs.set_value("Spec40/item1", { "foo": {}, "bar": [] })
check_named_set("Spec40/item1/foo")
check_list("Spec40/item1/bar")
uccs.set_value("Spec40/item1", [ {}, [] ] )
check_named_set("Spec40/item1[0]")
check_list("Spec40/item1[1]")
uccs.set_value("Spec40/item1", [[[[[[]]]]]] )
check_list("Spec40/item1[0][0][0][0][0]")
uccs.set_value("Spec40/item1", { 'a': { 'a': { 'a': {} } } } )
check_named_set("Spec40/item1/a/a/a")
def test_add_dup_value(self): def test_add_dup_value(self):
fake_conn = fakeUIConn() fake_conn = fakeUIConn()
uccs = self.create_uccs_listtest(fake_conn) uccs = self.create_uccs_listtest(fake_conn)
@@ -1101,7 +1183,7 @@ class TestUIModuleCCSession(unittest.TestCase):
def test_commit(self): def test_commit(self):
fake_conn = fakeUIConn() fake_conn = fakeUIConn()
uccs = self.create_uccs2(fake_conn) uccs = self.create_uccs(fake_conn)
uccs.commit() uccs.commit()
uccs._local_changes = {'Spec2': {'item5': [ 'a' ]}} uccs._local_changes = {'Spec2': {'item5': [ 'a' ]}}
uccs.commit() uccs.commit()