diff --git a/releasenotes/notes/upgrade_prompt-405c4f9fe3b4764c.yaml b/releasenotes/notes/upgrade_prompt-405c4f9fe3b4764c.yaml new file mode 100644 index 000000000..618a79c21 --- /dev/null +++ b/releasenotes/notes/upgrade_prompt-405c4f9fe3b4764c.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Prompt the operator before running the upgrades and suggest to perform a backup + before. Can be ignored with -y/--yes. diff --git a/tripleoclient/tests/v1/tripleo/test_tripleo_upgrade.py b/tripleoclient/tests/v1/tripleo/test_tripleo_upgrade.py index e142bc54a..4eda5625d 100644 --- a/tripleoclient/tests/v1/tripleo/test_tripleo_upgrade.py +++ b/tripleoclient/tests/v1/tripleo/test_tripleo_upgrade.py @@ -16,6 +16,7 @@ import mock from osc_lib.tests import utils +import six # Load the plugin init module for the plugin list and show commands from tripleoclient.v1 import tripleo_upgrade @@ -60,3 +61,48 @@ class TestUpgrade(utils.TestCommand): parsed_args.standlone = True parsed_args.upgrade = True mock_deploy.assert_called_with(self.cmd, parsed_args) + + @mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.take_action', + autospec=True) + @mock.patch('sys.stdin', spec=six.StringIO) + def test_take_action_prompt(self, mock_stdin, mock_deploy): + mock_stdin.isatty.return_value = True + mock_stdin.readline.return_value = 'y' + parsed_args = self.check_parser(self.cmd, + ['--local-ip', '127.0.0.1', + '--templates', '/tmp/thtroot', + '--stack', 'undercloud', + '--output-dir', '/my', + '-e', '/tmp/thtroot/puppet/foo.yaml', + '-e', '/tmp/thtroot//docker/bar.yaml', + '-e', '/tmp/thtroot42/notouch.yaml', + '-e', '~/custom.yaml', + '-e', 'something.yaml', + '-e', '../../../outside.yaml'], []) + self.cmd.take_action(parsed_args) + parsed_args.standlone = True + parsed_args.upgrade = True + mock_deploy.assert_called_with(self.cmd, parsed_args) + + @mock.patch('tripleoclient.v1.tripleo_deploy.Deploy', + autospec=True) + @mock.patch('sys.stdin', spec=six.StringIO) + def test_take_action_prompt_no(self, mock_stdin, mock_deploy): + mock_stdin.isatty.return_value = True + mock_stdin.readline.return_value = 'n' + parsed_args = self.check_parser(self.cmd, + ['--local-ip', '127.0.0.1', + '--templates', '/tmp/thtroot', + '--stack', 'undercloud', + '--output-dir', '/my', + '-e', '/tmp/thtroot/puppet/foo.yaml', + '-e', '/tmp/thtroot//docker/bar.yaml', + '-e', '/tmp/thtroot42/notouch.yaml', + '-e', '~/custom.yaml', + '-e', 'something.yaml', + '-e', '../../../outside.yaml'], []) + self.cmd.take_action(parsed_args) + parsed_args.standlone = True + parsed_args.upgrade = True + mock_stdin.readline.assert_called_with() + mock_deploy.assert_not_called() diff --git a/tripleoclient/v1/tripleo_deploy.py b/tripleoclient/v1/tripleo_deploy.py index 2ae5cd741..e3f5eb891 100644 --- a/tripleoclient/v1/tripleo_deploy.py +++ b/tripleoclient/v1/tripleo_deploy.py @@ -554,6 +554,8 @@ class Deploy(command.Command): "with no undercloud.")) parser.add_argument('--upgrade', default=False, action='store_true', help=_("Upgrade an existing deployment.")) + parser.add_argument('-y', '--yes', default=False, action='store_true', + help=_("Skip yes/no prompt (assume yes).")) parser.add_argument('--stack', help=_("Stack name to create"), default='undercloud') @@ -782,6 +784,27 @@ class Deploy(command.Command): def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) + try: + if parsed_args.upgrade and ( + not parsed_args.yes and sys.stdin.isatty()): + prompt_response = six.moves.input( + ('It is strongly recommended to perform a backup ' + 'before the upgrade. Are you sure you want to ' + 'upgrade [y/N]?') + ).lower() + if not prompt_response.startswith('y'): + self.log.info('User did not confirm upgrade so ' + 'taking no action.') + return + except KeyboardInterrupt: # ctrl-c + self.log.info('User did not confirm upgrade ' + '(ctrl-c) so taking no action.') + return + except EOFError: # ctrl-d + self.log.info('User did not confirm upgrade ' + '(ctrl-d) so taking no action.') + return + if parsed_args.standalone: if self._standalone_deploy(parsed_args) != 0: msg = _('Deployment failed.')