From c55a2ea232a9bdca8d4d75b513772f109d0dffd0 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 26 Nov 2012 13:52:34 +1300 Subject: [PATCH] Don't assume parsed JSON in REST API. This checks to see if the 'template' attribute is a dict. If not it uses format.parse_to_template to parse it. Change-Id: Ic9b9ef3e88a33a93d5896277cc3d4da4fd55fc25 --- heat/api/openstack/v1/stacks.py | 24 +++++++++++++++--------- heat/tests/test_api_openstack_v1.py | 25 ++++++++++++++++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index 0461551d..64a78fec 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -26,6 +26,7 @@ from webob import exc from heat.api.openstack.v1 import util from heat.common import wsgi +from heat.engine import format from heat.engine import api as engine_api from heat.engine import rpcapi as engine_rpcapi @@ -57,16 +58,16 @@ class InstantiationData(object): self.data = data @staticmethod - def json_parse(data, data_type): + def format_parse(data, data_type): """ - Parse the supplied data as JSON, raising the appropriate exception - if it is in the wrong format. + Parse the supplied data as JSON or YAML, raising the appropriate + exception if it is in the wrong format. """ try: - return json.loads(data) + return format.parse_to_template(data) except ValueError: - err_reason = "%s not in valid JSON format" % data_type + err_reason = "%s not in valid format" % data_type raise exc.HTTPBadRequest(explanation=err_reason) def stack_name(self): @@ -79,7 +80,8 @@ class InstantiationData(object): def _load_template(self, template_url): """ - Retrieve a template from a URL, in JSON format. + Retrieve a template from a URL, in JSON + or YAML format. """ logger.debug('Template URL %s' % template_url) url = urlparse.urlparse(template_url) @@ -98,7 +100,7 @@ class InstantiationData(object): if resp.status != 200: raise exc.HTTPBadRequest(explanation=err_reason) - return self.json_parse(resp.read(), 'Template') + return self.format_parse(resp.read(), 'Template') finally: conn.close() except socket.gaierror: @@ -107,10 +109,14 @@ class InstantiationData(object): def template(self): """ Get template file contents, either inline or from a URL, in JSON - format. + or YAML format. """ if self.PARAM_TEMPLATE in self.data: - return self.data[self.PARAM_TEMPLATE] + tpl = self.data[self.PARAM_TEMPLATE] + if isinstance(tpl, dict): + return tpl + return self.format_parse(self.data[self.PARAM_TEMPLATE], + 'Template') elif self.PARAM_TEMPLATE_URL in self.data: return self._load_template(self.data[self.PARAM_TEMPLATE_URL]) diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py index 2e42f59c..e624192c 100644 --- a/heat/tests/test_api_openstack_v1.py +++ b/heat/tests/test_api_openstack_v1.py @@ -18,6 +18,7 @@ import socket import nose import mox import json +import yaml import unittest from nose.plugins.attrib import attr @@ -48,16 +49,16 @@ class InstantiationDataTest(unittest.TestCase): def tearDown(self): self.m.UnsetStubs() - def test_json_parse(self): + def test_format_parse(self): data = {"key1": ["val1[0]", "val1[1]"], "key2": "val2"} json_repr = '{ "key1": [ "val1[0]", "val1[1]" ], "key2": "val2" }' - parsed = stacks.InstantiationData.json_parse(json_repr, 'foo') + parsed = stacks.InstantiationData.format_parse(json_repr, 'foo') self.assertEqual(parsed, data) - def test_json_parse_invalid(self): + def test_format_parse_invalid(self): self.assertRaises(webob.exc.HTTPBadRequest, - stacks.InstantiationData.json_parse, - 'not json', 'Garbage') + stacks.InstantiationData.format_parse, + '!@#$%^¬ json', 'Garbage') def test_stack_name(self): body = {'stack_name': 'wibble'} @@ -75,6 +76,20 @@ class InstantiationDataTest(unittest.TestCase): data = stacks.InstantiationData(body) self.assertEqual(data.template(), template) + def test_template_string_json(self): + template = '{"foo": "bar", "blarg": "wibble"}' + body = {'template': template} + data = stacks.InstantiationData(body) + self.assertEqual(data.template(), json.loads(template)) + + def test_template_string_yaml(self): + template = '''foo: bar +blarg: wibble +''' + body = {'template': template} + data = stacks.InstantiationData(body) + self.assertEqual(data.template(), yaml.load(template)) + def test_template_url(self): template = {'foo': 'bar', 'blarg': 'wibble'} url = 'http://example.com/template' -- 2.45.2