Convert bool/int values into string for string properties
Instead of rising an exception, boolean and integer values are converted into string if string is expected. Change-Id: I1e0014576c4df447bfa1595c530f1e24f411195d Closes-Bug: #1367375
This commit is contained in:
parent
0661277f11
commit
48214930bb
@ -243,6 +243,9 @@ class Property(object):
|
|||||||
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 not isinstance(value, basestring):
|
if not isinstance(value, basestring):
|
||||||
|
if isinstance(value, (bool, int)):
|
||||||
|
value = six.text_type(value)
|
||||||
|
else:
|
||||||
raise ValueError(_('Value must be a string'))
|
raise ValueError(_('Value must be a string'))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -74,7 +74,8 @@ class ResWithComplexPropsAndAttrs(GenericResource):
|
|||||||
|
|
||||||
|
|
||||||
class ResourceWithProps(GenericResource):
|
class ResourceWithProps(GenericResource):
|
||||||
properties_schema = {'Foo': {'Type': 'String'}}
|
properties_schema = {'Foo': {'Type': 'String'},
|
||||||
|
'FooInt': {'Type': 'Integer'}}
|
||||||
|
|
||||||
|
|
||||||
class ResourceWithPropsAndAttrs(ResourceWithProps):
|
class ResourceWithPropsAndAttrs(ResourceWithProps):
|
||||||
|
@ -1589,26 +1589,6 @@ class AutoScalingTest(common.HeatTestCase):
|
|||||||
self.assertIsNone(rsrc.resource_id)
|
self.assertIsNone(rsrc.resource_id)
|
||||||
self.assertEqual('LaunchConfig', rsrc.FnGetRefId())
|
self.assertEqual('LaunchConfig', rsrc.FnGetRefId())
|
||||||
|
|
||||||
def test_validate_BlockDeviceMappings_VolumeSize_invalid_str(self):
|
|
||||||
t = template_format.parse(as_template)
|
|
||||||
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
||||||
bdm = [{'DeviceName': 'vdb',
|
|
||||||
'Ebs': {'SnapshotId': '1234',
|
|
||||||
'VolumeSize': 10}}]
|
|
||||||
lcp['BlockDeviceMappings'] = bdm
|
|
||||||
stack = utils.parse_stack(t, params=self.params)
|
|
||||||
self.stub_ImageConstraint_validate()
|
|
||||||
self.m.ReplayAll()
|
|
||||||
|
|
||||||
e = self.assertRaises(exception.StackValidationFailed,
|
|
||||||
self.create_scaling_group, t,
|
|
||||||
stack, 'LaunchConfig')
|
|
||||||
|
|
||||||
expected_msg = "Value must be a string"
|
|
||||||
self.assertIn(expected_msg, six.text_type(e))
|
|
||||||
|
|
||||||
self.m.VerifyAll()
|
|
||||||
|
|
||||||
def test_validate_BlockDeviceMappings_without_Ebs_property(self):
|
def test_validate_BlockDeviceMappings_without_Ebs_property(self):
|
||||||
t = template_format.parse(as_template)
|
t = template_format.parse(as_template)
|
||||||
lcp = t['Resources']['LaunchConfig']['Properties']
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
||||||
|
@ -2234,6 +2234,12 @@ class StackServiceTest(HeatTestCase):
|
|||||||
'update_allowed': False,
|
'update_allowed': False,
|
||||||
'immutable': False,
|
'immutable': False,
|
||||||
},
|
},
|
||||||
|
'FooInt': {
|
||||||
|
'type': 'integer',
|
||||||
|
'required': False,
|
||||||
|
'update_allowed': False,
|
||||||
|
'immutable': False,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
'attributes': {
|
'attributes': {
|
||||||
'foo': {'description': 'A generic attribute'},
|
'foo': {'description': 'A generic attribute'},
|
||||||
|
@ -149,7 +149,7 @@ class EventTest(HeatTestCase):
|
|||||||
rname = 'bad_resource'
|
rname = 'bad_resource'
|
||||||
defn = rsrc_defn.ResourceDefinition(rname,
|
defn = rsrc_defn.ResourceDefinition(rname,
|
||||||
'ResourceWithRequiredProps',
|
'ResourceWithRequiredProps',
|
||||||
{'Foo': False})
|
{'IntFoo': False})
|
||||||
|
|
||||||
res = generic_rsrc.ResourceWithRequiredProps(rname, defn, self.stack)
|
res = generic_rsrc.ResourceWithRequiredProps(rname, defn, self.stack)
|
||||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||||
|
@ -225,30 +225,6 @@ class InstancesTest(HeatTestCase):
|
|||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_validate_BlockDeviceMappings_VolumeSize_invalid_str(self):
|
|
||||||
stack_name = 'val_VolumeSize_valid'
|
|
||||||
tmpl, stack = self._setup_test_stack(stack_name)
|
|
||||||
bdm = [{'DeviceName': 'vdb',
|
|
||||||
'Ebs': {'SnapshotId': '1234',
|
|
||||||
'VolumeSize': 10}}]
|
|
||||||
wsp = tmpl.t['Resources']['WebServer']['Properties']
|
|
||||||
wsp['BlockDeviceMappings'] = bdm
|
|
||||||
resource_defns = tmpl.resource_definitions(stack)
|
|
||||||
instance = instances.Instance('validate_volume_size',
|
|
||||||
resource_defns['WebServer'], stack)
|
|
||||||
|
|
||||||
self._mock_get_image_id_success('F17-x86_64-gold', 1)
|
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
|
||||||
nova.NovaClientPlugin._create().MultipleTimes().AndReturn(self.fc)
|
|
||||||
|
|
||||||
self.m.ReplayAll()
|
|
||||||
|
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
|
||||||
instance.validate)
|
|
||||||
self.assertIn("Value must be a string", six.text_type(exc))
|
|
||||||
|
|
||||||
self.m.VerifyAll()
|
|
||||||
|
|
||||||
def test_validate_BlockDeviceMappings_without_Ebs_property(self):
|
def test_validate_BlockDeviceMappings_without_Ebs_property(self):
|
||||||
stack_name = 'without_Ebs'
|
stack_name = 'without_Ebs'
|
||||||
tmpl, stack = self._setup_test_stack(stack_name)
|
tmpl, stack = self._setup_test_stack(stack_name)
|
||||||
|
@ -703,6 +703,16 @@ class PropertyTest(testtools.TestCase):
|
|||||||
self.assertEqual("int() argument must be a string or a number, "
|
self.assertEqual("int() argument must be a string or a number, "
|
||||||
"not 'list'", six.text_type(ex))
|
"not 'list'", six.text_type(ex))
|
||||||
|
|
||||||
|
def test_str_from_int(self):
|
||||||
|
schema = {'Type': 'String'}
|
||||||
|
p = properties.Property(schema)
|
||||||
|
self.assertEqual('3', p.get_value(3))
|
||||||
|
|
||||||
|
def test_str_from_bool(self):
|
||||||
|
schema = {'Type': 'String'}
|
||||||
|
p = properties.Property(schema)
|
||||||
|
self.assertEqual('True', p.get_value(True))
|
||||||
|
|
||||||
def test_int_from_str_good(self):
|
def test_int_from_str_good(self):
|
||||||
schema = {'Type': 'Integer'}
|
schema = {'Type': 'Integer'}
|
||||||
p = properties.Property(schema)
|
p = properties.Property(schema)
|
||||||
@ -1498,16 +1508,25 @@ class PropertiesValidationTest(testtools.TestCase):
|
|||||||
props = properties.Properties(schema, {})
|
props = properties.Properties(schema, {})
|
||||||
self.assertIsNone(props.validate())
|
self.assertIsNone(props.validate())
|
||||||
|
|
||||||
def test_bad_data(self):
|
|
||||||
schema = {'foo': {'Type': 'String'}}
|
|
||||||
props = properties.Properties(schema, {'foo': 42})
|
|
||||||
self.assertRaises(exception.StackValidationFailed, props.validate)
|
|
||||||
|
|
||||||
def test_unknown_typo(self):
|
def test_unknown_typo(self):
|
||||||
schema = {'foo': {'Type': 'String'}}
|
schema = {'foo': {'Type': 'String'}}
|
||||||
props = properties.Properties(schema, {'food': 42})
|
props = properties.Properties(schema, {'food': 42})
|
||||||
self.assertRaises(exception.StackValidationFailed, props.validate)
|
self.assertRaises(exception.StackValidationFailed, props.validate)
|
||||||
|
|
||||||
|
def test_list_instead_string(self):
|
||||||
|
schema = {'foo': {'Type': 'String'}}
|
||||||
|
props = properties.Properties(schema, {'foo': ['foo', 'bar']})
|
||||||
|
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
||||||
|
self.assertEqual('Property error : foo Value must be a string',
|
||||||
|
six.text_type(ex))
|
||||||
|
|
||||||
|
def test_dict_instead_string(self):
|
||||||
|
schema = {'foo': {'Type': 'String'}}
|
||||||
|
props = properties.Properties(schema, {'foo': {'foo': 'bar'}})
|
||||||
|
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
||||||
|
self.assertEqual('Property error : foo Value must be a string',
|
||||||
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_none_string(self):
|
def test_none_string(self):
|
||||||
schema = {'foo': {'Type': 'String'}}
|
schema = {'foo': {'Type': 'String'}}
|
||||||
props = properties.Properties(schema, {'foo': None})
|
props = properties.Properties(schema, {'foo': None})
|
||||||
|
Loading…
Reference in New Issue
Block a user