Merge ""version" section should be required in template"
This commit is contained in:
commit
1b7fd3dc28
@ -28,7 +28,7 @@ from ..plugin import docker_container # noqa
|
||||
|
||||
template = '''
|
||||
{
|
||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "Test template",
|
||||
"Parameters": {},
|
||||
"Resources": {
|
||||
|
@ -169,6 +169,7 @@ class FakeAutoScale(object):
|
||||
class ScalingGroupTest(HeatTestCase):
|
||||
|
||||
group_template = template_format.parse('''
|
||||
HeatTemplateFormatVersion: "2012-12-12"
|
||||
Description: "Rackspace Auto Scale"
|
||||
Parameters: {}
|
||||
Resources:
|
||||
@ -335,6 +336,7 @@ class ScalingGroupTest(HeatTestCase):
|
||||
|
||||
class PolicyTest(HeatTestCase):
|
||||
policy_template = template_format.parse('''
|
||||
HeatTemplateFormatVersion: "2012-12-12"
|
||||
Description: "Rackspace Auto Scale"
|
||||
Parameters: {}
|
||||
Resources:
|
||||
@ -477,6 +479,7 @@ class PolicyTest(HeatTestCase):
|
||||
|
||||
class WebHookTest(HeatTestCase):
|
||||
webhook_template = template_format.parse('''
|
||||
HeatTemplateFormatVersion: "2012-12-12"
|
||||
Description: "Rackspace Auto Scale"
|
||||
Parameters: {}
|
||||
Resources:
|
||||
|
@ -69,28 +69,14 @@ def parse(tmpl_str):
|
||||
else:
|
||||
if tpl is None:
|
||||
tpl = {}
|
||||
if u'heat_template_version' not in tpl:
|
||||
default_for_missing(tpl, u'HeatTemplateFormatVersion',
|
||||
HEAT_VERSIONS)
|
||||
# Looking for supported version keys in the loaded template
|
||||
if not ('HeatTemplateFormatVersion' in tpl
|
||||
or 'heat_template_version' in tpl
|
||||
or 'AWSTemplateFormatVersion' in tpl):
|
||||
raise ValueError(_("Template format version not found."))
|
||||
return tpl
|
||||
|
||||
|
||||
def default_for_missing(tpl, version_param, versions):
|
||||
'''
|
||||
Checks a parsed template for missing version and sections.
|
||||
|
||||
This is currently only applied to YAML templates.
|
||||
'''
|
||||
# if version is missing, implicitly use the lastest one
|
||||
if version_param not in tpl:
|
||||
tpl[version_param] = versions[-1]
|
||||
|
||||
# create empty placeholders for any of the main dict sections
|
||||
for param in (u'Parameters', u'Mappings', u'Resources', u'Outputs'):
|
||||
if param not in tpl:
|
||||
tpl[param] = {}
|
||||
|
||||
|
||||
def convert_json_to_yaml(json_str):
|
||||
'''Convert a string containing the AWS JSON template format
|
||||
to an equivalent string containing the Heat YAML format.
|
||||
|
@ -3,10 +3,6 @@
|
||||
|
||||
"Description" : "Template to test Neutron resources",
|
||||
|
||||
"Parameters" : {
|
||||
|
||||
},
|
||||
|
||||
"Resources" : {
|
||||
"network": {
|
||||
"Type": "OS::Neutron::Net",
|
||||
|
@ -30,6 +30,7 @@ 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):
|
||||
@ -464,7 +465,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -511,7 +511,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_rollback(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -558,7 +557,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_onfailure_true(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -605,7 +603,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_onfailure_false_delete(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -652,7 +649,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_onfailure_false_rollback(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -699,7 +695,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_onfailure_err(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -739,7 +734,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_err_rpcerr(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -809,7 +803,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_err_exists(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -845,7 +838,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_create_err_engine(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'CreateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -881,7 +873,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_update(self):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'UpdateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -929,7 +920,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
|
||||
def test_update_bad_name(self):
|
||||
stack_name = "wibble"
|
||||
template = {u'Foo': u'bar'}
|
||||
json_template = json.dumps(template)
|
||||
params = {'Action': 'UpdateStack', 'StackName': stack_name,
|
||||
'TemplateBody': '%s' % json_template,
|
||||
@ -961,7 +951,6 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
# Format a dummy request
|
||||
stack_name = "wordpress"
|
||||
identity = dict(identifier.HeatIdentifier('t', stack_name, '6'))
|
||||
template = {u'Foo': u'bar'}
|
||||
params = {'Action': 'GetTemplate', 'StackName': stack_name}
|
||||
dummy_req = self._dummy_GET_request(params)
|
||||
self._stub_enforce(dummy_req, 'GetTemplate')
|
||||
@ -1092,12 +1081,10 @@ class CfnStackControllerTest(HeatTestCase):
|
||||
def test_bad_resources_in_template(self):
|
||||
# Format a dummy request
|
||||
json_template = {
|
||||
'template': {
|
||||
'AWSTemplateFormatVersion': '2010-09-09',
|
||||
'Resources': {
|
||||
'Type': 'AWS: : EC2: : Instance',
|
||||
},
|
||||
}
|
||||
'AWSTemplateFormatVersion': '2010-09-09',
|
||||
'Resources': {
|
||||
'Type': 'AWS: : EC2: : Instance',
|
||||
},
|
||||
}
|
||||
params = {'Action': 'ValidateTemplate',
|
||||
'TemplateBody': '%s' % json.dumps(json_template)}
|
||||
|
@ -64,8 +64,12 @@ def to_remote_error(error):
|
||||
class InstantiationDataTest(HeatTestCase):
|
||||
|
||||
def test_format_parse(self):
|
||||
data = {"key1": ["val1[0]", "val1[1]"], "key2": "val2"}
|
||||
json_repr = '{ "key1": [ "val1[0]", "val1[1]" ], "key2": "val2" }'
|
||||
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(parsed, data)
|
||||
|
||||
@ -77,6 +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'
|
||||
parameters:
|
||||
KeyName:
|
||||
type: string
|
||||
@ -86,7 +91,7 @@ parameters:
|
||||
parse_ex = self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
stacks.InstantiationData.format_parse,
|
||||
bad_temp, 'foo')
|
||||
self.assertIn('line 3, column 3', str(parse_ex))
|
||||
self.assertIn('line 4, column 3', str(parse_ex))
|
||||
|
||||
def test_stack_name(self):
|
||||
body = {'stack_name': 'wibble'}
|
||||
@ -105,20 +110,18 @@ parameters:
|
||||
self.assertEqual(data.template(), template)
|
||||
|
||||
def test_template_string_json(self):
|
||||
template = '{"foo": "bar", "blarg": "wibble"}'
|
||||
template = '{"heat_template_version": "2012-12-12",' \
|
||||
'"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
|
||||
template = '''HeatTemplateFormatVersion: 2012-12-12
|
||||
foo: bar
|
||||
blarg: wibble
|
||||
'''
|
||||
parsed = {u'HeatTemplateFormatVersion': u'2012-12-12',
|
||||
u'Mappings': {},
|
||||
u'Outputs': {},
|
||||
u'Parameters': {},
|
||||
u'Resources': {},
|
||||
u'blarg': u'wibble',
|
||||
u'foo': u'bar'}
|
||||
|
||||
@ -127,7 +130,9 @@ blarg: wibble
|
||||
self.assertEqual(data.template(), parsed)
|
||||
|
||||
def test_template_url(self):
|
||||
template = {'foo': 'bar', 'blarg': 'wibble'}
|
||||
template = {'heat_template_version': '2013-05-23',
|
||||
'foo': 'bar',
|
||||
'blarg': 'wibble'}
|
||||
url = 'http://example.com/template'
|
||||
body = {'template_url': url}
|
||||
data = stacks.InstantiationData(body)
|
||||
|
@ -405,7 +405,7 @@ Outputs:
|
||||
|
||||
def test_nested_stack_three_deep(self):
|
||||
root_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -413,7 +413,7 @@ Resources:
|
||||
TemplateURL: 'https://server.test/depth1.template'
|
||||
'''
|
||||
depth1_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -421,7 +421,7 @@ Resources:
|
||||
TemplateURL: 'https://server.test/depth2.template'
|
||||
'''
|
||||
depth2_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -445,7 +445,7 @@ Resources:
|
||||
|
||||
def test_nested_stack_four_deep(self):
|
||||
root_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -453,7 +453,7 @@ Resources:
|
||||
TemplateURL: 'https://server.test/depth1.template'
|
||||
'''
|
||||
depth1_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -461,7 +461,7 @@ Resources:
|
||||
TemplateURL: 'https://server.test/depth2.template'
|
||||
'''
|
||||
depth2_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -469,7 +469,7 @@ Resources:
|
||||
TemplateURL: 'https://server.test/depth3.template'
|
||||
'''
|
||||
depth3_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -500,7 +500,7 @@ Resources:
|
||||
|
||||
def test_nested_stack_four_wide(self):
|
||||
root_template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
@ -545,7 +545,7 @@ Resources:
|
||||
|
||||
def test_nested_stack_infinite_recursion(self):
|
||||
template = '''
|
||||
HeatTemplateFormat: 2012-12-12
|
||||
HeatTemplateFormatVersion: 2012-12-12
|
||||
Resources:
|
||||
Nested:
|
||||
Type: AWS::CloudFormation::Stack
|
||||
|
@ -104,6 +104,7 @@ class ParserTest(HeatTestCase):
|
||||
|
||||
|
||||
mapping_template = template_format.parse('''{
|
||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||
"Mappings" : {
|
||||
"ValidMapping" : {
|
||||
"TestKey" : { "TestValue" : "wibble" }
|
||||
@ -789,10 +790,12 @@ class StackTest(HeatTestCase):
|
||||
self.assertEqual(1, stack.total_resources())
|
||||
|
||||
def _setup_nested(self, name):
|
||||
nested_tpl = ('{"Resources":{'
|
||||
nested_tpl = ('{"HeatTemplateFormatVersion" : "2012-12-12",'
|
||||
'"Resources":{'
|
||||
'"A": {"Type": "GenericResourceType"},'
|
||||
'"B": {"Type": "GenericResourceType"}}}')
|
||||
tpl = {'Resources':
|
||||
tpl = {'HeatTemplateFormatVersion': "2012-12-12",
|
||||
'Resources':
|
||||
{'A': {'Type': 'AWS::CloudFormation::Stack',
|
||||
'Properties':
|
||||
{'TemplateURL': 'http://server.test/nested.json'}},
|
||||
|
@ -92,6 +92,7 @@ class ProviderTemplateTest(HeatTestCase):
|
||||
def test_to_parameters(self):
|
||||
"""Tests property conversion to parameter values."""
|
||||
provider = {
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Parameters': {
|
||||
'Foo': {'Type': 'String'},
|
||||
'AList': {'Type': 'CommaDelimitedList'},
|
||||
@ -163,6 +164,7 @@ class ProviderTemplateTest(HeatTestCase):
|
||||
|
||||
def test_attributes_extra(self):
|
||||
provider = {
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Outputs': {
|
||||
'Foo': {'Value': 'bar'},
|
||||
'Blarg': {'Value': 'wibble'},
|
||||
@ -221,6 +223,7 @@ class ProviderTemplateTest(HeatTestCase):
|
||||
|
||||
def test_properties_normal(self):
|
||||
provider = {
|
||||
'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Parameters': {
|
||||
'Foo': {'Type': 'String'},
|
||||
'Blarg': {'Type': 'String', 'Default': 'wibble'},
|
||||
@ -417,7 +420,9 @@ class ProviderTemplateTest(HeatTestCase):
|
||||
parser.Template({}),
|
||||
stack_id=str(uuid.uuid4()))
|
||||
|
||||
minimal_temp = json.dumps({'Parameters': {}, 'Resources': {}})
|
||||
minimal_temp = json.dumps({'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Parameters': {},
|
||||
'Resources': {}})
|
||||
self.m.StubOutWithMock(urlfetch, "get")
|
||||
urlfetch.get(test_templ_name,
|
||||
allowed_schemes=('http', 'https',
|
||||
|
@ -35,6 +35,7 @@ ws_res_snippet = {"Type": "some_magic_type",
|
||||
|
||||
param_template = '''
|
||||
{
|
||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||
"Parameters" : {
|
||||
"KeyName" : {
|
||||
"Description" : "KeyName",
|
||||
@ -54,6 +55,7 @@ param_template = '''
|
||||
|
||||
simple_template = '''
|
||||
{
|
||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||
"Parameters" : {},
|
||||
"Resources" : {
|
||||
"WebServer": {
|
||||
|
@ -60,8 +60,6 @@ class JsonToYamlTest(HeatTestCase):
|
||||
del(yml[u'HeatTemplateFormatVersion'])
|
||||
|
||||
jsn = template_format.parse(json_str)
|
||||
template_format.default_for_missing(jsn, 'AWSTemplateFormatVersion',
|
||||
template_format.CFN_VERSIONS)
|
||||
|
||||
if u'AWSTemplateFormatVersion' in jsn:
|
||||
del(jsn[u'AWSTemplateFormatVersion'])
|
||||
@ -81,18 +79,6 @@ class JsonToYamlTest(HeatTestCase):
|
||||
|
||||
class YamlMinimalTest(HeatTestCase):
|
||||
|
||||
def test_minimal_yaml(self):
|
||||
yaml1 = ''
|
||||
yaml2 = '''HeatTemplateFormatVersion: '2012-12-12'
|
||||
Parameters: {}
|
||||
Mappings: {}
|
||||
Resources: {}
|
||||
Outputs: {}
|
||||
'''
|
||||
tpl1 = template_format.parse(yaml1)
|
||||
tpl2 = template_format.parse(yaml2)
|
||||
self.assertEqual(tpl1, tpl2)
|
||||
|
||||
def test_long_yaml(self):
|
||||
template = {'HeatTemplateVersion': '2012-12-12'}
|
||||
config.cfg.CONF.set_override('max_template_size', 1024)
|
||||
@ -105,6 +91,16 @@ Outputs: {}
|
||||
msg = 'Request limit exceeded: Template exceeds maximum allowed size.'
|
||||
self.assertEqual(msg, str(ex))
|
||||
|
||||
def test_parse_no_version_format(self):
|
||||
yaml = ''
|
||||
self.assertRaises(ValueError, template_format.parse, yaml)
|
||||
yaml2 = '''Parameters: {}
|
||||
Mappings: {}
|
||||
Resources: {}
|
||||
Outputs: {}
|
||||
'''
|
||||
self.assertRaises(ValueError, template_format.parse, yaml2)
|
||||
|
||||
|
||||
class YamlParseExceptions(HeatTestCase):
|
||||
|
||||
@ -143,13 +139,9 @@ class JsonYamlResolvedCompareTest(HeatTestCase):
|
||||
|
||||
def compare_stacks(self, json_file, yaml_file, parameters):
|
||||
t1 = self.load_template(json_file)
|
||||
template_format.default_for_missing(t1, 'AWSTemplateFormatVersion',
|
||||
template_format.CFN_VERSIONS)
|
||||
del(t1[u'AWSTemplateFormatVersion'])
|
||||
|
||||
t2 = self.load_template(yaml_file)
|
||||
del(t2[u'HeatTemplateFormatVersion'])
|
||||
|
||||
del(t1[u'AWSTemplateFormatVersion'])
|
||||
stack1 = utils.parse_stack(t1, parameters)
|
||||
stack2 = utils.parse_stack(t2, parameters)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user