diff options
Diffstat (limited to 'openstackclient')
| -rw-r--r-- | openstackclient/compute/v2/server.py | 76 | ||||
| -rw-r--r-- | openstackclient/tests/unit/compute/v2/test_server.py | 50 |
2 files changed, 101 insertions, 25 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 5c603d04..76f5ffd8 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -4461,26 +4461,30 @@ class SshServer(command.Command): metavar='<server>', help=_('Server (name or ID)'), ) + # Deprecated during the Yoga cycle parser.add_argument( '--login', '-l', metavar='<login-name>', - help=_('Login name (ssh -l option)'), + help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( '--port', '-p', metavar='<port>', type=int, - help=_('Destination port (ssh -p option)'), + help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( '--identity', '-i', metavar='<keyfile>', - help=_('Private key file (ssh -i option)'), + help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( '--option', '-o', metavar='<config-options>', - help=_('Options in ssh_config(5) format (ssh -o option)'), + help=argparse.SUPPRESS, ) ip_group = parser.add_mutually_exclusive_group() ip_group.add_argument( @@ -4521,6 +4525,7 @@ class SshServer(command.Command): default='public', help=_('Use other IP address (public, private, etc)'), ) + # Deprecated during the Yoga cycle parser.add_argument( '-v', dest='verbose', @@ -4528,46 +4533,77 @@ class SshServer(command.Command): default=False, help=argparse.SUPPRESS, ) + parser.add_argument( + 'ssh_args', + nargs='*', + metavar='-- <standard ssh args>', + help=( + 'Any argument or option that ssh allows. ' + 'Use -- once between openstackclient args and SSH args.' + ), + ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute + server = utils.find_resource( compute_client.servers, parsed_args.server, ) - # Build the command - cmd = "ssh" + # first, handle the deprecated options + if any(( + parsed_args.port, + parsed_args.identity, + parsed_args.option, + parsed_args.login, + parsed_args.verbose, + )): + msg = _( + 'The ssh options have been deprecated. The ssh equivalent ' + 'options can be used instead as arguments after "--" on ' + 'the command line.' + ) + self.log.warning(msg) ip_address_family = [4, 6] if parsed_args.ipv4: ip_address_family = [4] - cmd += " -4" if parsed_args.ipv6: ip_address_family = [6] - cmd += " -6" + + args = parsed_args.ssh_args[:] if parsed_args.port: - cmd += " -p %d" % parsed_args.port + args.extend(['-p', str(parsed_args.port)]) + if parsed_args.identity: - cmd += " -i %s" % parsed_args.identity + args.extend(['-i', parsed_args.identity]) + if parsed_args.option: - cmd += " -o %s" % parsed_args.option + args.extend(['-o', parsed_args.option]) + if parsed_args.login: login = parsed_args.login - else: + args.extend(['-l', login]) + elif '-l' not in args: login = self.app.client_manager.auth_ref.username + args.extend(['-l', login]) + if parsed_args.verbose: - cmd += " -v" - - cmd += " %s@%s" - ip_address = _get_ip_address(server.addresses, - parsed_args.address_type, - ip_address_family) - LOG.debug("ssh command: %s", (cmd % (login, ip_address))) - os.system(cmd % (login, ip_address)) + args.append('-v') + + ip_address = _get_ip_address( + server.addresses, + parsed_args.address_type, + ip_address_family, + ) + + cmd = ' '.join(['ssh', ip_address] + args) + LOG.debug("ssh command: {cmd}".format(cmd=cmd)) + os.system(cmd) class StartServer(command.Command): diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index acff61e6..3f7ad04a 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -8307,15 +8307,48 @@ class TestServerSsh(TestServer): ('ipv6', False), ('address_type', 'public'), ('verbose', False), + ('ssh_args', []), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + with mock.patch.object(self.cmd.log, 'warning') as mock_warning: + result = self.cmd.take_action(parsed_args) + + self.assertIsNone(result) + mock_exec.assert_called_once_with('ssh 192.168.1.30 -l cloud') + mock_warning.assert_not_called() + + def test_server_ssh_passthrough_opts(self, mock_exec): + arglist = [ + self.server.name, + '--', + '-l', 'username', + '-p', '2222', + ] + verifylist = [ + ('server', self.server.name), + ('login', None), + ('port', None), + ('identity', None), + ('option', None), + ('ipv4', False), + ('ipv6', False), + ('address_type', 'public'), + ('verbose', False), + ('ssh_args', ['-l', 'username', '-p', '2222']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch.object(self.cmd.log, 'warning') as mock_warning: + result = self.cmd.take_action(parsed_args) self.assertIsNone(result) - mock_exec.assert_called_once_with('ssh cloud@192.168.1.30') + mock_exec.assert_called_once_with( + 'ssh 192.168.1.30 -l username -p 2222' + ) + mock_warning.assert_not_called() - def test_server_ssh_opts(self, mock_exec): + def test_server_ssh_deprecated_opts(self, mock_exec): arglist = [ self.server.name, '-l', 'username', @@ -8331,14 +8364,21 @@ class TestServerSsh(TestServer): ('ipv6', False), ('address_type', 'public'), ('verbose', False), + ('ssh_args', []), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + with mock.patch.object(self.cmd.log, 'warning') as mock_warning: + result = self.cmd.take_action(parsed_args) self.assertIsNone(result) mock_exec.assert_called_once_with( - 'ssh -p 2222 username@192.168.1.30' + 'ssh 192.168.1.30 -p 2222 -l username' + ) + mock_warning.assert_called_once() + self.assertIn( + 'The ssh options have been deprecated.', + mock_warning.call_args[0][0], ) |
