Convert props form delimited params to lists

Use allow_conversion flag to convert comma_delimited_list
to list before validation when using from_parameter.

Change-Id: Id144aade23eee13df227acdb728906c8dd345337
Closes-Bug: #1617019
This commit is contained in:
rabi 2016-08-26 17:05:54 +05:30
parent a495438c9c
commit 80bc4fbebd
4 changed files with 26 additions and 6 deletions

View File

@ -28,6 +28,16 @@ def extract_bool(name, value):
return strutils.bool_from_string(value, strict=True) return strutils.bool_from_string(value, strict=True)
def delim_string_to_list(value):
if value is None:
return None
if value == '':
return []
return value.split(',')
def extract_int(name, value, allow_zero=True, allow_negative=False): def extract_int(name, value, allow_zero=True, allow_negative=False):
if value is None: if value is None:
return None return None

View File

@ -21,6 +21,7 @@ import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.common import param_utils
from heat.engine import constraints as constr from heat.engine import constraints as constr
@ -376,10 +377,7 @@ class CommaDelimitedListParam(ParsedParameter, collections.Sequence):
if isinstance(value, list): if isinstance(value, list):
return [(six.text_type(x)) for x in value] return [(six.text_type(x)) for x in value]
try: try:
if value is not None: return param_utils.delim_string_to_list(value)
if value == '':
return []
return value.split(',')
except (KeyError, AttributeError) as err: except (KeyError, AttributeError) as err:
message = _('Value must be a comma-delimited list string: %s') message = _('Value must be a comma-delimited list string: %s')
raise ValueError(message % six.text_type(err)) raise ValueError(message % six.text_type(err))

View File

@ -18,6 +18,7 @@ import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.common import param_utils
from heat.engine import constraints as constr from heat.engine import constraints as constr
from heat.engine import function from heat.engine import function
from heat.engine.hot import parameters as hot_param from heat.engine.hot import parameters as hot_param
@ -162,7 +163,8 @@ class Schema(constr.Schema):
# a json parameter value is passed via a Map property, which requires # a json parameter value is passed via a Map property, which requires
# some coercion to pass strings or lists (which are both valid for # some coercion to pass strings or lists (which are both valid for
# Json parameters but not for Map properties). # Json parameters but not for Map properties).
allow_conversion = param.type == param.MAP allow_conversion = (param.type == param.MAP
or param.type == param.LIST)
# make update_allowed true by default on TemplateResources # make update_allowed true by default on TemplateResources
# as the template should deal with this. # as the template should deal with this.
@ -299,6 +301,9 @@ class Property(object):
def _get_list(self, value, validate=False): def _get_list(self, value, validate=False):
if value is None: if value is None:
value = self.has_default() and self.default() or [] value = self.has_default() and self.default() or []
if self.schema.allow_conversion and isinstance(value,
six.string_types):
value = param_utils.delim_string_to_list(value)
if (not isinstance(value, collections.Sequence) or if (not isinstance(value, collections.Sequence) or
isinstance(value, six.string_types)): isinstance(value, six.string_types)):
raise TypeError(_('"%s" is not a list') % repr(value)) raise TypeError(_('"%s" is not a list') % repr(value))

View File

@ -598,7 +598,7 @@ class PropertySchemaTest(common.HeatTestCase):
self.assertEqual(properties.Schema.LIST, schema.type) self.assertEqual(properties.Schema.LIST, schema.type)
self.assertIsNone(schema.default) self.assertIsNone(schema.default)
self.assertFalse(schema.required) self.assertFalse(schema.required)
self.assertFalse(schema.allow_conversion) self.assertTrue(schema.allow_conversion)
props = properties.Properties({'test': schema}, {}) props = properties.Properties({'test': schema}, {})
props.validate() props.validate()
@ -903,6 +903,13 @@ class PropertyTest(common.HeatTestCase):
p = properties.Property({'Type': 'List'}) p = properties.Property({'Type': 'List'})
self.assertRaises(TypeError, p.get_value, {'foo': 'bar'}) self.assertRaises(TypeError, p.get_value, {'foo': 'bar'})
def test_list_is_delimited(self):
p = properties.Property({'Type': 'List'})
self.assertRaises(TypeError, p.get_value, 'foo,bar')
p.schema.allow_conversion = True
self.assertEqual(['foo', 'bar'], p.get_value('foo,bar'))
self.assertEqual(['foo'], p.get_value('foo'))
def test_list_maxlength_good(self): def test_list_maxlength_good(self):
schema = {'Type': 'List', schema = {'Type': 'List',
'MaxLength': '3'} 'MaxLength': '3'}