Browse Source

[trac926] error on set for nonexistent item

Jelte Jansen 13 years ago
parent
commit
834d488697

+ 9 - 3
src/bin/bindctl/bindcmd.py

@@ -628,7 +628,7 @@ class BindCmdInterpreter(Cmd):
             values = self.config_data.get_value_maps(identifier, show_all)
             values = self.config_data.get_value_maps(identifier, show_all)
             for value_map in values:
             for value_map in values:
                 line = value_map['name']
                 line = value_map['name']
-                if value_map['type'] in [ 'module', 'map', 'named_map' ]:
+                if value_map['type'] in [ 'module', 'map' ]:
                     line += "/"
                     line += "/"
                 elif value_map['type'] == 'list' \
                 elif value_map['type'] == 'list' \
                      and value_map['value'] != []:
                      and value_map['value'] != []:
@@ -636,8 +636,14 @@ class BindCmdInterpreter(Cmd):
                     # we have more data to show
                     # we have more data to show
                     line += "/"
                     line += "/"
                 else:
                 else:
-                    # if type is named_map, don't print value
-                    if value_map['type'] != 'named_map':
+                    # if type is named_map, don't print value if None
+                    # (it is either {} meaning empty, or None, meaning
+                    # there actually is data, but not to be shown with
+                    # the current command
+                    if value_map['type'] == 'named_map' and\
+                       value_map['value'] is None:
+                        line += "/\t"
+                    else:
                         line += "\t" + json.dumps(value_map['value'])
                         line += "\t" + json.dumps(value_map['value'])
                 line += "\t" + value_map['type']
                 line += "\t" + value_map['type']
                 line += "\t"
                 line += "\t"

+ 25 - 11
src/lib/python/isc/config/config_data.py

@@ -410,7 +410,6 @@ class MultiConfigData:
             id_parts = isc.cc.data.split_identifier(id)
             id_parts = isc.cc.data.split_identifier(id)
             id_prefix = ""
             id_prefix = ""
             while len(id_parts) > 0:
             while len(id_parts) > 0:
-                # [XX] TODO: Refactor
                 id_part = id_parts.pop(0)
                 id_part = id_parts.pop(0)
                 item_id, list_indices = isc.cc.data.split_identifier_list_indices(id_part)
                 item_id, list_indices = isc.cc.data.split_identifier_list_indices(id_part)
                 id_list = module + "/" + id_prefix + "/" + item_id
                 id_list = module + "/" + id_prefix + "/" + item_id
@@ -527,7 +526,7 @@ class MultiConfigData:
                 spec_part_list = spec_part['list_item_spec']
                 spec_part_list = spec_part['list_item_spec']
                 list_value, status = self.get_value(identifier)
                 list_value, status = self.get_value(identifier)
                 if list_value is None:
                 if list_value is None:
-                    raise isc.cc.data.DataNotFoundError(identifier)
+                    raise isc.cc.data.DataNotFoundError(identifier + " not found")
 
 
                 if type(list_value) != list:
                 if type(list_value) != list:
                     # the identifier specified a single element
                     # the identifier specified a single element
@@ -550,11 +549,10 @@ class MultiConfigData:
                 self._append_value_item(result, spec_part_map, identifier, all)
                 self._append_value_item(result, spec_part_map, identifier, all)
             elif item_type == "named_map":
             elif item_type == "named_map":
                 value, status = self.get_value(identifier)
                 value, status = self.get_value(identifier)
-                if status == self.NONE or (status == self.DEFAULT and value == {}):
-                    raise isc.cc.data.DataNotFoundError(identifier)
+
                 # show just the one entry, when either the map is empty,
                 # show just the one entry, when either the map is empty,
                 # or when this is element is not requested specifically
                 # or when this is element is not requested specifically
-                if (len(value.keys()) == 0 and (all or first)):
+                if len(value.keys()) == 0:
                     entry = _create_value_map_entry(identifier,
                     entry = _create_value_map_entry(identifier,
                                                     item_type,
                                                     item_type,
                                                     {}, status)
                                                     {}, status)
@@ -567,12 +565,14 @@ class MultiConfigData:
                 else:
                 else:
                     spec_part_named_map = spec_part['named_map_item_spec']
                     spec_part_named_map = spec_part['named_map_item_spec']
                     for entry in value:
                     for entry in value:
-                    #    xxxxxxxxxxx
-                        self._append_value_item(result, spec_part_named_map, identifier + "/" + entry, all)
+                        self._append_value_item(result,
+                                                spec_part_named_map,
+                                                identifier + "/" + entry,
+                                                all)
             else:
             else:
                 value, status = self.get_value(identifier)
                 value, status = self.get_value(identifier)
                 if status == self.NONE and not spec_part['item_optional']:
                 if status == self.NONE and not spec_part['item_optional']:
-                    raise isc.cc.data.DataNotFoundError(identifier)
+                    raise isc.cc.data.DataNotFoundError(identifier + " not found")
 
 
                 entry = _create_value_map_entry(identifier,
                 entry = _create_value_map_entry(identifier,
                                                 item_type,
                                                 item_type,
@@ -628,7 +628,7 @@ class MultiConfigData:
                     spec_part = spec_part['list_item_spec']
                     spec_part = spec_part['list_item_spec']
                 check_type(spec_part, value)
                 check_type(spec_part, value)
         else:
         else:
-            raise isc.cc.data.DataNotFoundError(identifier)
+            raise isc.cc.data.DataNotFoundError(identifier + " not found")
 
 
         # Since we do not support list diffs (yet?), we need to
         # Since we do not support list diffs (yet?), we need to
         # copy the currently set list of items to _local_changes
         # copy the currently set list of items to _local_changes
@@ -638,12 +638,26 @@ class MultiConfigData:
         cur_id_part = '/'
         cur_id_part = '/'
         for id_part in id_parts:
         for id_part in id_parts:
             id, list_indices = isc.cc.data.split_identifier_list_indices(id_part)
             id, list_indices = isc.cc.data.split_identifier_list_indices(id_part)
+            cur_value, status = self.get_value(cur_id_part + id)
+            # Check if the value was there in the first place
+            if status == MultiConfigData.NONE and cur_id_part != "/":
+                raise isc.cc.data.DataNotFoundError(id_part +
+                                                    " not found in " +
+                                                    cur_id_part)
             if list_indices is not None:
             if list_indices is not None:
-                cur_list, status = self.get_value(cur_id_part + id)
+                # And check if we don't set something outside of any
+                # list
+                cur_list = cur_value
+                for list_index in list_indices:
+                    if list_index >= len(cur_list):
+                        raise isc.cc.data.DataNotFoundError("No item " +
+                                  str(list_index) + " in " + id_part)
+                    else:
+                        cur_list = cur_list[list_index]
                 if status != MultiConfigData.LOCAL:
                 if status != MultiConfigData.LOCAL:
                     isc.cc.data.set(self._local_changes,
                     isc.cc.data.set(self._local_changes,
                                     cur_id_part + id,
                                     cur_id_part + id,
-                                    cur_list)
+                                    cur_value)
             cur_id_part = cur_id_part + id_part + "/"
             cur_id_part = cur_id_part + id_part + "/"
         isc.cc.data.set(self._local_changes, identifier, value)
         isc.cc.data.set(self._local_changes, identifier, value)
  
  

+ 5 - 4
src/lib/python/isc/config/tests/ccsession_test.py

@@ -750,16 +750,17 @@ class TestUIModuleCCSession(unittest.TestCase):
         uccs.add_value("/Spec32/named_map_item", "foo")
         uccs.add_value("/Spec32/named_map_item", "foo")
         value, status = uccs.get_value("/Spec32/named_map_item")
         value, status = uccs.get_value("/Spec32/named_map_item")
         self.assertEqual({'a': 1, 'b': 2, 'foo': 3}, value)
         self.assertEqual({'a': 1, 'b': 2, 'foo': 3}, value)
-        uccs.set_value("/Spec32/named_map_item/bar", 4)
-        value, status = uccs.get_value("/Spec32/named_map_item")
-        self.assertEqual({'a': 1, 'b': 2, 'foo': 3, 'bar': 4}, value)
 
 
         uccs.remove_value("/Spec32/named_map_item", "a")
         uccs.remove_value("/Spec32/named_map_item", "a")
         uccs.remove_value("/Spec32/named_map_item", "foo")
         uccs.remove_value("/Spec32/named_map_item", "foo")
         value, status = uccs.get_value("/Spec32/named_map_item")
         value, status = uccs.get_value("/Spec32/named_map_item")
-        self.assertEqual({'b': 2, 'bar': 4}, value)
+        self.assertEqual({'b': 2}, value)
 
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
         self.assertRaises(isc.cc.data.DataNotFoundError,
+                          uccs.set_value,
+                          "/Spec32/named_map_item/no_such_item",
+                          4)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
                           uccs.remove_value, "/Spec32/named_map_item",
                           uccs.remove_value, "/Spec32/named_map_item",
                           "no_such_item")
                           "no_such_item")