Reuse existing disable_rollback in stack-update

This patch makes `stack-update` command to change the `disable_rollback`
bit of the stack IF AND ONLY IF explicitly requested on CLI.

In order to facilitate this, `--rollback` CLI argument to `stack-update`
is added (accepting values from 1, on, true, t, 0, off, false, f and similar)
to explicitly set disable_rollback property of the stack on stack update.
If this argument is omitted, the value of disable_rollback
of the stack to be updated will be implicitly used by heat engine.

The boolean switch '--enable-rollback' is deprecated with appropriate
message (although the default behavior is effectively changed).

Change-Id: I235198ec04bfb192fcbfa4e2e3e618b64c99d3df
Closes-Bug: #1324366
This commit is contained in:
Pavlo Shchelokovskyy 2014-05-29 16:22:03 +03:00
parent 95841b5633
commit 847a8fd566
2 changed files with 141 additions and 8 deletions

View File

@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import re
import six
@ -1085,6 +1086,7 @@ class ShellTestUserPass(ShellBase):
'stack-update teststack2/2 '
'--template-file=%s '
'--timeout 123 '
'--rollback off '
'--parameters="InstanceType=m1.large;DBUsername=wp;'
'DBPassword=verybadpassword;KeyName=heat_key;'
'LinuxDistribution=F17"' % template_file)
@ -1228,8 +1230,17 @@ class ShellTestUserPass(ShellBase):
self.shell_error('stack-adopt teststack ', failed_msg)
@httpretty.activate
def test_stack_update(self):
def test_stack_update_enable_rollback(self):
self.register_keystone_auth_fixture()
template_file = os.path.join(TEST_VAR_DIR, 'minimal.template')
with open(template_file) as f:
template_data = json.load(f)
expected_data = {'files': {},
'environment': {},
'template': template_data,
'disable_rollback': False,
'parameters': mox.IgnoreArg()
}
resp = fakes.FakeHTTPResponse(
202,
'Accepted',
@ -1237,18 +1248,16 @@ class ShellTestUserPass(ShellBase):
'The request is accepted for processing.')
http.HTTPClient.json_request(
'PUT', '/stacks/teststack2/2',
data=mox.IgnoreArg(),
data=expected_data,
headers={'X-Auth-Key': 'password', 'X-Auth-User': 'username'}
).AndReturn((resp, None))
fakes.script_heat_list()
self.m.ReplayAll()
template_file = os.path.join(TEST_VAR_DIR, 'minimal.template')
update_text = self.shell(
'stack-update teststack2/2 '
'--rollback on '
'--template-file=%s '
'--enable-rollback '
'--parameters="InstanceType=m1.large;DBUsername=wp;'
'DBPassword=verybadpassword;KeyName=heat_key;'
'LinuxDistribution=F17"' % template_file)
@ -1262,6 +1271,99 @@ class ShellTestUserPass(ShellBase):
for r in required:
self.assertRegexpMatches(update_text, r)
@httpretty.activate
def test_stack_update_disable_rollback(self):
self.register_keystone_auth_fixture()
template_file = os.path.join(TEST_VAR_DIR, 'minimal.template')
with open(template_file) as f:
template_data = json.load(f)
expected_data = {'files': {},
'environment': {},
'template': template_data,
'disable_rollback': True,
'parameters': mox.IgnoreArg()
}
resp = fakes.FakeHTTPResponse(
202,
'Accepted',
{},
'The request is accepted for processing.')
http.HTTPClient.json_request(
'PUT', '/stacks/teststack2',
data=expected_data,
headers={'X-Auth-Key': 'password', 'X-Auth-User': 'username'}
).AndReturn((resp, None))
fakes.script_heat_list()
self.m.ReplayAll()
update_text = self.shell(
'stack-update teststack2 '
'--template-file=%s '
'--rollback off '
'--parameters="InstanceType=m1.large;DBUsername=wp;'
'DBPassword=verybadpassword;KeyName=heat_key;'
'LinuxDistribution=F17"' % template_file)
required = [
'stack_name',
'id',
'teststack2',
'1'
]
for r in required:
self.assertRegexpMatches(update_text, r)
@httpretty.activate
def test_stack_update_fault_rollback_value(self):
self.register_keystone_auth_fixture()
self.m.ReplayAll()
template_file = os.path.join(TEST_VAR_DIR, 'minimal.template')
self.shell_error('stack-update teststack2/2 '
'--rollback Foo '
'--template-file=%s' % template_file,
"Unrecognized value 'Foo', acceptable values are:"
)
@httpretty.activate
def test_stack_update_rollback_default(self):
self.register_keystone_auth_fixture()
template_file = os.path.join(TEST_VAR_DIR, 'minimal.template')
with open(template_file) as f:
template_data = json.load(f)
expected_data = {'files': {},
'environment': {},
'template': template_data,
'parameters': mox.IgnoreArg()
}
resp_update = fakes.FakeHTTPResponse(
202,
'Accepted',
{},
'The request is accepted for processing.')
http.HTTPClient.json_request(
'PUT', '/stacks/teststack2',
data=expected_data,
headers={'X-Auth-Key': 'password', 'X-Auth-User': 'username'}
).AndReturn((resp_update, None))
fakes.script_heat_list()
self.m.ReplayAll()
update_text = self.shell(
'stack-update teststack2 '
'--template-file=%s '
'--parameters="InstanceType=m1.large;DBUsername=wp;'
'DBPassword=verybadpassword;KeyName=heat_key;'
'LinuxDistribution=F17"' % template_file)
required = [
'stack_name',
'id',
'teststack2',
'2'
]
for r in required:
self.assertRegexpMatches(update_text, r)
@httpretty.activate
def test_stack_delete(self):
self.register_keystone_auth_fixture()

View File

@ -21,6 +21,7 @@ import yaml
from heatclient.common import template_utils
from heatclient.common import utils
from heatclient.openstack.common import jsonutils
from heatclient.openstack.common import strutils
import heatclient.exc as exc
@ -347,7 +348,16 @@ def do_stack_show(hc, args):
type=int,
help='Stack update timeout in minutes.')
@utils.arg('-r', '--enable-rollback', default=False, action="store_true",
help='Enable rollback on create/update failure.')
help='DEPRECATED! Use --rollback argument instead. '
'Enable rollback on stack update failure. '
'NOTE: default behavior is now to use the rollback value '
'of existing stack.')
@utils.arg('--rollback', default=None, metavar='<VALUE>',
help='Set rollback on update failure. '
'Values %(true)s set rollback to enabled. '
'Values %(false)s set rollback to disabled. '
'Default is to use the value of existing stack to be updated.'
% {'true': strutils.TRUE_STRINGS, 'false': strutils.FALSE_STRINGS})
@utils.arg('-P', '--parameters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
help='Parameter values used to create the stack. '
'This can be specified multiple times, or once with parameters '
@ -374,7 +384,16 @@ def do_update(hc, args):
type=int,
help='Stack update timeout in minutes.')
@utils.arg('-r', '--enable-rollback', default=False, action="store_true",
help='Enable rollback on create/update failure.')
help='DEPRECATED! Use --rollback argument instead. '
'Enable rollback on stack update failure. '
'NOTE: default behavior is now to use the rollback value '
'of existing stack.')
@utils.arg('--rollback', default=None, metavar='<VALUE>',
help='Set rollback on update failure. '
'Values %(true)s set rollback to enabled. '
'Values %(false)s set rollback to disabled. '
'Default is to use the value of existing stack to be updated.'
% {'true': strutils.TRUE_STRINGS, 'false': strutils.FALSE_STRINGS})
@utils.arg('-P', '--parameters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
help='Parameter values used to create the stack. '
'This can be specified multiple times, or once with parameters '
@ -396,7 +415,6 @@ def do_stack_update(hc, args):
fields = {
'stack_id': args.id,
'disable_rollback': not(args.enable_rollback),
'parameters': utils.format_parameters(args.parameters),
'template': template,
'files': dict(list(tpl_files.items()) + list(env_files.items())),
@ -406,6 +424,19 @@ def do_stack_update(hc, args):
if args.timeout:
fields['timeout_mins'] = args.timeout
if args.rollback is not None:
try:
rollback = strutils.bool_from_string(args.rollback, strict=True)
except ValueError as ex:
raise exc.CommandError(six.text_type(ex))
else:
fields['disable_rollback'] = not(rollback)
# TODO(pshchelo): remove the following 'else' clause after deprecation
# period of --enable-rollback switch and assign -r shortcut to --rollback
else:
if args.enable_rollback:
fields['disable_rollback'] = False
hc.stacks.update(**fields)
do_stack_list(hc)