From aee10997ac1b821b30ca9812d51ced8661da0d2b Mon Sep 17 00:00:00 2001 From: Jason Dunsmore Date: Mon, 29 Aug 2016 14:44:06 -0500 Subject: [PATCH] Move CFN pseudo functions out of Parameters base class And create a CfnParameters class, similar to HOTParameters. Change-Id: I5e71ce9affb8188b696c12e9f008678ce08a913c --- heat/engine/cfn/parameters.py | 52 +++++++++++++++++++++++++++++ heat/engine/cfn/template.py | 7 ++-- heat/engine/parameters.py | 19 ++++++----- heat/tests/test_engine_api_utils.py | 4 +-- heat/tests/test_hot.py | 26 +++++++-------- heat/tests/test_template.py | 4 +-- 6 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 heat/engine/cfn/parameters.py diff --git a/heat/engine/cfn/parameters.py b/heat/engine/cfn/parameters.py new file mode 100644 index 0000000000..55d5082a4a --- /dev/null +++ b/heat/engine/cfn/parameters.py @@ -0,0 +1,52 @@ +# +# 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.common.i18n import _ +from heat.engine import constraints as constr +from heat.engine import parameters + + +class CfnParameters(parameters.Parameters): + PSEUDO_PARAMETERS = ( + PARAM_STACK_ID, PARAM_STACK_NAME, PARAM_REGION + ) = ( + 'AWS::StackId', 'AWS::StackName', 'AWS::Region' + ) + + def _pseudo_parameters(self, stack_identifier): + stack_id = (stack_identifier.arn() + if stack_identifier is not None else 'None') + stack_name = stack_identifier and stack_identifier.stack_name + + yield parameters.Parameter( + self.PARAM_STACK_ID, + parameters.Schema(parameters.Schema.STRING, _('Stack ID'), + default=str(stack_id))) + if stack_name: + yield parameters.Parameter( + self.PARAM_STACK_NAME, + parameters.Schema(parameters.Schema.STRING, _('Stack Name'), + default=stack_name)) + yield parameters.Parameter( + self.PARAM_REGION, + parameters.Schema(parameters.Schema.STRING, + default='ap-southeast-1', + constraints=[ + constr.AllowedValues( + ['us-east-1', + 'us-west-1', + 'us-west-2', + 'sa-east-1', + 'eu-west-1', + 'ap-southeast-1', + 'ap-northeast-1'])])) diff --git a/heat/engine/cfn/template.py b/heat/engine/cfn/template.py index afb2f55b84..476b66c7b8 100644 --- a/heat/engine/cfn/template.py +++ b/heat/engine/cfn/template.py @@ -18,6 +18,7 @@ import six from heat.common import exception from heat.common.i18n import _ from heat.engine.cfn import functions as cfn_funcs +from heat.engine.cfn import parameters as cfn_params from heat.engine import function from heat.engine import parameters from heat.engine import rsrc_defn @@ -105,9 +106,9 @@ class CfnTemplateBase(template_common.CommonTemplate): return section def parameters(self, stack_identifier, user_params, param_defaults=None): - return parameters.Parameters(stack_identifier, self, - user_params=user_params, - param_defaults=param_defaults) + return cfn_params.CfnParameters(stack_identifier, self, + user_params=user_params, + param_defaults=param_defaults) def resource_definitions(self, stack): resources = self.t.get(self.RESOURCES) or {} diff --git a/heat/engine/parameters.py b/heat/engine/parameters.py index 00f097a871..04c6f852b7 100644 --- a/heat/engine/parameters.py +++ b/heat/engine/parameters.py @@ -11,8 +11,10 @@ # License for the specific language governing permissions and limitations # under the License. +import abc import collections import itertools +import warnings from oslo_serialization import jsonutils from oslo_utils import encodeutils @@ -472,6 +474,7 @@ class JsonParam(ParsedParameter): self.schema.validate_value(parsed, context=context, template=template) +@six.add_metaclass(abc.ABCMeta) class Parameters(collections.Mapping): """Parameters of a stack. @@ -479,12 +482,6 @@ class Parameters(collections.Mapping): the stack's template. """ - PSEUDO_PARAMETERS = ( - PARAM_STACK_ID, PARAM_STACK_NAME, PARAM_REGION - ) = ( - 'AWS::StackId', 'AWS::StackName', 'AWS::Region' - ) - def __init__(self, stack_identifier, tmpl, user_params=None, param_defaults=None): """Initialisation of the parameter. @@ -569,18 +566,22 @@ class Parameters(collections.Mapping): raise exception.UnknownUserParameter(key=param) def _pseudo_parameters(self, stack_identifier): + warnings.warn("Parameters._pseudo_parameters() is deprecated and " + "will become an abstract method in future. Subclasses " + "should override it to provide their own pseudo " + "parameters.", DeprecationWarning) stack_id = (stack_identifier.arn() if stack_identifier is not None else 'None') stack_name = stack_identifier and stack_identifier.stack_name - yield Parameter(self.PARAM_STACK_ID, + yield Parameter('AWS::StackId', Schema(Schema.STRING, _('Stack ID'), default=str(stack_id))) if stack_name: - yield Parameter(self.PARAM_STACK_NAME, + yield Parameter('AWS::StackName', Schema(Schema.STRING, _('Stack Name'), default=stack_name)) - yield Parameter(self.PARAM_REGION, + yield Parameter('AWS::Region', Schema(Schema.STRING, default='ap-southeast-1', constraints=[ diff --git a/heat/tests/test_engine_api_utils.py b/heat/tests/test_engine_api_utils.py index 84f9322cc2..e635740a08 100644 --- a/heat/tests/test_engine_api_utils.py +++ b/heat/tests/test_engine_api_utils.py @@ -24,8 +24,8 @@ from heat.common import template_format from heat.common import timeutils as heat_timeutils from heat.db.sqlalchemy import models from heat.engine import api +from heat.engine.cfn import parameters as cfn_param from heat.engine import event -from heat.engine import parameters from heat.engine import stack as parser from heat.engine import template from heat.objects import event as event_object @@ -1033,7 +1033,7 @@ class FormatValidateParameterTest(common.HeatTestCase): t = template_format.parse(self.template % self.param) tmpl = template.Template(t) - tmpl_params = parameters.Parameters(None, tmpl) + tmpl_params = cfn_param.CfnParameters(None, tmpl) tmpl_params.validate(validate_value=False) param = tmpl_params.params[self.param_name] param_formated = api.format_validate_parameter(param) diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index 762dbcf096..43057acada 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -19,6 +19,7 @@ from heat.common import exception from heat.common import identifier from heat.common import template_format from heat.engine.cfn import functions as cfn_functions +from heat.engine.cfn import parameters as cfn_param from heat.engine import check_resource as cr from heat.engine import conditions from heat.engine import environment @@ -26,7 +27,6 @@ from heat.engine import function from heat.engine.hot import functions as hot_functions from heat.engine.hot import parameters as hot_param from heat.engine.hot import template as hot_template -from heat.engine import parameters from heat.engine import resource from heat.engine import resources from heat.engine import rsrc_defn @@ -2763,7 +2763,7 @@ class HOTParamValidatorTest(common.HeatTestCase): foo: bar ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual("Invalid key 'foo' for parameter (param1)", six.text_type(error)) @@ -2776,7 +2776,7 @@ class HOTParamValidatorTest(common.HeatTestCase): description: Hi! ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual("Missing parameter type for parameter: param1", six.text_type(error)) @@ -2789,7 +2789,7 @@ class HOTParamValidatorTest(common.HeatTestCase): type: Unicode ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid type (Unicode)", six.text_type(error)) @@ -2805,7 +2805,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid key 'allowed_valus' for parameter constraints", @@ -2821,7 +2821,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid parameter constraints for parameter param1, " @@ -2837,7 +2837,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid parameter constraints, expected a mapping", @@ -2854,7 +2854,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual("No constraint expressed", six.text_type(error)) @@ -2869,7 +2869,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid range constraint, expected a mapping", @@ -2886,7 +2886,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: 1 ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid key 'foo' for range constraint", six.text_type(error)) @@ -2902,7 +2902,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid length constraint, expected a mapping", @@ -2919,7 +2919,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "Invalid key 'foo' for length constraint", six.text_type(error)) @@ -2935,7 +2935,7 @@ class HOTParamValidatorTest(common.HeatTestCase): default: foo ''') error = self.assertRaises( - exception.InvalidSchemaError, parameters.Parameters, + exception.InvalidSchemaError, cfn_param.CfnParameters, "stack_testit", template.Template(hot_tpl)) self.assertEqual( "AllowedPattern must be a string", six.text_type(error)) diff --git a/heat/tests/test_template.py b/heat/tests/test_template.py index 4aa7c9b35f..a409d68483 100644 --- a/heat/tests/test_template.py +++ b/heat/tests/test_template.py @@ -23,12 +23,12 @@ from stevedore import extension from heat.common import exception from heat.common import template_format from heat.engine.cfn import functions as cfn_funcs +from heat.engine.cfn import parameters as cfn_p from heat.engine.cfn import template as cfn_t from heat.engine.clients.os import nova from heat.engine import environment from heat.engine import function from heat.engine.hot import template as hot_t -from heat.engine import parameters from heat.engine import rsrc_defn from heat.engine import stack from heat.engine import template @@ -888,7 +888,7 @@ class TemplateTest(common.HeatTestCase): tmpl = template.Template(parameter_template, env=env) stk = stack.Stack(self.ctx, 'test', tmpl) tmpl.env = environment.Environment({}) - stk.parameters = parameters.Parameters(stk.identifier(), tmpl) + stk.parameters = cfn_p.CfnParameters(stk.identifier(), tmpl) snippet = {"Ref": "foo"} self.assertRaises(exception.UserParameterMissing, self.resolve,