Merge "Allow lists and strings for Json parameters via provider resources"
This commit is contained in:
commit
32aa3aac2b
@ -13,6 +13,7 @@
|
||||
|
||||
import collections
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
@ -58,13 +59,15 @@ class Schema(constr.Schema):
|
||||
implemented=True,
|
||||
update_allowed=False,
|
||||
immutable=False,
|
||||
support_status=support.SupportStatus()):
|
||||
support_status=support.SupportStatus(),
|
||||
allow_conversion=False):
|
||||
super(Schema, self).__init__(data_type, description, default,
|
||||
schema, required, constraints)
|
||||
self.implemented = implemented
|
||||
self.update_allowed = update_allowed
|
||||
self.immutable = immutable
|
||||
self.support_status = support_status
|
||||
self.allow_conversion = allow_conversion
|
||||
# validate structural correctness of schema itself
|
||||
self.validate()
|
||||
|
||||
@ -146,6 +149,13 @@ class Schema(constr.Schema):
|
||||
param.BOOLEAN: cls.BOOLEAN
|
||||
}
|
||||
|
||||
# allow_conversion allows slightly more flexible type conversion
|
||||
# where property->parameter types don't align, primarily when
|
||||
# a json parameter value is passed via a Map property, which requires
|
||||
# some coercion to pass strings or lists (which are both valid for
|
||||
# Json parameters but not for Map properties).
|
||||
allow_conversion = param.type == param.MAP
|
||||
|
||||
# make update_allowed true by default on TemplateResources
|
||||
# as the template should deal with this.
|
||||
return cls(data_type=param_type_map.get(param.type, cls.MAP),
|
||||
@ -153,7 +163,8 @@ class Schema(constr.Schema):
|
||||
required=param.required,
|
||||
constraints=param.constraints,
|
||||
update_allowed=True,
|
||||
immutable=False)
|
||||
immutable=False,
|
||||
allow_conversion=allow_conversion)
|
||||
|
||||
def allowed_param_prop_type(self):
|
||||
"""
|
||||
@ -269,6 +280,14 @@ class Property(object):
|
||||
if value is None:
|
||||
value = self.has_default() and self.default() or {}
|
||||
if not isinstance(value, collections.Mapping):
|
||||
# This is to handle passing Lists via Json parameters exposed
|
||||
# via a provider resource, in particular lists-of-dicts which
|
||||
# cannot be handled correctly via comma_delimited_list
|
||||
if self.schema.allow_conversion:
|
||||
if isinstance(value, six.string_types):
|
||||
return value
|
||||
elif isinstance(value, collections.Sequence):
|
||||
return jsonutils.dumps(value)
|
||||
raise TypeError(_('"%s" is not a map') % value)
|
||||
|
||||
return dict(self._get_children(six.iteritems(value),
|
||||
|
@ -11,6 +11,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import testtools
|
||||
|
||||
@ -468,6 +469,7 @@ class PropertySchemaTest(testtools.TestCase):
|
||||
self.assertTrue(schema.required)
|
||||
self.assertIsNone(schema.default)
|
||||
self.assertEqual(0, len(schema.constraints))
|
||||
self.assertFalse(schema.allow_conversion)
|
||||
|
||||
def test_from_number_param_min(self):
|
||||
default = "42"
|
||||
@ -546,6 +548,7 @@ class PropertySchemaTest(testtools.TestCase):
|
||||
self.assertIsNone(schema.default)
|
||||
self.assertFalse(schema.required)
|
||||
self.assertEqual(1, len(schema.constraints))
|
||||
self.assertFalse(schema.allow_conversion)
|
||||
|
||||
allowed_constraint = schema.constraints[0]
|
||||
|
||||
@ -563,6 +566,7 @@ class PropertySchemaTest(testtools.TestCase):
|
||||
self.assertEqual(properties.Schema.LIST, schema.type)
|
||||
self.assertIsNone(schema.default)
|
||||
self.assertFalse(schema.required)
|
||||
self.assertFalse(schema.allow_conversion)
|
||||
|
||||
def test_from_json_param(self):
|
||||
param = parameters.Schema.from_dict('name', {
|
||||
@ -575,6 +579,7 @@ class PropertySchemaTest(testtools.TestCase):
|
||||
self.assertEqual(properties.Schema.MAP, schema.type)
|
||||
self.assertIsNone(schema.default)
|
||||
self.assertFalse(schema.required)
|
||||
self.assertTrue(schema.allow_conversion)
|
||||
|
||||
|
||||
class PropertyTest(testtools.TestCase):
|
||||
@ -862,6 +867,12 @@ class PropertyTest(testtools.TestCase):
|
||||
p = properties.Property({'Type': 'Map'})
|
||||
self.assertRaises(TypeError, p.get_value, ['foo'])
|
||||
|
||||
def test_map_allow_conversion(self):
|
||||
p = properties.Property({'Type': 'Map'})
|
||||
p.schema.allow_conversion = True
|
||||
self.assertEqual('foo', p.get_value('foo'))
|
||||
self.assertEqual(jsonutils.dumps(['foo']), p.get_value(['foo']))
|
||||
|
||||
def test_map_schema_good(self):
|
||||
map_schema = {'valid': {'Type': 'Boolean'}}
|
||||
p = properties.Property({'Type': 'Map', 'Schema': map_schema})
|
||||
|
Loading…
Reference in New Issue
Block a user