From 68d51b348822bcd5b02056c1a04eeee9d099d091 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Feb 15 2022 13:23:49 +0000 Subject: [PATCH 1/3] Retry gssapi_login if it makes sense Related: https://pagure.io/koji/issue/3170 --- diff --git a/koji/__init__.py b/koji/__init__.py index fa89f3b..50d1c34 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -2548,7 +2548,18 @@ class ClientSession(object): kwargs = {'proxyuser': proxyuser} if proxyauthtype is not None: kwargs['proxyauthtype'] = proxyauthtype - sinfo = self._callMethod('sslLogin', [], kwargs, retry=False) + for i in range(self.opts.get('max_retries', 30)): + try: + sinfo = self._callMethod('sslLogin', [], kwargs, retry=False) + except Exception as ex: + # retry on connection error requests.exceptions.ConnectionError + # die on: + # - any non-connection related error (http code, etc.) + # - requests.exceptions.SSLError - CA-mismatch, etc. - die on all SSL + # related errors + if (not is_conn_error(ex) or isinstance(ex, requests.exceptions.SSLError)): + raise + time.sleep(self.opts.get('retry_interval', 20)) except Exception as e: e_str = ''.join(traceback.format_exception_only(type(e), e)).strip('\n') e_str = '(gssapi auth failed: %s)\n' % e_str From fa4ec5a3526f195415edcabf592c91c88bbdf026 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Feb 15 2022 13:23:49 +0000 Subject: [PATCH 2/3] fix test --- diff --git a/tests/test_lib/test_gssapi.py b/tests/test_lib/test_gssapi.py index c5f71be..6249221 100644 --- a/tests/test_lib/test_gssapi.py +++ b/tests/test_lib/test_gssapi.py @@ -26,8 +26,8 @@ class TestGSSAPI(unittest.TestCase): def test_gssapi_login(self): old_environ = dict(**os.environ) self.session.gssapi_login() - self.session._callMethod.assert_called_once_with( - 'sslLogin', [], {'proxyuser': None}, retry=False) + self.session._callMethod.assert_called_with( + 'sslLogin', [], {'proxyuser': None}, retry=False) self.assertEqual(old_environ, dict(**os.environ)) @mock.patch('koji.reqgssapi.HTTPKerberosAuth') @@ -46,8 +46,8 @@ class TestGSSAPI(unittest.TestCase): for accepted_version in accepted_versions: koji.reqgssapi.__version__ = accepted_version rv = self.session.gssapi_login(principal, keytab, ccache) - self.session._callMethod.assert_called_once_with( - 'sslLogin', [], {'proxyuser': None}, retry=False) + self.session._callMethod.assert_called_with( + 'sslLogin', [], {'proxyuser': None}, retry=False) self.assertEqual(old_environ, dict(**os.environ)) self.assertTrue(rv) self.session._callMethod.reset_mock() @@ -83,8 +83,8 @@ class TestGSSAPI(unittest.TestCase): self.session._callMethod.side_effect = Exception('login failed') with self.assertRaises(koji.GSSAPIAuthError): self.session.gssapi_login() - self.session._callMethod.assert_called_once_with( - 'sslLogin', [], {'proxyuser': None}, retry=False) + self.session._callMethod.assert_called_with( + 'sslLogin', [], {'proxyuser': None}, retry=False) self.assertEqual(old_environ, dict(**os.environ)) def test_gssapi_login_http(self): From 8f3ef04b619f6e1983d9445530c161912ba3e3d5 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Feb 15 2022 13:32:54 +0000 Subject: [PATCH 3/3] logging and comment update --- diff --git a/koji/__init__.py b/koji/__init__.py index 50d1c34..f9a79f4 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -2545,20 +2545,29 @@ class ClientSession(object): # Depending on the server configuration, we might not be able to # connect without client certificate, which means that the conn # will fail with a handshake failure, which is retried by default. + # For this case we're now using retry=False and test errors for + # this exact usecase. kwargs = {'proxyuser': proxyuser} if proxyauthtype is not None: kwargs['proxyauthtype'] = proxyauthtype - for i in range(self.opts.get('max_retries', 30)): + for tries in range(self.opts.get('max_retries', 30)): try: sinfo = self._callMethod('sslLogin', [], kwargs, retry=False) + break except Exception as ex: - # retry on connection error requests.exceptions.ConnectionError + # retry on requests.exceptions.ConnectionError # die on: # - any non-connection related error (http code, etc.) # - requests.exceptions.SSLError - CA-mismatch, etc. - die on all SSL # related errors if (not is_conn_error(ex) or isinstance(ex, requests.exceptions.SSLError)): raise + # logging similar to normal retry + if self.logger.isEnabledFor(logging.DEBUG): + tb_str = ''.join(traceback.format_exception(*sys.exc_info())) + self.logger.debug(tb_str) + self.logger.info("Try #%s for call %s (sslLogin) failed: %s", + tries, self.callnum, ex) time.sleep(self.opts.get('retry_interval', 20)) except Exception as e: e_str = ''.join(traceback.format_exception_only(type(e), e)).strip('\n')