BIND 10 master, updated. 03b60b9a5cf2a0085c0dd003593b884517b6aa7e Merge #2113

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Aug 2 08:44:47 UTC 2012


The branch, master has been updated
       via  03b60b9a5cf2a0085c0dd003593b884517b6aa7e (commit)
       via  b4dc5098233236ad352d9d01694b917e620ed9c0 (commit)
       via  940753065730e77c7fad72d005f62713f2cfb82c (commit)
       via  28d84a9af289a4fbbdef1eb7da8e3674dc0de9af (commit)
       via  e93f78639de53b00ae47c3232fedcbded6844d62 (commit)
       via  22af7691098b53daf64e90313bfd53d5e240d61c (commit)
       via  d3892b7807918a8b0e747958c8a29cc77e1f49bc (commit)
      from  4f9f077ffae95f15f162d8f640c4896fe56b7934 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 03b60b9a5cf2a0085c0dd003593b884517b6aa7e
Merge: 4f9f077 b4dc509
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Aug 2 10:19:53 2012 +0200

    Merge #2113

-----------------------------------------------------------------------

Summary of changes:
 src/bin/cfgmgr/plugins/datasrc_config_plugin.py |   60 +++++++++--
 src/bin/cfgmgr/plugins/tests/datasrc_test.py    |  127 ++++++++++++++++++++++-
 src/lib/python/isc/config/module_spec.py        |    2 +
 3 files changed, 179 insertions(+), 10 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/cfgmgr/plugins/datasrc_config_plugin.py b/src/bin/cfgmgr/plugins/datasrc_config_plugin.py
index f675aba..12710d5 100644
--- a/src/bin/cfgmgr/plugins/datasrc_config_plugin.py
+++ b/src/bin/cfgmgr/plugins/datasrc_config_plugin.py
@@ -16,20 +16,64 @@
 from isc.config.module_spec import module_spec_from_file
 from isc.util.file import path_search
 from bind10_config import PLUGIN_PATHS
+import isc.dns
+import isc.datasrc
+import json
+import os.path
+import copy
+
 spec = module_spec_from_file(path_search('datasrc.spec', PLUGIN_PATHS))
 
 def check(config):
     """
     Check the configuration.
     """
-    # TODO: Once we have solved ticket #2051, create the list and
-    # fill it with the configuration. We probably want to have some way
-    # to not load the data sources, just the configuration. It could
-    # be hacked together by subclassing ConfigurableClientList and
-    # having empty getDataSource method. But it looks like a hack and it
-    # won't really check the params configuration.
-    #
-    # For now, we let everything pass.
+    # Check the data layout first
+    errors=[]
+    if not spec.validate_config(False, config, errors):
+        return ' '.join(errors)
+
+    classes = config.get('classes')
+    # Nothing passed here
+    if classes is None:
+        return None
+
+    for rr_class_str in classes:
+        try:
+            rr_class = isc.dns.RRClass(rr_class_str)
+        except isc.dns.InvalidRRClass as irc:
+            return "The class '" + rr_class_str + "' is invalid"
+
+        dlist = isc.datasrc.ConfigurableClientList(rr_class)
+        # We get a copy here, as we are going to mangle the configuration.
+        # But we don't want our changes to propagate outside, to the real
+        # configuration.
+        client_config = copy.deepcopy(classes.get(rr_class_str))
+
+        for client in client_config:
+            if client['type'] == 'MasterFiles':
+                if not client.get('cache-enable', False):
+                    return 'The cache must be enabled in MasterFiles type'
+                params = client.get('params')
+                if type(params) != dict:
+                    return 'Params of MasterFiles must be a named set'
+                for name in params:
+                    try:
+                        isc.dns.Name(name)
+                    except Exception as e: # There are many related exceptions
+                        return str(e)
+                    if not os.path.exists(params[name]):
+                        return "Master file " + params[name] + " does not exist"
+                # We remove the list of zones locally. We already checked them,
+                # and the client list would have skipped them anyway, as we
+                # forbid cache. But it would produce a warning and we don't
+                # want that here.
+                client['params'] = {}
+
+        try:
+            dlist.configure(json.dumps(client_config), False)
+        except isc.datasrc.Error as dse:
+            return str(dse)
     return None
 
 def load():
diff --git a/src/bin/cfgmgr/plugins/tests/datasrc_test.py b/src/bin/cfgmgr/plugins/tests/datasrc_test.py
index f88ef87..f4381b4 100644
--- a/src/bin/cfgmgr/plugins/tests/datasrc_test.py
+++ b/src/bin/cfgmgr/plugins/tests/datasrc_test.py
@@ -16,12 +16,36 @@
 # Make sure we can load the module, put it into path
 import sys
 import os
+import unittest
+import json
 sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
+import isc.log
 
 import datasrc_config_plugin
-import unittest
 
 class DatasrcTest(unittest.TestCase):
+    def reject(self, config):
+        """
+        Just a shortcut to check the config is rejected.
+        """
+        old = json.dumps(config)
+        self.assertIsNotNone(datasrc_config_plugin.check({"classes":
+                                                         config}))
+        # There's some data mangling inside the plugin. Check it does
+        # not propagate out, as it could change the real configuration.
+        self.assertEqual(old, json.dumps(config))
+
+    def accept(self, config):
+        """
+        Just a shortcut to check the config is accepted.
+        """
+        old = json.dumps(config)
+        self.assertIsNone(datasrc_config_plugin.check({"classes":
+                                                      config}))
+        # There's some data mangling inside the plugin. Check it does
+        # not propagate out, as it could change the real configuration.
+        self.assertEqual(old, json.dumps(config))
+
     def test_load(self):
         """
         Checks the entry point returns the correct values.
@@ -32,5 +56,104 @@ class DatasrcTest(unittest.TestCase):
         # The plugin stores it's spec
         self.assertEqual(spec, datasrc_config_plugin.spec)
 
+    def test_empty(self):
+        """
+        Check an empty input is OK.
+        """
+        self.accept({})
+
+    def test_invalid_spec(self):
+        """
+        Check it rejects stuff that is not well-formed according
+        to the spec.
+        """
+        self.reject("test")
+        self.reject(13)
+        self.reject([])
+        self.reject({"IN": {}})
+        self.reject({"IN": [{"bad-name": True}]})
+
+    def test_class(self):
+        """
+        The class is rejected, if it is wrong.
+        """
+        self.reject({"BAD": []})
+        self.reject({"": []})
+        # But with a good one, it works
+        for c in ["IN", "CH", "HS"]:
+            self.accept({c: []})
+
+    def test_mem_ok(self):
+        """
+        Test we accept an in-memory data source. It doesn't really matter
+        which one it is. We just want to make sure we accept something
+        and this one does not need any kind of path mangling to find
+        plugins.
+        """
+        self.accept({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": True,
+            "params": {}
+        }]})
+
+    def test_dstype_bad(self):
+        """
+        The configuration is correct by the spec, but it would be rejected
+        by the client list. Check we reject it.
+        """
+        self.reject({"IN": [{
+            "type": "No such type"
+        }]})
+
+    def test_invalid_mem_params(self):
+        """
+        The client list skips in-memory sources. So we check it locally that
+        invalid things are rejected.
+        """
+        # The 'params' key is mandatory for MasterFiles
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": True
+        }]})
+        # The cache must be enabled
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": False,
+            "params": {}
+        }]})
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "params": {}
+        }]})
+        # Bad params type
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": True,
+            "params": []
+        }]})
+        # Bad name
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": True,
+            "params": {
+                "example....org.": '/file/does/not/exist'
+            }
+        }]})
+
+    def test_no_such_file_mem(self):
+        """
+        We also check the existance of master files. Not the actual content,
+        though.
+        """
+        self.reject({"IN": [{
+            "type": "MasterFiles",
+            "cache-enable": True,
+            "params": {
+                "example.org.": '/file/does/not/exist'
+            }
+        }]})
+
 if __name__ == '__main__':
-        unittest.main()
+    isc.log.init("bind10")
+    isc.log.resetUnitTestRootLogger()
+    unittest.main()
diff --git a/src/lib/python/isc/config/module_spec.py b/src/lib/python/isc/config/module_spec.py
index b79f928..e5568f6 100644
--- a/src/lib/python/isc/config/module_spec.py
+++ b/src/lib/python/isc/config/module_spec.py
@@ -386,6 +386,8 @@ def _validate_format(spec, value, errors):
     return True
 
 def _validate_item(spec, full, data, errors):
+    if spec.get('item_type') == 'any':
+        return True
     if not _validate_type(spec, data, errors):
         return False
     elif type(data) == list:



More information about the bind10-changes mailing list