Browse Source

bindctl config show improvements;
if the identified item is a map, show the entries
if it is a list, show the items with an index
(thinking about having a third one; if the list consists of map items, show the entries of those too, but we need list addressing (#405) to do that right)

also added a show_json command which simply prints the complete item and all its children in JSON format

temporarily added a few fake config_data items to Auth to play around with. we'll need to remove these before merge later


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac384@3443 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 14 years ago
parent
commit
359efa4b21

+ 57 - 0
src/bin/auth/auth.spec.pre.in

@@ -7,6 +7,63 @@
         "item_type": "string",
         "item_optional": true,
         "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
+      },
+      {
+        "item_name": "list",
+        "item_type": "list",
+        "item_optional": true,
+        "item_default": [],
+        "list_item_spec": {
+            "item_name": "value",
+            "item_type": "map",
+            "item_optional": false,
+            "item_default": {},
+            "map_item_spec":
+            [{
+              "item_name": "number",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 1
+            },
+            {
+              "item_name": "name",
+              "item_type": "string",
+              "item_optional": false,
+              "item_default": ""
+            }]
+        }
+    },
+    {
+      "item_name": "map",
+      "item_type": "map",
+      "item_optional": false,
+      "item_default": {},
+      "map_item_spec":
+        [{
+          "item_name": "number",
+          "item_type": "integer",
+          "item_optional": false,
+          "item_default": 1
+        },
+        {
+          "item_name": "name",
+          "item_type": "string",
+          "item_optional": false,
+          "item_default": ""
+        },
+        {
+          "item_name": "list",
+          "item_type": "list",
+          "item_optional": false,
+          "item_default": [],
+          "list_item_spec": {
+            "item_name": "value",
+            "item_type": "integer",
+            "item_optional": false,
+            "item_default": 1
+          }
+        }            
+        ]
       }
     ],
     "commands": [

+ 6 - 0
src/bin/bindctl/bindcmd.py

@@ -566,6 +566,12 @@ class BindCmdInterpreter(Cmd):
                     if value_map['modified']:
                         line += "(modified)"
                     print(line)
+            elif cmd.command == "show_json":
+                if identifier == "":
+                    print("Need at least the module to show the configuration in JSON format")
+                else:
+                    data, default = self.config_data.get_value(identifier)
+                    print(json.dumps(data))
             elif cmd.command == "add":
                 self.config_data.add_value(identifier, cmd.params['value'])
             elif cmd.command == "remove":

+ 5 - 0
src/bin/bindctl/bindctl-source.py.in

@@ -38,6 +38,11 @@ def prepare_config_commands(tool):
     cmd.add_param(param)
     module.add_command(cmd)
 
+    cmd = CommandInfo(name = "show_json", desc = "Show full configuration in JSON format")
+    param = ParamInfo(name = "identifier", type = "string", optional=True)
+    cmd.add_param(param)
+    module.add_command(cmd)
+
     cmd = CommandInfo(name = "add", desc = "Add entry to configuration list")
     param = ParamInfo(name = "identifier", type = "string", optional=True)
     cmd.add_param(param)

+ 2 - 2
src/lib/config/tests/testdata/spec22.spec

@@ -1,6 +1,6 @@
 {
   "module_spec": {
-    "module_name": "Spec2",
+    "module_name": "Spec22",
     "config_data": [
       { "item_name": "value1",
         "item_type": "integer",
@@ -81,7 +81,7 @@
       { "item_name": "value9",
         "item_type": "map",
         "item_optional": false,
-        "item_default": {},
+        "item_default": { "v91": "def", "v92": {} },
         "map_item_spec": [
           { "item_name": "v91",
             "item_type": "string",

+ 34 - 2
src/lib/python/isc/config/config_data.py

@@ -335,8 +335,16 @@ class MultiConfigData:
         module, sep, id = identifier.partition("/")
         try:
             spec = find_spec_part(self._specifications[module].get_config_spec(), id)
-            if 'item_default' in spec:
+            if type(spec) == dict and 'item_default' in spec:
                 return spec['item_default']
+            elif type(spec) == list:
+                result = {}
+                for i in spec:
+                    if type(i) == dict and 'item_default' in i:
+                        result[i['item_name']] = i['item_default']
+                    else:
+                        result[i['item_name']] = None
+                return result
             else:
                 return None
         except isc.cc.data.DataNotFoundError as dnfe:
@@ -405,19 +413,43 @@ class MultiConfigData:
                             entry['default'] = False
                         result.append(entry)
                 elif type(spec_part) == dict:
+                    # Two 'special cases' for easier viewing;
+                    # If the item is a map, show the first-level contents
+                    #
+                    # If the item is a list, show all elements (with index in the name).
+                    #
                     item = spec_part
                     if item['item_type'] == 'list':
                         li_spec = item['list_item_spec']
                         item_list, status =  self.get_value("/" + identifier)
                         if item_list != None:
+                            i = 0
                             for value in item_list:
                                 result_part2 = {}
-                                result_part2['name'] = li_spec['item_name']
+                                result_part2['name'] = item['item_name'] + '[' + str(i) + ']'
                                 result_part2['value'] = value
                                 result_part2['type'] = li_spec['item_type']
                                 result_part2['default'] = False
                                 result_part2['modified'] = False
                                 result.append(result_part2)
+                                i = i + 1
+                    elif item['item_type'] == 'map':
+                        map_name = item['item_name'] + "/"
+                        for map_item in item['map_item_spec']:
+                            entry = {}
+                            entry['name'] = map_name + map_item['item_name']
+                            entry['type'] = map_item['item_type']
+                            value, status = self.get_value("/" + identifier + "/" + map_item['item_name'])
+                            entry['value'] = value
+                            if status == self.LOCAL:
+                                entry['modified'] = True
+                            else:
+                                entry['modified'] = False
+                            if status == self.DEFAULT:
+                                entry['default'] = False
+                            else:
+                                entry['default'] = False
+                            result.append(entry)
                     else:
                         entry = {}
                         entry['name'] = item['item_name']

+ 20 - 2
src/lib/python/isc/config/tests/config_data_test.py

@@ -403,8 +403,8 @@ class TestMultiConfigData(unittest.TestCase):
                           {'default': False, 'type': 'list', 'name': 'item5', 'value': ['a', 'b'], 'modified': False},
                           {'default': False, 'type': 'map', 'name': 'item6', 'value': {}, 'modified': False}], maps)
         maps = self.mcd.get_value_maps("/Spec2/item5")
-        self.assertEqual([{'default': False, 'type': 'string', 'name': 'list_element', 'value': 'a', 'modified': False},
-                          {'default': False, 'type': 'string', 'name': 'list_element', 'value': 'b', 'modified': False}], maps)
+        self.assertEqual([{'default': False, 'type': 'string', 'name': 'item5[0]', 'value': 'a', 'modified': False},
+                          {'default': False, 'type': 'string', 'name': 'item5[1]', 'value': 'b', 'modified': False}], maps)
         maps = self.mcd.get_value_maps("/Spec2/item1")
         self.assertEqual([{'default': False, 'type': 'integer', 'name': 'item1', 'value': 2, 'modified': False}], maps)
         maps = self.mcd.get_value_maps("/Spec2/item2")
@@ -422,6 +422,24 @@ class TestMultiConfigData(unittest.TestCase):
         maps = self.mcd.get_value_maps("/Spec24/item")
         self.assertEqual([], maps)
 
+        module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec22.spec")
+        self.mcd.set_specification(module_spec)
+        expected = [{'default': False,
+                     'modified': False,
+                     'name': 'value9/v91',
+                     'type': 'string',
+                     'value': 'def'},
+                    {'default': False,
+                     'modified': False,
+                     'name': 'value9/v92',
+                     'type': 'map',
+                     'value': {}
+                    }
+                   ]
+
+        maps = self.mcd.get_value_maps("/Spec22/value9")
+        self.assertEqual(expected, maps)
+
 
 
     def test_set_value(self):