From 7998ec89affef39f814b97050657e8aef5c7e43e Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Fri, 2 Oct 2015 10:33:03 +0100 Subject: [PATCH] Add PATCH support for stack-update --dry-run Previously we just passed the "existing" kwarg directly to the PUT, which was then ignored by the API, so PATCH update preview commands wouldn't work. Now heat supports PATCH preview_update_stack, we can revise this to use the PATCH method when appropriate. Requires this heat patch for --existing --dry-run to work when used together: https://review.openstack.org/#/c/230054 Change-Id: Ib07c0a83edfbef7a08b4af344850d0a791b7704d Closes-Bug: #1501207 --- heatclient/tests/unit/test_shell.py | 39 ++++++++++++++++++++++++----- heatclient/v1/stacks.py | 11 +++++--- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/heatclient/tests/unit/test_shell.py b/heatclient/tests/unit/test_shell.py index 0e4bf033..b7e3c03d 100644 --- a/heatclient/tests/unit/test_shell.py +++ b/heatclient/tests/unit/test_shell.py @@ -2315,7 +2315,7 @@ class ShellTestUserPass(ShellBase): for r in required: self.assertRegexpMatches(update_text, r) - def test_stack_update_dry_run(self): + def _setup_stubs_update_dry_run(self, template_file, existing=False): self.register_keystone_auth_fixture() resp_dict = {"stack": { @@ -2336,7 +2336,6 @@ class ShellTestUserPass(ShellBase): self.client.json_request( 'GET', '/stacks/teststack2/2').AndReturn((resp, resp_dict)) - template_file = os.path.join(TEST_VAR_DIR, 'minimal.template') template_data = open(template_file).read() replaced_res = {"resource_name": "my_res", @@ -2375,22 +2374,50 @@ class ShellTestUserPass(ShellBase): 'environment': {}, 'template': jsonutils.loads(template_data), 'parameters': {'"KeyPairName': 'updated_key"'}, - 'disable_rollback': False, - 'existing': True} + 'disable_rollback': False} + + if existing is True: + method = 'PATCH' + else: + method = 'PUT' if self.client == http.SessionClient: self.client.request( - '/stacks/teststack2/2/preview', 'PUT', + '/stacks/teststack2/2/preview', method, data=expected_data, headers={}).AndReturn(resp) else: http.HTTPClient.json_request( - 'PUT', '/stacks/teststack2/2/preview', + method, '/stacks/teststack2/2/preview', data=expected_data, headers={'X-Auth-Key': 'password', 'X-Auth-User': 'username'} ).AndReturn((resp, None)) self.m.ReplayAll() + def test_stack_update_dry_run(self): + template_file = os.path.join(TEST_VAR_DIR, 'minimal.template') + self._setup_stubs_update_dry_run(template_file) + update_preview_text = self.shell( + 'stack-update teststack2/2 ' + '--template-file=%s ' + '--enable-rollback ' + '--parameters="KeyPairName=updated_key" ' + '--dry-run ' % template_file) + + required = [ + 'stack_name', + 'id', + 'teststack2', + '2', + 'state', + 'replaced' + ] + for r in required: + self.assertRegexpMatches(update_preview_text, r) + + def test_stack_update_dry_run_patch(self): + template_file = os.path.join(TEST_VAR_DIR, 'minimal.template') + self._setup_stubs_update_dry_run(template_file, existing=True) update_preview_text = self.shell( 'stack-update teststack2/2 ' '--template-file=%s ' diff --git a/heatclient/v1/stacks.py b/heatclient/v1/stacks.py index 7ce25e04..28aa83ef 100644 --- a/heatclient/v1/stacks.py +++ b/heatclient/v1/stacks.py @@ -151,9 +151,14 @@ class StackManager(base.BaseManager): """Preview a stack update.""" s = self.get(stack_id) headers = self.client.credentials_headers() - resp = self.client.put('/stacks/%s/%s/preview' % - (s.stack_name, s.id), - data=kwargs, headers=headers) + if kwargs.pop('existing', None): + resp = self.client.patch('/stacks/%s/%s/preview' % + (s.stack_name, s.id), + data=kwargs, headers=headers) + else: + resp = self.client.put('/stacks/%s/%s/preview' % + (s.stack_name, s.id), + data=kwargs, headers=headers) body = utils.get_response_body(resp) return body