Add a user confirmation to node delete
Node delete is a destructive action and we should prompt a user to confirm they want to do this action. We also added a --yes parameter to skip this confirmation prompt. Change-Id: If4a82977e2351fd3a9e0241eee60cb3719ef43c0
This commit is contained in:
parent
869832a635
commit
2b3b7f1e1f
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added a y/n prompt to the node delete command to prevent a user from
|
||||||
|
accidently executing a node delete action since it's a destructive
|
||||||
|
action.
|
|
@ -20,6 +20,7 @@ import mock
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
from osc_lib import exceptions as oscexc
|
||||||
from osc_lib.tests import utils as test_utils
|
from osc_lib.tests import utils as test_utils
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ class TestDeleteNode(fakes.TestDeleteNode):
|
||||||
# probably be fixed so that it can pass with that.
|
# probably be fixed so that it can pass with that.
|
||||||
def test_node_delete(self):
|
def test_node_delete(self):
|
||||||
argslist = ['instance1', 'instance2', '--templates',
|
argslist = ['instance1', 'instance2', '--templates',
|
||||||
'--stack', 'overcast', '--timeout', '90']
|
'--stack', 'overcast', '--timeout', '90', '--yes']
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('stack', 'overcast'),
|
('stack', 'overcast'),
|
||||||
('nodes', ['instance1', 'instance2'])
|
('nodes', ['instance1', 'instance2'])
|
||||||
|
@ -82,9 +83,24 @@ class TestDeleteNode(fakes.TestDeleteNode):
|
||||||
'timeout': 90
|
'timeout': 90
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
||||||
|
return_value=False)
|
||||||
|
def test_node_delete_no_confirm(self, confirm_mock):
|
||||||
|
argslist = ['instance1', 'instance2', '--templates',
|
||||||
|
'--stack', 'overcast', '--timeout', '90']
|
||||||
|
verifylist = [
|
||||||
|
('stack', 'overcast'),
|
||||||
|
('nodes', ['instance1', 'instance2'])
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(oscexc.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
def test_node_wrong_stack(self):
|
def test_node_wrong_stack(self):
|
||||||
argslist = ['instance1', '--templates',
|
argslist = ['instance1', '--templates',
|
||||||
'--stack', 'overcast']
|
'--stack', 'overcast', '--yes']
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('stack', 'overcast'),
|
('stack', 'overcast'),
|
||||||
('nodes', ['instance1', ])
|
('nodes', ['instance1', ])
|
||||||
|
@ -102,7 +118,7 @@ class TestDeleteNode(fakes.TestDeleteNode):
|
||||||
|
|
||||||
def test_node_delete_without_stack(self):
|
def test_node_delete_without_stack(self):
|
||||||
|
|
||||||
arglist = ['instance1', ]
|
arglist = ['instance1', '--yes']
|
||||||
|
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('stack', 'overcloud'),
|
('stack', 'overcloud'),
|
||||||
|
@ -130,7 +146,7 @@ class TestDeleteNode(fakes.TestDeleteNode):
|
||||||
def test_node_delete_wrong_instance(self):
|
def test_node_delete_wrong_instance(self):
|
||||||
|
|
||||||
argslist = ['wrong_instance', '--templates',
|
argslist = ['wrong_instance', '--templates',
|
||||||
'--stack', 'overcloud']
|
'--stack', 'overcloud', '--yes']
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('stack', 'overcloud'),
|
('stack', 'overcloud'),
|
||||||
('nodes', ['wrong_instance']),
|
('nodes', ['wrong_instance']),
|
||||||
|
|
|
@ -17,6 +17,7 @@ import argparse
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from osc_lib import exceptions as oscexc
|
||||||
from osc_lib.i18n import _
|
from osc_lib.i18n import _
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -69,11 +70,24 @@ class DeleteNode(command.Command):
|
||||||
"Keep in mind that due to keystone session duration "
|
"Keep in mind that due to keystone session duration "
|
||||||
"that timeout has an upper bound of 4 hours ")
|
"that timeout has an upper bound of 4 hours ")
|
||||||
)
|
)
|
||||||
|
parser.add_argument('-y', '--yes',
|
||||||
|
help=_('Skip yes/no prompt (assume yes).'),
|
||||||
|
default=False,
|
||||||
|
action="store_true")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
self.log.debug("take_action(%s)" % parsed_args)
|
self.log.debug("take_action(%s)" % parsed_args)
|
||||||
clients = self.app.client_manager
|
clients = self.app.client_manager
|
||||||
|
|
||||||
|
if not parsed_args.yes:
|
||||||
|
confirm = oooutils.prompt_user_for_confirmation(
|
||||||
|
message=_("Are you sure you want to delete these overcloud "
|
||||||
|
"nodes [y/N]? "),
|
||||||
|
logger=self.log)
|
||||||
|
if not confirm:
|
||||||
|
raise oscexc.CommandError("Action not confirmed, exiting.")
|
||||||
|
|
||||||
orchestration_client = clients.orchestration
|
orchestration_client = clients.orchestration
|
||||||
|
|
||||||
stack = oooutils.get_stack(orchestration_client, parsed_args.stack)
|
stack = oooutils.get_stack(orchestration_client, parsed_args.stack)
|
||||||
|
|
Loading…
Reference in New Issue