Give cfn a separate Template class
Change-Id: Iddeeef7e0303fcbf09fc936a96ec68dbccd5489e
This commit is contained in:
parent
00eb5295d1
commit
f7a52b5005
|
@ -0,0 +1,67 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from heat.engine import parameters
|
||||
from heat.engine import template
|
||||
from heat.engine.cfn import functions
|
||||
|
||||
|
||||
class CfnTemplate(template.Template):
|
||||
'''A stack template.'''
|
||||
|
||||
SECTIONS = (VERSION, DESCRIPTION, MAPPINGS,
|
||||
PARAMETERS, RESOURCES, OUTPUTS) = \
|
||||
('AWSTemplateFormatVersion', 'Description', 'Mappings',
|
||||
'Parameters', 'Resources', 'Outputs')
|
||||
|
||||
SECTIONS_NO_DIRECT_ACCESS = set([PARAMETERS, VERSION])
|
||||
|
||||
def __getitem__(self, section):
|
||||
'''Get the relevant section in the template.'''
|
||||
if section not in self.SECTIONS:
|
||||
raise KeyError(_('"%s" is not a valid template section') % section)
|
||||
if section in self.SECTIONS_NO_DIRECT_ACCESS:
|
||||
raise KeyError(
|
||||
_('Section %s can not be accessed directly.') % section)
|
||||
|
||||
if section == self.DESCRIPTION:
|
||||
default = 'No description'
|
||||
else:
|
||||
default = {}
|
||||
|
||||
return self.t.get(section, default)
|
||||
|
||||
def version(self):
|
||||
for key in ('HeatTemplateFormatVersion', 'AWSTemplateFormatVersion'):
|
||||
if key in self.t:
|
||||
return key, self.t[key]
|
||||
|
||||
# All user templates are forced to include a version string. This is
|
||||
# just a convenient default for unit tests.
|
||||
return 'HeatTemplateFormatVersion', '2012-12-12'
|
||||
|
||||
def param_schemata(self):
|
||||
params = self.t.get(self.PARAMETERS, {}).iteritems()
|
||||
return dict((name, parameters.Schema.from_dict(schema))
|
||||
for name, schema in params)
|
||||
|
||||
def parameters(self, stack_identifier, user_params, validate_value=True,
|
||||
context=None):
|
||||
return parameters.Parameters(stack_identifier, self,
|
||||
user_params=user_params,
|
||||
validate_value=validate_value,
|
||||
context=context)
|
||||
|
||||
def functions(self):
|
||||
return functions.function_mapping(*self.version())
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
from heat.common import exception
|
||||
from heat.engine import template
|
||||
from heat.engine.cfn import template as cfn_template
|
||||
from heat.engine import parameters
|
||||
from heat.engine import constraints as constr
|
||||
from heat.openstack.common.gettextutils import _
|
||||
|
@ -41,7 +42,7 @@ class HOTemplate(template.Template):
|
|||
"""
|
||||
|
||||
SECTIONS = (VERSION, DESCRIPTION, PARAMETER_GROUPS, PARAMETERS,
|
||||
RESOURCES, OUTPUTS, UNDEFINED) = \
|
||||
RESOURCES, OUTPUTS, MAPPINGS) = \
|
||||
('heat_template_version', 'description', 'parameter_groups',
|
||||
'parameters', 'resources', 'outputs', '__undefined__')
|
||||
|
||||
|
@ -49,12 +50,12 @@ class HOTemplate(template.Template):
|
|||
|
||||
VERSIONS = ('2013-05-23',)
|
||||
|
||||
_CFN_TO_HOT_SECTIONS = {template.Template.VERSION: VERSION,
|
||||
template.Template.DESCRIPTION: DESCRIPTION,
|
||||
template.Template.PARAMETERS: PARAMETERS,
|
||||
template.Template.MAPPINGS: UNDEFINED,
|
||||
template.Template.RESOURCES: RESOURCES,
|
||||
template.Template.OUTPUTS: OUTPUTS}
|
||||
_CFN_TO_HOT_SECTIONS = {cfn_template.CfnTemplate.VERSION: VERSION,
|
||||
cfn_template.CfnTemplate.DESCRIPTION: DESCRIPTION,
|
||||
cfn_template.CfnTemplate.PARAMETERS: PARAMETERS,
|
||||
cfn_template.CfnTemplate.MAPPINGS: MAPPINGS,
|
||||
cfn_template.CfnTemplate.RESOURCES: RESOURCES,
|
||||
cfn_template.CfnTemplate.OUTPUTS: OUTPUTS}
|
||||
|
||||
def __init__(self, template, *args, **kwargs):
|
||||
version = template[self.VERSION]
|
||||
|
@ -79,7 +80,7 @@ class HOTemplate(template.Template):
|
|||
raise KeyError(
|
||||
_('Section %s can not be accessed directly.') % section)
|
||||
|
||||
if section == self.UNDEFINED:
|
||||
if section == self.MAPPINGS:
|
||||
return {}
|
||||
|
||||
if section == self.DESCRIPTION:
|
||||
|
|
|
@ -13,36 +13,27 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
import collections
|
||||
import functools
|
||||
|
||||
from heat.db import api as db_api
|
||||
from heat.engine import parameters
|
||||
from heat.engine.cfn import functions
|
||||
from heat.openstack.common.gettextutils import _
|
||||
|
||||
|
||||
class Template(collections.Mapping):
|
||||
'''A stack template.'''
|
||||
|
||||
SECTIONS = (VERSION, DESCRIPTION, MAPPINGS,
|
||||
PARAMETERS, RESOURCES, OUTPUTS) = \
|
||||
('AWSTemplateFormatVersion', 'Description', 'Mappings',
|
||||
'Parameters', 'Resources', 'Outputs')
|
||||
|
||||
SECTIONS_NO_DIRECT_ACCESS = set([PARAMETERS, VERSION])
|
||||
|
||||
def __new__(cls, template, *args, **kwargs):
|
||||
'''Create a new Template of the appropriate class.'''
|
||||
|
||||
if cls == Template:
|
||||
# deferred module imports to avoid circular dependency
|
||||
if 'heat_template_version' in template:
|
||||
|
||||
# defer import of HOT module to avoid circular dependency
|
||||
# at load time
|
||||
from heat.engine import hot
|
||||
|
||||
return hot.HOTemplate(template, *args, **kwargs)
|
||||
else:
|
||||
from heat.engine.cfn import template as cfn
|
||||
return cfn.CfnTemplate(template, *args, **kwargs)
|
||||
|
||||
return super(Template, cls).__new__(cls)
|
||||
|
||||
|
@ -72,21 +63,6 @@ class Template(collections.Mapping):
|
|||
self.id = new_rt.id
|
||||
return self.id
|
||||
|
||||
def __getitem__(self, section):
|
||||
'''Get the relevant section in the template.'''
|
||||
if section not in self.SECTIONS:
|
||||
raise KeyError(_('"%s" is not a valid template section') % section)
|
||||
if section in self.SECTIONS_NO_DIRECT_ACCESS:
|
||||
raise KeyError(
|
||||
_('Section %s can not be accessed directly.') % section)
|
||||
|
||||
if section == self.DESCRIPTION:
|
||||
default = 'No description'
|
||||
else:
|
||||
default = {}
|
||||
|
||||
return self.t.get(section, default)
|
||||
|
||||
def __iter__(self):
|
||||
'''Return an iterator over the section names.'''
|
||||
return (s for s in self.SECTIONS
|
||||
|
@ -96,29 +72,26 @@ class Template(collections.Mapping):
|
|||
'''Return the number of sections.'''
|
||||
return len(self.SECTIONS) - len(self.SECTIONS_NO_DIRECT_ACCESS)
|
||||
|
||||
@abc.abstractmethod
|
||||
def version(self):
|
||||
for key in ('HeatTemplateFormatVersion', 'AWSTemplateFormatVersion'):
|
||||
if key in self.t:
|
||||
return key, self.t[key]
|
||||
|
||||
# All user templates are forced to include a version string. This is
|
||||
# just a convenient default for unit tests.
|
||||
return 'HeatTemplateFormatVersion', '2012-12-12'
|
||||
'''Return a (versionkey, version) tuple for the template.'''
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def param_schemata(self):
|
||||
params = self.t.get(self.PARAMETERS, {}).iteritems()
|
||||
return dict((name, parameters.Schema.from_dict(schema))
|
||||
for name, schema in params)
|
||||
'''Return a dict of parameters.Schema objects for the parameters.'''
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self, stack_identifier, user_params, validate_value=True,
|
||||
context=None):
|
||||
return parameters.Parameters(stack_identifier, self,
|
||||
user_params=user_params,
|
||||
validate_value=validate_value,
|
||||
context=context)
|
||||
'''Return a parameters.Parameters object for the stack.'''
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def functions(self):
|
||||
return functions.function_mapping(*self.version())
|
||||
'''Return a dict of template functions keyed by name.'''
|
||||
pass
|
||||
|
||||
def parse(self, stack, snippet):
|
||||
parse = functools.partial(self.parse, stack)
|
||||
|
|
|
@ -2608,7 +2608,7 @@ class StackServiceTest(HeatTestCase):
|
|||
|
||||
def test_validate_new_stack_checks_resource_limit(self):
|
||||
cfg.CONF.set_override('max_resources_per_stack', 5)
|
||||
template = {service.parser.Template.RESOURCES: [1, 2, 3, 4, 5, 6]}
|
||||
template = {'Resources': [1, 2, 3, 4, 5, 6]}
|
||||
parsed_template = service.parser.Template(template)
|
||||
self.assertRaises(exception.RequestLimitExceeded,
|
||||
self.eng._validate_new_stack,
|
||||
|
|
|
@ -1473,7 +1473,7 @@ class StackTest(HeatTestCase):
|
|||
self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
self.assertEqual('BTemplate',
|
||||
self.stack.t[template.Template.DESCRIPTION])
|
||||
self.stack.t[self.stack.t.DESCRIPTION])
|
||||
|
||||
@utils.stack_delete_after
|
||||
def test_update_modify_ok_replace(self):
|
||||
|
|
|
@ -177,7 +177,7 @@ class StackResourceTest(HeatTestCase):
|
|||
|
||||
def test__validate_nested_resources_checks_num_of_resources(self):
|
||||
stack_resource.cfg.CONF.set_override('max_resources_per_stack', 2)
|
||||
tmpl = {stack_resource.parser.Template.RESOURCES: [1]}
|
||||
tmpl = {'Resources': [1]}
|
||||
template = stack_resource.parser.Template(tmpl)
|
||||
root_resources = mock.Mock(return_value=2)
|
||||
self.parent_resource.stack.root_stack.total_resources = root_resources
|
||||
|
|
Loading…
Reference in New Issue