This is an automated email from the ASF dual-hosted git repository. tomaz pushed a commit to branch 2.8.x in repository https://gitbox.apache.org/repos/asf/libcloud.git
commit 0e8af0e919befab151426cee5246045e1169c002 Author: Tomaz Muraus <[email protected]> AuthorDate: Tue Mar 31 23:18:44 2020 +0200 Add a test case which verifies deploy_node() correctly propagates fatal errors instead of retrying. --- libcloud/compute/base.py | 3 ++- libcloud/test/compute/test_deployment.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libcloud/compute/base.py b/libcloud/compute/base.py index 4529844..0f555fc 100644 --- a/libcloud/compute/base.py +++ b/libcloud/compute/base.py @@ -1726,13 +1726,14 @@ class NodeDriver(BaseDriver): ssh_client.connect() except SSH_TIMEOUT_EXCEPTION_CLASSES as e: # Errors which represent fatal invalid key files which should - # be propagated to the user + # be propagated to the user without us retrying message = str(e).lower() invalid_key_msgs = [ 'no such file or directory', 'invalid key', 'not a valid ', 'invalid or unsupported key type', + 'private file is encrypted', 'private key file is encrypted' ] diff --git a/libcloud/test/compute/test_deployment.py b/libcloud/test/compute/test_deployment.py index dd25310..e7aa9e0 100644 --- a/libcloud/test/compute/test_deployment.py +++ b/libcloud/test/compute/test_deployment.py @@ -24,6 +24,7 @@ import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import u from libcloud.utils.py3 import PY3 +from libcloud.utils.py3 import assertRaisesRegex from libcloud.compute.deployment import MultiStepDeployment, Deployment from libcloud.compute.deployment import SSHKeyDeployment, ScriptDeployment @@ -32,6 +33,7 @@ from libcloud.compute.base import Node from libcloud.compute.base import NodeAuthPassword from libcloud.compute.types import NodeState, DeploymentError, LibcloudError from libcloud.compute.ssh import BaseSSHClient +from libcloud.compute.ssh import have_paramiko from libcloud.compute.drivers.rackspace import RackspaceFirstGenNodeDriver as Rackspace from libcloud.test import MockHttp, XML_HEADERS @@ -356,6 +358,30 @@ class DeploymentTests(unittest.TestCase): else: self.fail('Exception was not thrown') + @unittest.skipIf(not have_paramiko, 'Skipping because paramiko is not available') + def test_ssh_client_connect_immediately_throws_on_fatal_execption(self): + # Verify that fatal exceptions are immediately propagated and ensure + # we don't try to retry on them + from paramiko.ssh_exception import SSHException + from paramiko.ssh_exception import PasswordRequiredException + + mock_ssh_client = Mock() + mock_ssh_client.connect = Mock() + mock_ssh_client.connect.side_effect = IOError('bam') + + mock_exceptions = [ + SSHException('Invalid or unsupported key type'), + PasswordRequiredException('private key file is encrypted') + ] + + for mock_exception in mock_exceptions: + mock_ssh_client.connect = Mock(side_effect=mock_exception) + assertRaisesRegex(self, mock_exception.__class__, str(mock_exception), + self.driver._ssh_client_connect, + ssh_client=mock_ssh_client, + wait_period=0.1, + timeout=0.2) + def test_run_deployment_script_success(self): task = Mock() ssh_client = Mock()
