Fixes template not using the JSON or YAML format

An internal unexpected exception is raised while validating a template
which only has string content. We should handle the case and raise the
correct error message such as "invalid format" and to tell the template is
not using the JSON or YAML format.

And modify incorrect version name and version date in this patch.
And change "template" from global variale to class varialbe in
test_api_cfn_v1.py. (missed in another patch which this patch
depends on: Change Idc2ba2b9 by misoperation)

Change-Id: I46ee8c48e3ddae71be061cfda0c029d86d132684
Closes-Bug: #1267379
This commit is contained in:
huangtianhua 2014-01-17 16:00:33 +08:00
parent 1b7fd3dc28
commit dbc66c1efd
4 changed files with 67 additions and 32 deletions

View File

@ -59,9 +59,9 @@ def parse(tmpl_str):
if len(tmpl_str) > cfg.CONF.max_template_size:
msg = _('Template exceeds maximum allowed size.')
raise exception.RequestLimitExceeded(message=msg)
if tmpl_str.startswith('{'):
try:
tpl = json.loads(tmpl_str)
else:
except ValueError:
try:
tpl = yaml.load(tmpl_str, Loader=yaml_loader)
except yaml.YAMLError as yea:
@ -69,6 +69,9 @@ def parse(tmpl_str):
else:
if tpl is None:
tpl = {}
if not isinstance(tpl, dict):
raise ValueError(_('The template is not a JSON object '
'or YAML mapping.'))
# Looking for supported version keys in the loaded template
if not ('HeatTemplateFormatVersion' in tpl
or 'heat_template_version' in tpl

View File

@ -30,7 +30,6 @@ from heat.tests.common import HeatTestCase
from heat.tests import utils
policy_path = os.path.dirname(os.path.realpath(__file__)) + "/policy/"
template = {u'AWSTemplateFormatVersion': u'2010-09-09', u'Foo': u'bar'}
class CfnStackControllerTest(HeatTestCase):
@ -51,6 +50,8 @@ class CfnStackControllerTest(HeatTestCase):
cfg.CONF.set_default('host', 'host')
self.topic = rpc_api.ENGINE_TOPIC
self.api_version = '1.0'
self.template = {u'AWSTemplateFormatVersion': u'2010-09-09',
u'Foo': u'bar'}
# Create WSGI controller instance
class DummyConfig():
@ -465,7 +466,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -488,7 +489,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -511,7 +512,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_rollback(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -534,7 +535,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -557,7 +558,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_onfailure_true(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -580,7 +581,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -603,7 +604,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_onfailure_false_delete(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -626,7 +627,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -649,7 +650,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_onfailure_false_rollback(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -672,7 +673,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -695,7 +696,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_onfailure_err(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -734,7 +735,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_err_rpcerr(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -756,7 +757,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -769,7 +770,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -782,7 +783,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -803,7 +804,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_err_exists(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -822,7 +823,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -838,7 +839,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_create_err_engine(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'CreateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'TimeoutInMinutes': 30,
@ -856,7 +857,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -873,7 +874,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_update(self):
# Format a dummy request
stack_name = "wordpress"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'UpdateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'Parameters.member.1.ParameterKey': 'InstanceType',
@ -897,7 +898,7 @@ class CfnStackControllerTest(HeatTestCase):
{'namespace': None,
'method': 'update_stack',
'args': {'stack_identity': identity,
'template': template,
'template': self.template,
'params': engine_parms,
'files': {},
'args': engine_args},
@ -920,7 +921,7 @@ class CfnStackControllerTest(HeatTestCase):
def test_update_bad_name(self):
stack_name = "wibble"
json_template = json.dumps(template)
json_template = json.dumps(self.template)
params = {'Action': 'UpdateStack', 'StackName': stack_name,
'TemplateBody': '%s' % json_template,
'Parameters.member.1.ParameterKey': 'InstanceType',
@ -956,7 +957,7 @@ class CfnStackControllerTest(HeatTestCase):
self._stub_enforce(dummy_req, 'GetTemplate')
# Stub out the RPC call to the engine with a pre-canned response
engine_resp = template
engine_resp = self.template
self.m.StubOutWithMock(rpc, 'call')
rpc.call(dummy_req.context, self.topic,
@ -976,7 +977,7 @@ class CfnStackControllerTest(HeatTestCase):
expected = {'GetTemplateResponse':
{'GetTemplateResult':
{'TemplateBody': template}}}
{'TemplateBody': self.template}}}
self.assertEqual(response, expected)

View File

@ -81,7 +81,7 @@ class InstantiationDataTest(HeatTestCase):
def test_format_parse_invalid_message(self):
# make sure the parser error gets through to the caller.
bad_temp = '''
heat_template_version: '2012-12-12'
heat_template_version: '2013-05-23'
parameters:
KeyName:
type: string
@ -110,7 +110,7 @@ parameters:
self.assertEqual(data.template(), template)
def test_template_string_json(self):
template = '{"heat_template_version": "2012-12-12",' \
template = '{"heat_template_version": "2013-05-23",' \
'"foo": "bar", "blarg": "wibble"}'
body = {'template': template}
data = stacks.InstantiationData(body)

View File

@ -79,8 +79,14 @@ class JsonToYamlTest(HeatTestCase):
class YamlMinimalTest(HeatTestCase):
def _parse_template(self, tmpl_str, msg_str):
parse_ex = self.assertRaises(ValueError,
template_format.parse,
tmpl_str)
self.assertIn(msg_str, str(parse_ex))
def test_long_yaml(self):
template = {'HeatTemplateVersion': '2012-12-12'}
template = {'HeatTemplateFormatVersion': '2012-12-12'}
config.cfg.CONF.set_override('max_template_size', 1024)
template['Resources'] = ['a'] * (config.cfg.CONF.max_template_size / 3)
limit = config.cfg.CONF.max_template_size
@ -93,13 +99,38 @@ class YamlMinimalTest(HeatTestCase):
def test_parse_no_version_format(self):
yaml = ''
self.assertRaises(ValueError, template_format.parse, yaml)
self._parse_template(yaml, 'Template format version not found')
yaml2 = '''Parameters: {}
Mappings: {}
Resources: {}
Outputs: {}
'''
self.assertRaises(ValueError, template_format.parse, yaml2)
self._parse_template(yaml2, 'Template format version not found')
def test_parse_string_template(self):
tmpl_str = 'just string'
msg = 'The template is not a JSON object or YAML mapping.'
self._parse_template(tmpl_str, msg)
def test_parse_invalid_yaml_and_json_template(self):
tmpl_str = '{test'
msg = 'line 1, column 1'
self._parse_template(tmpl_str, msg)
def test_parse_json_document(self):
tmpl_str = '["foo" , "bar"]'
msg = 'The template is not a JSON object or YAML mapping.'
self._parse_template(tmpl_str, msg)
def test_parse_empty_json_template(self):
tmpl_str = '{}'
msg = 'Template format version not found'
self._parse_template(tmpl_str, msg)
def test_parse_yaml_template(self):
tmpl_str = 'heat_template_version: 2013-05-23'
expected = {'heat_template_version': '2013-05-23'}
self.assertEqual(expected, template_format.parse(tmpl_str))
class YamlParseExceptions(HeatTestCase):