]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Enable conversion for composite attribute items
authorSalvatore Orlando <salv.orlando@gmail.com>
Fri, 2 Aug 2013 18:47:09 +0000 (11:47 -0700)
committerSalvatore Orlando <salv.orlando@gmail.com>
Fri, 9 Aug 2013 13:23:07 +0000 (06:23 -0700)
Bug 1207881

Enable 'dict validators' to convert composite attributes' items
using a 'convert_to' specification in a way similar to first-level
API attributes.
This is needed in order to ensure boolean sub-attributes are
properly handled.

Change-Id: I7f466befaa88112cf7e9b77d854ac292b2af638f

neutron/api/v2/attributes.py
neutron/extensions/l3_ext_gw_mode.py
neutron/tests/unit/test_attributes.py

index d7aea8c2aee3db35554cc95802ca7203dbf1b5bc..1b0e1a24989d50f90843fb2e5304728c20911b9b 100644 (file)
@@ -320,6 +320,29 @@ def _validate_uuid_list(data, valid_values=None):
         return msg
 
 
+def _validate_dict_item(key, key_validator, data):
+    # Find conversion function, if any, and apply it
+    conv_func = key_validator.get('convert_to')
+    if conv_func:
+        data[key] = conv_func(data.get(key))
+    # Find validator function
+    # TODO(salv-orlando): Structure of dict attributes should be improved
+    # to avoid iterating over items
+    val_func = val_params = None
+    for (k, v) in key_validator.iteritems():
+        if k.startswith('type:'):
+            # ask forgiveness, not permission
+            try:
+                val_func = validators[k]
+            except KeyError:
+                return _("Validator '%s' does not exist.") % k
+            val_params = v
+            break
+    # Process validation
+    if val_func:
+        return val_func(data.get(key), val_params)
+
+
 def _validate_dict(data, key_specs=None):
     if not isinstance(data, dict):
         msg = _("'%s' is not a dictionary") % data
@@ -339,25 +362,14 @@ def _validate_dict(data, key_specs=None):
             LOG.debug(msg)
             return msg
 
-    # Perform validation of all values according to the specifications.
+    # Perform validation and conversion of all values
+    # according to the specifications.
     for key, key_validator in [(k, v) for k, v in key_specs.iteritems()
                                if k in data]:
-
-        for val_name in [n for n in key_validator.iterkeys()
-                         if n.startswith('type:')]:
-            # Check whether specified validator exists.
-            if val_name not in validators:
-                msg = _("Validator '%s' does not exist.") % val_name
-                LOG.debug(msg)
-                return msg
-
-            val_func = validators[val_name]
-            val_params = key_validator[val_name]
-
-            msg = val_func(data.get(key), val_params)
-            if msg:
-                LOG.debug(msg)
-                return msg
+        msg = _validate_dict_item(key, key_validator, data)
+        if msg:
+            LOG.debug(msg)
+            return msg
 
 
 def _validate_dict_or_none(data, key_specs=None):
index 18e7acc98f6104ae5831495296757f91ddd653d1..073b8209d5814f9ca78240c1bd2316cd235e3801 100644 (file)
@@ -19,6 +19,7 @@
 #
 
 from neutron.api import extensions
+from neutron.api.v2 import attributes as attrs
 from neutron.common import exceptions as qexception
 from neutron.extensions import l3
 
@@ -37,7 +38,8 @@ EXTENDED_ATTRIBUTES_2_0 = {
                  'validate':
                  {'type:dict_or_nodata':
                   {'network_id': {'type:uuid': None, 'required': True},
-                   'enable_snat': {'type:boolean': None, 'required': False}}
+                   'enable_snat': {'type:boolean': None, 'required': False,
+                                   'convert_to': attrs.convert_to_boolean}}
                   }}}}
 
 
index 49b57e8198fbd6105d86b60a126169dca48986cc..a79a67e02cb6893e619959fd14316590922bac69 100644 (file)
@@ -537,6 +537,20 @@ class TestAttributes(base.BaseTestCase):
         msg = attributes._validate_dict(dictionary, constraints)
         self.assertIsNotNone(msg)
 
+    def test_validate_dict_convert_boolean(self):
+        dictionary, constraints = self._construct_dict_and_constraints()
+
+        constraints['key_bool'] = {
+            'type:boolean': None,
+            'required': False,
+            'convert_to': attributes.convert_to_boolean}
+        dictionary['key_bool'] = 'true'
+        msg = attributes._validate_dict(dictionary, constraints)
+        self.assertIsNone(msg)
+        # Explicitly comparing with literal 'True' as assertTrue
+        # succeeds also for 'true'
+        self.assertIs(True, dictionary['key_bool'])
+
     def test_subdictionary(self):
         dictionary, constraints = self._construct_dict_and_constraints()