Skip to content

Commit 332273a

Browse files
dis-xcompenguinolog
authored andcommitted
Allow to disable printing expected runtime errors in SSHAuth (#49)
When users on a node are not prepared yet, it is expected to get wrong authorization exception like this: ssh_client.py:147 -- Connection using stored authentication info failed! Traceback (most recent call last): ... BadAuthenticationType: ('Bad authentication type', [u'publickey']) (allowed_types=[u'publickey']) - new parameter to SSHClient 'verbose' allows to disable printing such errors during waiting for ssh access.
1 parent 344b810 commit 332273a

File tree

4 files changed

+33
-5
lines changed

4 files changed

+33
-5
lines changed

doc/source/SSHClient.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ API: SSHClient and SSHAuth.
2424
:type private_keys: ``typing.Optional[typing.Iterable[paramiko.RSAKey]]``
2525
:param auth: credentials for connection
2626
:type auth: typing.Optional[SSHAuth]
27+
:param verbose: show additional error/warning messages
28+
:type verbose: bool
2729

2830
.. note:: auth has priority over username/password/private_keys
2931

exec_helpers/_ssh_client_base.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def __call__(
116116
password=None, # type: typing.Optional[str]
117117
private_keys=None, # type: typing.Optional[typing.Iterable[paramiko.RSAKey]]
118118
auth=None, # type: typing.Optional[ssh_auth.SSHAuth]
119+
verbose=True, # type: bool
119120
): # type: (...) -> SSHClientBase
120121
"""Main memorize method: check for cached instance and return it.
121122
@@ -125,6 +126,7 @@ def __call__(
125126
:type password: str
126127
:type private_keys: list
127128
:type auth: ssh_auth.SSHAuth
129+
:type verbose: bool
128130
:rtype: SSHClient
129131
"""
130132
if (host, port) in cls.__cache:
@@ -160,7 +162,7 @@ def __call__(
160162
).__call__(
161163
host=host, port=port,
162164
username=username, password=password, private_keys=private_keys,
163-
auth=auth)
165+
auth=auth, verbose=verbose)
164166
cls.__cache[(ssh.hostname, ssh.port)] = ssh
165167
return ssh
166168

@@ -195,7 +197,7 @@ class SSHClientBase(six.with_metaclass(_MemorizedSSH, _api.ExecHelper)):
195197

196198
__slots__ = (
197199
'__hostname', '__port', '__auth', '__ssh', '__sftp',
198-
'__sudo_mode', '__keepalive_mode',
200+
'__sudo_mode', '__keepalive_mode', '__verbose',
199201
)
200202

201203
class __get_sudo(object):
@@ -279,6 +281,7 @@ def __init__(
279281
password=None, # type: typing.Optional[str]
280282
private_keys=None, # type: typing.Optional[typing.Iterable[paramiko.RSAKey]]
281283
auth=None, # type: typing.Optional[ssh_auth.SSHAuth]
284+
verbose=True, # type: bool
282285
): # type: (...) -> None
283286
"""SSHClient helper.
284287
@@ -294,6 +297,8 @@ def __init__(
294297
:type private_keys: typing.Optional[typing.Iterable[paramiko.RSAKey]]
295298
:param auth: credentials for connection
296299
:type auth: typing.Optional[ssh_auth.SSHAuth]
300+
:param verbose: show additional error/warning messages
301+
:type verbose: bool
297302
298303
.. note:: auth has priority over username/password/private_keys
299304
"""
@@ -310,6 +315,7 @@ def __init__(
310315

311316
self.__sudo_mode = False
312317
self.__keepalive_mode = True
318+
self.__verbose = verbose
313319

314320
self.__ssh = paramiko.SSHClient()
315321
self.__ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
@@ -400,7 +406,7 @@ def __connect(self):
400406
self.auth.connect(
401407
client=self.__ssh,
402408
hostname=self.hostname, port=self.port,
403-
log=True)
409+
log=self.__verbose)
404410

405411
def __connect_sftp(self):
406412
"""SFTP connection opener."""

exec_helpers/_ssh_client_base.pyi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class _MemorizedSSH(type):
1717
username: typing.Optional[str]=...,
1818
password: typing.Optional[str]=...,
1919
private_keys: typing.Optional[typing.Iterable[paramiko.RSAKey]]=...,
20-
auth: typing.Optional[ssh_auth.SSHAuth]=...
20+
auth: typing.Optional[ssh_auth.SSHAuth]=...,
21+
verbose: bool=...
2122
) -> SSHClientBase: ...
2223

2324
@classmethod
@@ -37,7 +38,8 @@ class SSHClientBase(_api.ExecHelper, metaclass=_MemorizedSSH):
3738
username: typing.Optional[str]=...,
3839
password: typing.Optional[str]=...,
3940
private_keys: typing.Optional[typing.Iterable[paramiko.RSAKey]]=...,
40-
auth: typing.Optional[ssh_auth.SSHAuth]=...
41+
auth: typing.Optional[ssh_auth.SSHAuth]=...,
42+
verbose: bool=...
4143
) -> None: ...
4244

4345
@property

test/test_ssh_client_init.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,21 @@ def test_025_init_memorize_reconnect(self, execute, client, policy, logger):
759759
exec_helpers.SSHClient(host=host)
760760
client.assert_called_once()
761761
policy.assert_called_once()
762+
763+
@mock.patch('time.sleep', autospec=True)
764+
def test_026_init_auth_impossible_key_no_verbose(
765+
self, sleep, client, policy, logger):
766+
connect = mock.Mock(side_effect=paramiko.AuthenticationException)
767+
768+
_ssh = mock.Mock()
769+
_ssh.attach_mock(connect, 'connect')
770+
client.return_value = _ssh
771+
772+
with self.assertRaises(paramiko.AuthenticationException):
773+
exec_helpers.SSHClient(
774+
host=host,
775+
auth=exec_helpers.SSHAuth(key=gen_private_keys(1).pop()),
776+
verbose=False
777+
)
778+
779+
logger.assert_not_called()

0 commit comments

Comments
 (0)