Skip to content

Commit 8f507d6

Browse files
authored
Merge pull request #4974 from StackStorm/hotfix/paramiko-bastion-cleanup
Fixed exception during SSH runner socket cleanup
2 parents 050e45f + 9c48bbf commit 8f507d6

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ Fixed
2929

3030
* Fixed a bug in the example nginx HA template declared headers twice (bug fix) #4966
3131
Contributed by @punkrokk
32+
* Fixed a bug in the ``paramiko_ssh`` runner where SSH sockets were not getting cleaned
33+
up correctly, specifically when specifying a bastion host / jump box. (bug fix) #4973
34+
35+
Contributed by Nick Maludy (@nmaludy Encore Technologies)
36+
3237

3338
3.2.0 - April 27, 2020
3439
----------------------

st2actions/tests/unit/test_paramiko_ssh.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -814,20 +814,46 @@ def test_socket_closed(self):
814814

815815
# Make sure .close() doesn't actually call anything real
816816
ssh_client.client = Mock()
817-
ssh_client.sftp_client = None
818-
ssh_client.bastion_client = None
817+
ssh_client.sftp_client = Mock()
818+
ssh_client.bastion_client = Mock()
819819

820820
ssh_client.socket = Mock()
821+
ssh_client.bastion_socket = Mock()
821822

822823
# Make sure we havent called any close methods at this point
823824
# TODO: Replace these with .assert_not_called() once it's Python 3.6+ only
824-
self.assertEqual(ssh_client.socket.process.kill.call_count, 0)
825-
self.assertEqual(ssh_client.socket.process.poll.call_count, 0)
825+
self.assertEqual(ssh_client.socket.close.call_count, 0)
826+
self.assertEqual(ssh_client.client.close.call_count, 0)
827+
self.assertEqual(ssh_client.sftp_client.close.call_count, 0)
828+
self.assertEqual(ssh_client.bastion_socket.close.call_count, 0)
829+
self.assertEqual(ssh_client.bastion_client.close.call_count, 0)
826830

827831
# Call the function that has changed
828832
ssh_client.close()
829833

830-
# Make sure we have called kill and poll
831834
# TODO: Replace these with .assert_called_once() once it's Python 3.6+ only
832-
self.assertEqual(ssh_client.socket.process.kill.call_count, 1)
833-
self.assertEqual(ssh_client.socket.process.poll.call_count, 1)
835+
self.assertEqual(ssh_client.socket.close.call_count, 1)
836+
self.assertEqual(ssh_client.client.close.call_count, 1)
837+
self.assertEqual(ssh_client.sftp_client.close.call_count, 1)
838+
self.assertEqual(ssh_client.bastion_socket.close.call_count, 1)
839+
self.assertEqual(ssh_client.bastion_client.close.call_count, 1)
840+
841+
@patch.object(ParamikoSSHClient, '_is_key_file_needs_passphrase',
842+
MagicMock(return_value=False))
843+
def test_socket_not_closed_if_none(self):
844+
conn_params = {'hostname': 'dummy.host.org',
845+
'username': 'ubuntu',
846+
'password': 'pass',
847+
'timeout': '600'}
848+
ssh_client = ParamikoSSHClient(**conn_params)
849+
850+
# Make sure .close() doesn't actually call anything real
851+
ssh_client.client = None
852+
ssh_client.sftp_client = None
853+
ssh_client.bastion_client = None
854+
855+
ssh_client.socket = None
856+
ssh_client.bastion_socket = None
857+
858+
# Call the function, this should not throw an exception
859+
ssh_client.close()

st2common/st2common/runners/paramiko_ssh.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -452,19 +452,18 @@ def run(self, cmd, timeout=None, quote=False, call_line_handler_func=False):
452452
return [stdout, stderr, status]
453453

454454
def close(self):
455-
self.logger.debug('Closing server connection')
456-
457-
self.client.close()
458-
459455
if self.socket:
460-
self.logger.debug('Closing proxycommand socket connection')
461-
# https://github.com/paramiko/paramiko/issues/789 Avoid zombie ssh processes
462-
self.socket.process.kill()
463-
self.socket.process.poll()
456+
self.socket.close()
457+
458+
if self.client:
459+
self.client.close()
464460

465461
if self.sftp_client:
466462
self.sftp_client.close()
467463

464+
if self.bastion_socket:
465+
self.bastion_socket.close()
466+
468467
if self.bastion_client:
469468
self.bastion_client.close()
470469

0 commit comments

Comments
 (0)