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:
Jan Provaznik 2014-10-01 15:26:45 +02:00
parent 0661277f11
commit 48214930bb
7 changed files with 37 additions and 52 deletions

View File

@ -243,7 +243,10 @@ class Property(object):
if value is None:
value = self.has_default() and self.default() or ''
if not isinstance(value, basestring):
raise ValueError(_('Value must be a string'))
if isinstance(value, (bool, int)):
value = six.text_type(value)
else:
raise ValueError(_('Value must be a string'))
return value
def _get_children(self, child_values, keys=None, validate=False):

View File

@ -74,7 +74,8 @@ class ResWithComplexPropsAndAttrs(GenericResource):
class ResourceWithProps(GenericResource):
properties_schema = {'Foo': {'Type': 'String'}}
properties_schema = {'Foo': {'Type': 'String'},
'FooInt': {'Type': 'Integer'}}
class ResourceWithPropsAndAttrs(ResourceWithProps):

View File

@ -1589,26 +1589,6 @@ class AutoScalingTest(common.HeatTestCase):
self.assertIsNone(rsrc.resource_id)
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):
t = template_format.parse(as_template)
lcp = t['Resources']['LaunchConfig']['Properties']

View File

@ -2234,6 +2234,12 @@ class StackServiceTest(HeatTestCase):
'update_allowed': False,
'immutable': False,
},
'FooInt': {
'type': 'integer',
'required': False,
'update_allowed': False,
'immutable': False,
},
},
'attributes': {
'foo': {'description': 'A generic attribute'},

View File

@ -149,7 +149,7 @@ class EventTest(HeatTestCase):
rname = 'bad_resource'
defn = rsrc_defn.ResourceDefinition(rname,
'ResourceWithRequiredProps',
{'Foo': False})
{'IntFoo': False})
res = generic_rsrc.ResourceWithRequiredProps(rname, defn, self.stack)
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',

View File

@ -225,30 +225,6 @@ class InstancesTest(HeatTestCase):
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):
stack_name = 'without_Ebs'
tmpl, stack = self._setup_test_stack(stack_name)

View File

@ -703,6 +703,16 @@ class PropertyTest(testtools.TestCase):
self.assertEqual("int() argument must be a string or a number, "
"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):
schema = {'Type': 'Integer'}
p = properties.Property(schema)
@ -1498,16 +1508,25 @@ class PropertiesValidationTest(testtools.TestCase):
props = properties.Properties(schema, {})
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):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'food': 42})
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):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'foo': None})