Update SSH client integration

- Add password to [ssh] tobiko.conf parameters.
- Add pkey to SSHClient connect parameters
- Allow to provide connect SSHClient connect parameters in
  ssh_client function
- Update ExectuteTest case

Change-Id: I9cfba84856cd4dcecd588e4b83f6ec9bbbe2fe12
This commit is contained in:
Federico Ressi 2019-05-29 06:13:02 +02:00
parent 10435b42cd
commit b4656b54c7
3 changed files with 39 additions and 27 deletions

View File

@ -26,5 +26,7 @@ def register_tobiko_options(conf):
cfg.StrOpt('key_file', default='~/.ssh/id_rsa',
help="Default SSH key to login to server instances"),
cfg.StrOpt('username', default='cirros',
help="Default username to login to server instances")
help="Default username to login to server instances"),
cfg.StrOpt('password', default='gocubsgo',
help="Default password to login to server instances"),
])

View File

@ -40,14 +40,17 @@ SSH_CONNECT_PARAMETERS = {
'username': str,
#: Used for password authentication; is also used for private key
# decryption if passphrase is not given
#: decryption if passphrase is not given
'password': str,
#: Used for decrypting private keys
'passphrase': str,
#: Private key to be used for authentication
'pkey': str,
#: The filename, or list of filenames, of optional private key(s) and/or
# certs to try for authentication
#: certs to try for authentication
'key_filename': str,
#: An optional timeout (in seconds) for the TCP connect
@ -57,7 +60,7 @@ SSH_CONNECT_PARAMETERS = {
'allow_agent': bool,
#: Set to False to disable searching for discoverable private key files in
# ~/.ssh/
#: ~/.ssh/
'look_for_keys': bool,
#: Set to True to turn on compression
@ -76,11 +79,11 @@ SSH_CONNECT_PARAMETERS = {
'gss_host': str,
#: Indicates whether or not the DNS is trusted to securely canonicalize the
# name of the host being connected to (default True).
#: name of the host being connected to (default True).
'gss_trust_dns': bool,
#: An optional timeout (in seconds) to wait for the SSH banner to be
# presented.
#: presented.
'banner_timeout': float,
#: An optional timeout (in seconds) to wait for an authentication response
@ -206,7 +209,7 @@ class SSHClientFixture(tobiko.SharedFixture):
while True:
timeout = deadline - now
LOG.debug("Logging in to %r... (time left %d seconds)", login,
timeout)
timeout)
try:
sock = self._open_proxy_sock()
client.connect(sock=sock, timeout=timeout, **parameters)
@ -302,7 +305,8 @@ class SSHClientManager(object):
def __init__(self):
self.clients = {}
def get_client(self, host, username=None, port=None, proxy_jump=None):
def get_client(self, host, username=None, port=None, proxy_jump=None,
**connect_parameters):
host_config = self.ssh_config.lookup(host)
hostname = host_config.hostname
port = port or host_config.port
@ -316,7 +320,7 @@ class SSHClientManager(object):
proxy_client = self.get_client(proxy_jump)
self.clients[host_key] = client = SSHClientFixture(
host=host, hostname=hostname, port=port, username=username,
proxy_client=proxy_client)
proxy_client=proxy_client, **connect_parameters)
return client
@property
@ -332,10 +336,10 @@ CLIENTS = SSHClientManager()
def ssh_client(host, port=None, username=None, proxy_jump=None,
manager=None):
manager=None, **connect_parameters):
manager = manager or CLIENTS
return manager.get_client(host=host, port=port, username=username,
proxy_jump=proxy_jump)
proxy_jump=proxy_jump, **connect_parameters)
def ssh_proxy_client(manager=None):

View File

@ -27,10 +27,18 @@ from tobiko.shell import sh
CONF = config.CONF
class ExecuteTest(testtools.TestCase):
class LocalExecuteTest(testtools.TestCase):
ssh_client = None
shell = '/bin/sh -c'
def execute(self, command, **kwargs):
kwargs.setdefault('shell', self.shell)
kwargs.setdefault('ssh_client', self.ssh_client)
return sh.execute(command, **kwargs)
def test_execute_string(self):
result = sh.execute('true', shell='/bin/sh -c')
result = self.execute('true')
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'true'],
@ -38,7 +46,7 @@ class ExecuteTest(testtools.TestCase):
result)
def test_execute_list(self):
result = sh.execute(['echo', 'something'], shell='/bin/sh -c')
result = self.execute(['echo', 'something'])
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'echo something'],
@ -46,7 +54,7 @@ class ExecuteTest(testtools.TestCase):
result)
def test_execute_writing_to_stdout(self):
result = sh.execute('echo something', shell='/bin/sh -c')
result = self.execute('echo something')
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'echo something'],
@ -54,7 +62,7 @@ class ExecuteTest(testtools.TestCase):
result)
def test_execute_writing_to_stderr(self):
result = sh.execute('echo something >&2', shell='/bin/sh -c')
result = self.execute('echo something >&2')
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'echo something >&2'],
@ -62,7 +70,7 @@ class ExecuteTest(testtools.TestCase):
result)
def test_execute_reading_from_stdin(self):
result = sh.execute('cat', shell='/bin/sh -c', stdin='some input\n')
result = self.execute('cat', stdin='some input\n')
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'cat'],
@ -71,16 +79,15 @@ class ExecuteTest(testtools.TestCase):
result)
def test_execute_failing_command(self):
ex = self.assertRaises(sh.ShellCommandFailed, sh.execute, 'exit 15',
shell='/bin/sh -c')
ex = self.assertRaises(sh.ShellCommandFailed, self.execute, 'exit 15')
self.assertEqual('', ex.stdout)
self.assertEqual('', ex.stderr)
self.assertEqual(15, ex.exit_status)
self.assertEqual(['/bin/sh', '-c', 'exit 15'], ex.command)
def test_execute_failing_command_writing_to_stdout(self):
ex = self.assertRaises(sh.ShellCommandFailed, sh.execute,
'echo something; exit 8', shell='/bin/sh -c')
ex = self.assertRaises(sh.ShellCommandFailed, self.execute,
'echo something; exit 8')
self.assertEqual('something\n', ex.stdout)
self.assertEqual('', ex.stderr)
self.assertEqual(8, ex.exit_status)
@ -88,9 +95,8 @@ class ExecuteTest(testtools.TestCase):
ex.command)
def test_execute_failing_command_writing_to_stderr(self):
ex = self.assertRaises(sh.ShellCommandFailed, sh.execute,
'echo something >&2; exit 7',
shell='/bin/sh -c')
ex = self.assertRaises(sh.ShellCommandFailed, self.execute,
'echo something >&2; exit 7')
self.assertEqual('', ex.stdout)
self.assertEqual('something\n', ex.stderr)
self.assertEqual(7, ex.exit_status)
@ -100,7 +106,7 @@ class ExecuteTest(testtools.TestCase):
@unittest.skipIf(sys.version_info < (3, 3),
'timeout not implemented for Python version < 3.3')
def test_execute_with_timeout(self):
result = sh.execute('true', timeout=30., shell='/bin/sh -c')
result = self.execute('true', timeout=30.)
self.assertEqual(
sh.ShellExecuteResult(
command=['/bin/sh', '-c', 'true'],
@ -111,9 +117,9 @@ class ExecuteTest(testtools.TestCase):
@unittest.skipIf(sys.version_info < (3, 3),
'timeout not implemented for Python version < 3.3')
def test_execute_with_timeout_expired(self):
ex = self.assertRaises(sh.ShellTimeoutExpired, sh.execute,
ex = self.assertRaises(sh.ShellTimeoutExpired, self.execute,
'echo out; echo err >&2; sleep 30',
timeout=.01, shell='/bin/sh -c')
timeout=.01)
self.assertEqual(['/bin/sh', '-c',
'echo out; echo err >&2; sleep 30'],
ex.command)