From 90fc4fe89e76e18df8831e1163c064eae76fbf69 Mon Sep 17 00:00:00 2001 From: Thomas Herve Date: Thu, 17 Mar 2016 16:03:08 +0100 Subject: [PATCH] Remove unknown parameters in patched update When updating a stack with the existing flag, we keep the parameters from the old template to be used against the new version. Sometimes parameters will get remove and won't make sense anymore, and keeping them would break update with a 'Parameter was not defined' error. This filters out such parameters so that the updates succeed. Change-Id: I6f2aa77da28d271dd001a137bb574b5470292f15 Closes-Bug: #1558610 --- heat/engine/service.py | 14 ++-- .../tests/engine/service/test_stack_update.py | 2 + .../functional/test_template_resource.py | 66 +++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/heat/engine/service.py b/heat/engine/service.py index 000ec6759b..67e1c4fa63 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -835,7 +835,7 @@ class EngineService(service.Service): # stack definition. If PARAM_EXISTING is specified, we merge # any environment provided into the existing one and attempt # to use the existing stack template, if one is not provided. - if args.get(rpc_api.PARAM_EXISTING, None): + if args.get(rpc_api.PARAM_EXISTING): existing_env = current_stack.env.user_env_as_dict() existing_params = existing_env[env_fmt.PARAMETERS] clear_params = set(args.get(rpc_api.PARAM_CLEAR_PARAMETERS, [])) @@ -872,12 +872,14 @@ class EngineService(service.Service): 'previous template stored')) msg = _('PATCH update to non-COMPLETE stack') raise exception.NotSupported(feature=msg) + tmpl = templatem.Template(new_template, files=new_files, + env=new_env) + for key in list(new_env.params.keys()): + if key not in tmpl.param_schemata(): + new_env.params.pop(key) else: - new_env = environment.Environment(params) - new_files = files - new_template = template - - tmpl = templatem.Template(new_template, files=new_files, env=new_env) + tmpl = templatem.Template(template, files=files, + env=environment.Environment(params)) max_resources = cfg.CONF.max_resources_per_stack if max_resources != -1 and len(tmpl[tmpl.RESOURCES]) > max_resources: diff --git a/heat/tests/engine/service/test_stack_update.py b/heat/tests/engine/service/test_stack_update.py index e33cd6ce94..766192eb88 100644 --- a/heat/tests/engine/service/test_stack_update.py +++ b/heat/tests/engine/service/test_stack_update.py @@ -149,6 +149,7 @@ class ServiceStackUpdateTest(common.HeatTestCase): stk.set_stack_user_project_id('1234') self.assertEqual({'KeyName': 'test'}, stk.t.env.params) + t['parameters']['newparam'] = {'type': 'number'} with mock.patch('heat.engine.stack.Stack') as mock_stack: stk.update = mock.Mock() mock_stack.load.return_value = stk @@ -187,6 +188,7 @@ class ServiceStackUpdateTest(common.HeatTestCase): self.assertEqual({'KeyName': 'test', 'removeme': 'foo'}, stk.t.env.params) + t['parameters']['newparam'] = {'type': 'number'} with mock.patch('heat.engine.stack.Stack') as mock_stack: stk.update = mock.Mock() mock_stack.load.return_value = stk diff --git a/heat_integrationtests/functional/test_template_resource.py b/heat_integrationtests/functional/test_template_resource.py index 9a3e833694..ebfd73e8a7 100644 --- a/heat_integrationtests/functional/test_template_resource.py +++ b/heat_integrationtests/functional/test_template_resource.py @@ -935,3 +935,69 @@ resources: stack_identifier, self.main_template_update, files={'resource.yaml': self.nested_templ_update}) + + +class TemplateResourceRemovedParamTest(functional_base.FunctionalTestsBase): + + main_template = ''' +heat_template_version: 2013-05-23 +parameters: + value1: + type: string + default: foo +resources: + my_resource: + type: resource.yaml + properties: + value1: {get_param: value1} +''' + nested_templ = ''' +heat_template_version: 2013-05-23 +parameters: + value1: + type: string + default: foo +resources: + test: + type: OS::Heat::TestResource + properties: + value: {get_param: value1} +''' + main_template_update = ''' +heat_template_version: 2013-05-23 +resources: + my_resource: + type: resource.yaml +''' + nested_templ_update = ''' +heat_template_version: 2013-05-23 +parameters: + value1: + type: string + default: foo + value2: + type: string + default: bar +resources: + test: + type: OS::Heat::TestResource + properties: + value: + str_replace: + template: VAL1-VAL2 + params: + VAL1: {get_param: value1} + VAL2: {get_param: value2} +''' + + def test_update(self): + stack_identifier = self.stack_create( + template=self.main_template, + environment={'parameters': {'value1': 'spam'}}, + files={'resource.yaml': self.nested_templ}) + + self.update_stack( + stack_identifier, + self.main_template_update, + environment={'parameter_defaults': {'value2': 'egg'}}, + files={'resource.yaml': self.nested_templ_update}, existing=True)