From ea6e95189f623911ed63c613055ad5b2baa647f8 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 5 Jun 2013 16:41:14 +0800 Subject: [PATCH] raise an UnknownUserParameter exception when receiving an unknown param add some validation logic to Parameters, so that when an invalid param is passed in an exception will be raised. Fixes bug #1186790 Change-Id: I8aece556d8fc5cd5533f4baf041e345bdc5722ec --- heat/api/aws/exception.py | 1 + heat/api/openstack/v1/util.py | 1 + heat/common/exception.py | 4 ++++ heat/engine/parameters.py | 8 ++++++++ heat/tests/test_api_cfn_v1.py | 15 +++++++++++++++ heat/tests/test_api_openstack_v1.py | 14 ++++++++++++++ heat/tests/test_nested_stack.py | 3 +++ heat/tests/test_parameters.py | 9 +++++++++ heat/tests/test_watch.py | 2 +- 9 files changed, 56 insertions(+), 1 deletion(-) diff --git a/heat/api/aws/exception.py b/heat/api/aws/exception.py index 44ed0ef2..462163c5 100644 --- a/heat/api/aws/exception.py +++ b/heat/api/aws/exception.py @@ -255,6 +255,7 @@ def map_remote_error(ex): 'StackExists', 'StackValidationFailed', 'InvalidTemplateReference', + 'UnknownUserParameter', ) denied_errors = ('Forbidden', 'NotAuthorized') diff --git a/heat/api/openstack/v1/util.py b/heat/api/openstack/v1/util.py index 7a38a4ad..f9666346 100644 --- a/heat/api/openstack/v1/util.py +++ b/heat/api/openstack/v1/util.py @@ -82,6 +82,7 @@ def remote_error(ex): 'StackExists': exc.HTTPConflict, 'StackValidationFailed': exc.HTTPBadRequest, 'InvalidTemplateReference': exc.HTTPBadRequest, + 'UnknownUserParameter': exc.HTTPBadRequest, } Exc = error_map.get(ex.exc_type, exc.HTTPInternalServerError) diff --git a/heat/common/exception.py b/heat/common/exception.py index 419685e1..b50c9921 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -191,6 +191,10 @@ class UserParameterMissing(OpenstackException): message = _("The Parameter (%(key)s) was not provided.") +class UnknownUserParameter(OpenstackException): + message = _("The Parameter (%(key)s) was not defined in template.") + + class InvalidTemplateAttribute(OpenstackException): message = _("The Referenced Attribute (%(resource)s %(key)s)" " is incorrect.") diff --git a/heat/engine/parameters.py b/heat/engine/parameters.py index 6b5af4fa..7ae8481e 100644 --- a/heat/engine/parameters.py +++ b/heat/engine/parameters.py @@ -16,6 +16,7 @@ import collections import re +from heat.common import exception from heat.engine import template PARAMETER_KEYS = ( @@ -246,6 +247,8 @@ class Parameters(collections.Mapping): for name, schema in tmpl[template.PARAMETERS].iteritems(): yield Parameter(name, schema, user_params.get(name)) + self.tmpl = tmpl + self._validate(user_params) self.params = dict((p.name, p) for p in parameters()) def __contains__(self, key): @@ -284,3 +287,8 @@ class Parameters(collections.Mapping): Set the AWS::StackId pseudo parameter value ''' self.params[PARAM_STACK_ID].schema[DEFAULT] = stack_id + + def _validate(self, user_params): + for param in user_params: + if param not in self.tmpl[template.PARAMETERS]: + raise exception.UnknownUserParameter(key=param) diff --git a/heat/tests/test_api_cfn_v1.py b/heat/tests/test_api_cfn_v1.py index 2b753aee..130d2682 100644 --- a/heat/tests/test_api_cfn_v1.py +++ b/heat/tests/test_api_cfn_v1.py @@ -540,6 +540,15 @@ class CfnStackControllerTest(HeatTestCase): 'args': engine_args}, 'version': self.api_version}, None ).AndRaise(rpc_common.RemoteError("AttributeError")) + rpc.call(dummy_req.context, self.topic, + {'namespace': None, + 'method': 'create_stack', + 'args': {'stack_name': stack_name, + 'template': template, + 'params': engine_parms, + 'args': engine_args}, + 'version': self.api_version}, None + ).AndRaise(rpc_common.RemoteError("UnknownUserParameter")) self.m.ReplayAll() @@ -547,6 +556,12 @@ class CfnStackControllerTest(HeatTestCase): self.assertEqual(type(result), exception.HeatInvalidParameterValueError) + + result = self.controller.create(dummy_req) + + self.assertEqual(type(result), + exception.HeatInvalidParameterValueError) + self.m.VerifyAll() def test_create_err_exists(self): diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py index c5db808d..b1e35b03 100644 --- a/heat/tests/test_api_openstack_v1.py +++ b/heat/tests/test_api_openstack_v1.py @@ -362,11 +362,25 @@ class StackControllerTest(ControllerTest, HeatTestCase): 'args': {'timeout_mins': 30}}, 'version': self.api_version}, None).AndRaise(rpc_common.RemoteError("AttributeError")) + rpc.call(req.context, self.topic, + {'namespace': None, + 'method': 'create_stack', + 'args': {'stack_name': stack_name, + 'template': template, + 'params': parameters, + 'args': {'timeout_mins': 30}}, + 'version': self.api_version}, + None).AndRaise(rpc_common.RemoteError("UnknownUserParameter")) + self.m.ReplayAll() self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, tenant_id=self.tenant, body=body) + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, + req, tenant_id=self.tenant, body=body) + self.m.VerifyAll() def test_create_err_existing(self): diff --git a/heat/tests/test_nested_stack.py b/heat/tests/test_nested_stack.py index 83f46de8..d9824981 100644 --- a/heat/tests/test_nested_stack.py +++ b/heat/tests/test_nested_stack.py @@ -37,6 +37,9 @@ Resources: nested_template = ''' HeatTemplateFormatVersion: '2012-12-12' +Parameters: + KeyName: + Type: String Outputs: Foo: Value: bar diff --git a/heat/tests/test_parameters.py b/heat/tests/test_parameters.py index bfa3672b..ffbc86e4 100644 --- a/heat/tests/test_parameters.py +++ b/heat/tests/test_parameters.py @@ -16,6 +16,7 @@ import testtools import json +from heat.common import exception from heat.engine import parameters @@ -338,3 +339,11 @@ class ParametersTest(testtools.TestCase): 'AWS::StackName': 'test_params'} self.assertEqual(params.map(str), expected) + + def test_unknown_params(self): + user_params = {'Foo': 'wibble'} + self.assertRaises(exception.UnknownUserParameter, + parameters.Parameters, + 'test', + params_schema, + user_params) diff --git a/heat/tests/test_watch.py b/heat/tests/test_watch.py index 12e1214e..92a536cf 100644 --- a/heat/tests/test_watch.py +++ b/heat/tests/test_watch.py @@ -52,7 +52,7 @@ class WatchRuleTest(HeatTestCase): empty_tmpl = {"template": {}} tmpl = parser.Template(empty_tmpl) stack_name = 'dummystack' - params = parser.Parameters(stack_name, tmpl, {'foo': 'bar'}) + params = parser.Parameters(stack_name, tmpl, {}) dummy_stack = parser.Stack(ctx, stack_name, tmpl, params) dummy_stack.state_set(dummy_stack.CREATE_COMPLETE, 'Testing') dummy_stack.store() -- 2.45.2