Merge "Retry on SSLError"

This commit is contained in:
Zuul 2023-03-21 19:37:06 +00:00 committed by Gerrit Code Review
commit 62641a2f49
2 changed files with 64 additions and 3 deletions

View File

@ -1798,8 +1798,13 @@ class Connection:
service_token=self.service_token, **kwargs) service_token=self.service_token, **kwargs)
self._add_response_dict(caller_response_dict, kwargs) self._add_response_dict(caller_response_dict, kwargs)
return rv return rv
except SSLError: except SSLError as e:
raise self._add_response_dict(caller_response_dict, kwargs)
if ('certificate verify' in str(e)) or \
('hostname' in str(e)) or \
self.attempts > self.retries:
raise
self.http_conn = None
except (socket.error, RequestException): except (socket.error, RequestException):
self._add_response_dict(caller_response_dict, kwargs) self._add_response_dict(caller_response_dict, kwargs)
if self.attempts > self.retries: if self.attempts > self.retries:

View File

@ -25,7 +25,7 @@ import warnings
import tempfile import tempfile
from hashlib import md5 from hashlib import md5
from urllib.parse import urlparse from urllib.parse import urlparse
from requests.exceptions import RequestException from requests.exceptions import RequestException, SSLError
from .utils import (MockHttpTest, fake_get_auth_keystone, StubResponse, from .utils import (MockHttpTest, fake_get_auth_keystone, StubResponse,
FakeKeystone) FakeKeystone)
@ -2176,6 +2176,62 @@ class TestConnection(MockHttpTest):
self.assertEqual(mock_auth.call_count, 1) self.assertEqual(mock_auth.call_count, 1)
self.assertEqual(conn.attempts, conn.retries + 1) self.assertEqual(conn.attempts, conn.retries + 1)
def test_no_retry_with_cert_sslerror(self):
def quick_sleep(*args):
pass
c.sleep = quick_sleep
for err in (
# Taken from real testing (requests==2.25.1, urllib3==1.26.5,
# pyOpenSSL==21.0.0) but note that these are actually way more
# messy/wrapped up in other exceptions
SSLError(
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: '
'certificate has expired (_ssl.c:997)'),
SSLError(
"hostname 'wrong.host.badssl.com' doesn't match either of "
"'*.badssl.com', 'badssl.com'"),
SSLError(
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: '
'self-signed certificate (_ssl.c:997)'),
SSLError(
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: '
'self-signed certificate in certificate chain (_ssl.c:997)'),
SSLError(
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: '
'unable to get local issuer certificate (_ssl.c:997)'),
SSLError(
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: '
'CA signature digest algorithm too weak (_ssl.c:997)'),
):
conn = c.Connection('http://www.test.com', 'asdf', 'asdf')
with self.subTest(err=err), mock.patch(
'swiftclient.client.http_connection') as \
fake_http_connection, \
mock.patch('swiftclient.client.get_auth_1_0') as mock_auth:
mock_auth.return_value = ('http://mock.com', 'mock_token')
fake_http_connection.side_effect = err
self.assertRaises(socket.error, conn.head_account)
self.assertEqual(mock_auth.call_count, 1)
self.assertEqual(conn.attempts, 1)
def test_retry_with_non_cert_sslerror(self):
def quick_sleep(*args):
pass
c.sleep = quick_sleep
conn = c.Connection('http://www.test.com', 'asdf', 'asdf')
with mock.patch('swiftclient.client.http_connection') as \
fake_http_connection, \
mock.patch('swiftclient.client.get_auth_1_0') as mock_auth:
mock_auth.return_value = ('http://mock.com', 'mock_token')
fake_http_connection.side_effect = SSLError(
"HTTPSConnectionPool(host='example.com', port=443): "
"Max retries exceeded with url: /v1/AUTH_test (Caused by "
"SSLError(SSLZeroReturnError(6, 'TLS/SSL connection has "
"been closed (EOF) (_ssl.c:997)')))")
self.assertRaises(socket.error, conn.head_account)
self.assertEqual(mock_auth.call_count, 1)
self.assertEqual(conn.attempts, conn.retries + 1)
def test_retry_with_force_auth_retry_exceptions(self): def test_retry_with_force_auth_retry_exceptions(self):
def quick_sleep(*args): def quick_sleep(*args):
pass pass