Merge "Enable conversion for composite attribute items"

This commit is contained in:
Jenkins 2013-08-14 06:32:56 +00:00 committed by Gerrit Code Review
commit 591ce97ab9
3 changed files with 46 additions and 18 deletions

View File

@ -320,6 +320,29 @@ def _validate_uuid_list(data, valid_values=None):
return msg 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): def _validate_dict(data, key_specs=None):
if not isinstance(data, dict): if not isinstance(data, dict):
msg = _("'%s' is not a dictionary") % data msg = _("'%s' is not a dictionary") % data
@ -339,25 +362,14 @@ def _validate_dict(data, key_specs=None):
LOG.debug(msg) LOG.debug(msg)
return 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() for key, key_validator in [(k, v) for k, v in key_specs.iteritems()
if k in data]: if k in data]:
msg = _validate_dict_item(key, key_validator, data)
for val_name in [n for n in key_validator.iterkeys() if msg:
if n.startswith('type:')]: LOG.debug(msg)
# Check whether specified validator exists. return msg
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
def _validate_dict_or_none(data, key_specs=None): def _validate_dict_or_none(data, key_specs=None):

View File

@ -19,6 +19,7 @@
# #
from neutron.api import extensions from neutron.api import extensions
from neutron.api.v2 import attributes as attrs
from neutron.common import exceptions as qexception from neutron.common import exceptions as qexception
from neutron.extensions import l3 from neutron.extensions import l3
@ -37,7 +38,8 @@ EXTENDED_ATTRIBUTES_2_0 = {
'validate': 'validate':
{'type:dict_or_nodata': {'type:dict_or_nodata':
{'network_id': {'type:uuid': None, 'required': True}, {'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}}
}}}} }}}}

View File

@ -537,6 +537,20 @@ class TestAttributes(base.BaseTestCase):
msg = attributes._validate_dict(dictionary, constraints) msg = attributes._validate_dict(dictionary, constraints)
self.assertIsNotNone(msg) 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): def test_subdictionary(self):
dictionary, constraints = self._construct_dict_and_constraints() dictionary, constraints = self._construct_dict_and_constraints()