From: Steven Hardy Date: Fri, 11 Jan 2013 13:43:52 +0000 (+0000) Subject: heat engine : Add metadata validation to WaitConditionHandle X-Git-Tag: 2014.1~1013 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=d02a9319b5d6268229042f0d41a8804af1980c0e;p=openstack-build%2Fheat-build.git heat engine : Add metadata validation to WaitConditionHandle Validate metadata before updating the WaitConditionHandle resource metadata, if we raise a ValueError in response to incorrectly formatted metadata then the CFN API will map this to a HeatInvalidParameterValueError, resulting in a descriptive error response to the malformed request Change-Id: I6fde27066e9e0eaee97b59a7fbbace09ca620b48 Signed-off-by: Steven Hardy --- diff --git a/heat/engine/resources/wait_condition.py b/heat/engine/resources/wait_condition.py index 100ef5e0..49557b78 100644 --- a/heat/engine/resources/wait_condition.py +++ b/heat/engine/resources/wait_condition.py @@ -113,11 +113,29 @@ class WaitConditionHandle(resource.Resource): else: return unicode(self.name) + def _metadata_format_ok(self, metadata): + """ + Check the format of the provided metadata is as expected. + metadata must use the following format: + { + "Status" : "Status (should be SUCCESS or FAILURE)" + "UniqueId" : "Some ID, must be unique for Count>1", + "Data" : "Arbitrary Data", + "Reason" : "Reason String" + } + """ + expected_keys = ['Data', 'Reason', 'Status', 'UniqueId'] + return sorted(metadata.keys()) == expected_keys + def metadata_update(self, metadata): ''' - Update the resource metadata + Validate and update the resource metadata ''' - self.metadata = metadata + if self._metadata_format_ok(metadata): + self.metadata = metadata + else: + logger.error("Metadata failed validation for %s" % self.name) + raise ValueError("Metadata format invalid") WAIT_STATUSES = ( diff --git a/heat/tests/test_waitcondition.py b/heat/tests/test_waitcondition.py index e7479187..c11e1864 100644 --- a/heat/tests/test_waitcondition.py +++ b/heat/tests/test_waitcondition.py @@ -239,10 +239,38 @@ class WaitConditionHandleTest(unittest.TestCase): resource = stack.resources['WaitHandle'] self.assertEqual(resource.state, 'CREATE_COMPLETE') - test_metadata = {'foo': 'bar', 'baz': 'quux', 'blarg': 'wibble'} + test_metadata = {'Data': 'foo', 'Reason': 'bar', + 'Status': 'SUCCESS', 'UniqueId': '123'} resource.metadata_update(test_metadata) self.assertEqual(resource.metadata, test_metadata) stack.delete() self.m.VerifyAll() + + def test_metadata_update_invalid(self): + stack = self.create_stack() + self.m.ReplayAll() + stack.create() + + resource = stack.resources['WaitHandle'] + self.assertEqual(resource.state, 'CREATE_COMPLETE') + + # metadata_update should raise a ValueError if the metadata + # is missing any of the expected keys + err1_metadata = {'Data': 'foo', 'Status': 'SUCCESS', 'UniqueId': '123'} + self.assertRaises(ValueError, resource.metadata_update, err1_metadata) + + err1_metadata = {'Data': 'foo', 'Reason': 'bar', 'UniqueId': '1234'} + self.assertRaises(ValueError, resource.metadata_update, err1_metadata) + + err1_metadata = {'Data': 'foo', 'Reason': 'bar', 'UniqueId': '1234'} + self.assertRaises(ValueError, resource.metadata_update, err1_metadata) + + err1_metadata = {'data': 'foo', 'reason': 'bar', + 'status': 'SUCCESS', 'uniqueid': '1234'} + self.assertRaises(ValueError, resource.metadata_update, err1_metadata) + + stack.delete() + + self.m.VerifyAll()