summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Provaznik <jprovazn@redhat.com>2014-10-01 15:26:45 +0200
committerSteven Hardy <shardy@redhat.com>2015-01-29 11:06:06 +0000
commitb52c916da0759fb5b310ecbcce5db2608b67fdb1 (patch)
treea5c3c87a1add20fa1c6b363ad54537a48d9d1c98
parent97bd3cca359b6cd59fb5330988e45135db52eefe (diff)
downloadheat-b52c916da0759fb5b310ecbcce5db2608b67fdb1.tar.gz
Convert bool/int values into string for string properties2014.2.2
Instead of rising an exception, boolean and integer values are converted into string if string is expected. Change-Id: I1e0014576c4df447bfa1595c530f1e24f411195d Closes-Bug: #1367375 (cherry picked from commit 48214930bbec2e09569d848fa5b8759c429acd5b)
-rw-r--r--heat/engine/properties.py5
-rw-r--r--heat/tests/generic_resource.py3
-rw-r--r--heat/tests/test_autoscaling.py20
-rw-r--r--heat/tests/test_engine_service.py6
-rw-r--r--heat/tests/test_event.py2
-rw-r--r--heat/tests/test_instance.py24
-rw-r--r--heat/tests/test_properties.py29
7 files changed, 37 insertions, 52 deletions
diff --git a/heat/engine/properties.py b/heat/engine/properties.py
index 0bec8fab5..bca7d552b 100644
--- a/heat/engine/properties.py
+++ b/heat/engine/properties.py
@@ -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):
diff --git a/heat/tests/generic_resource.py b/heat/tests/generic_resource.py
index 8e102d711..de3665041 100644
--- a/heat/tests/generic_resource.py
+++ b/heat/tests/generic_resource.py
@@ -76,7 +76,8 @@ class ResWithComplexPropsAndAttrs(GenericResource):
class ResourceWithProps(GenericResource):
- properties_schema = {'Foo': {'Type': 'String'}}
+ properties_schema = {'Foo': {'Type': 'String'},
+ 'FooInt': {'Type': 'Integer'}}
class ResourceWithPropsAndAttrs(ResourceWithProps):
diff --git a/heat/tests/test_autoscaling.py b/heat/tests/test_autoscaling.py
index 468d0035e..d57f688dc 100644
--- a/heat/tests/test_autoscaling.py
+++ b/heat/tests/test_autoscaling.py
@@ -1751,26 +1751,6 @@ class AutoScalingTest(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']
diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py
index fa8387fb2..1bcead69d 100644
--- a/heat/tests/test_engine_service.py
+++ b/heat/tests/test_engine_service.py
@@ -2202,6 +2202,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'},
diff --git a/heat/tests/test_event.py b/heat/tests/test_event.py
index 1f756a568..638b0f685 100644
--- a/heat/tests/test_event.py
+++ b/heat/tests/test_event.py
@@ -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',
diff --git a/heat/tests/test_instance.py b/heat/tests/test_instance.py
index 92698c362..e52198999 100644
--- a/heat/tests/test_instance.py
+++ b/heat/tests/test_instance.py
@@ -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)
diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py
index a92fa3b1f..616625a3b 100644
--- a/heat/tests/test_properties.py
+++ b/heat/tests/test_properties.py
@@ -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)
@@ -1514,16 +1524,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})