diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index f149e720bc..b051d60b9a 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -15,6 +15,7 @@ Stack endpoint for Heat v1 ReST API. """ +import contextlib from oslo_log import log as logging import six from six.moves.urllib import parse @@ -69,17 +70,10 @@ class InstantiationData(object): self.data[rpc_api.PARAM_EXISTING] = True @staticmethod - def format_parse(data, data_type): - """ - Parse the supplied data as JSON or YAML, raising the appropriate - exception if it is in the wrong format. - """ - + @contextlib.contextmanager + def parse_error_check(data_type): try: - if data_type == 'Environment': - return environment_format.parse(data) - else: - return template_format.parse(data) + yield except ValueError as parse_ex: mdict = {'type': data_type, 'error': six.text_type(parse_ex)} msg = _("%(type)s not in valid format: %(error)s") % mdict @@ -121,7 +115,8 @@ class InstantiationData(object): else: raise exc.HTTPBadRequest(_("No template specified")) - return self.format_parse(template_data, 'Template') + with self.parse_error_check('Template'): + return template_format.parse(template_data) def environment(self): """ @@ -135,8 +130,8 @@ class InstantiationData(object): if isinstance(env_data, dict): env = env_data else: - env = self.format_parse(env_data, - 'Environment') + with self.parse_error_check('Environment'): + env = environment_format.parse(env_data) environment_format.default_for_missing(env) parameters = self.data.get(self.PARAM_USER_PARAMS, {}) diff --git a/heat/tests/api/openstack_v1/test_api_openstack_v1.py b/heat/tests/api/openstack_v1/test_api_openstack_v1.py index 3f2064e226..400d2d1473 100644 --- a/heat/tests/api/openstack_v1/test_api_openstack_v1.py +++ b/heat/tests/api/openstack_v1/test_api_openstack_v1.py @@ -34,6 +34,7 @@ import heat.api.openstack.v1.stacks as stacks from heat.common import exception as heat_exc from heat.common import identifier from heat.common import policy +from heat.common import template_format from heat.common import urlfetch from heat.common import wsgi from heat.rpc import api as rpc_api @@ -64,22 +65,18 @@ def to_remote_error(error): class InstantiationDataTest(common.HeatTestCase): - def test_format_parse(self): - data = {"AWSTemplateFormatVersion": "2010-09-09", - "key1": ["val1[0]", "val1[1]"], - "key2": "val2"} - json_repr = ('{"AWSTemplateFormatVersion" : "2010-09-09",' - '"key1": [ "val1[0]", "val1[1]" ], ' - '"key2": "val2" }') - parsed = stacks.InstantiationData.format_parse(json_repr, 'foo') - self.assertEqual(data, parsed) + def test_parse_error_success(self): + with stacks.InstantiationData.parse_error_check('Garbage'): + pass - def test_format_parse_invalid(self): - self.assertRaises(webob.exc.HTTPBadRequest, - stacks.InstantiationData.format_parse, - '!@#$%^¬ json', 'Garbage') + def test_parse_error(self): + def generate_error(): + with stacks.InstantiationData.parse_error_check('Garbage'): + raise ValueError - def test_format_parse_invalid_message(self): + self.assertRaises(webob.exc.HTTPBadRequest, generate_error) + + def test_parse_error_message(self): # make sure the parser error gets through to the caller. bad_temp = ''' heat_template_version: '2013-05-23' @@ -89,10 +86,13 @@ parameters: description: bla ''' - parse_ex = self.assertRaises(webob.exc.HTTPBadRequest, - stacks.InstantiationData.format_parse, - bad_temp, 'foo') + def generate_error(): + with stacks.InstantiationData.parse_error_check('foo'): + template_format.parse(bad_temp) + + parse_ex = self.assertRaises(webob.exc.HTTPBadRequest, generate_error) self.assertIn('line 4, column 3', six.text_type(parse_ex)) + self.assertIn('foo', six.text_type(parse_ex)) def test_stack_name(self): body = {'stack_name': 'wibble'}