From 068ba5f211833cc1232acfe15b673d26436719cd Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Apr 20 2022 13:40:37 +0000 Subject: Add compatibility for Bodhi >= 6.0.0 Compatibility with Bodhi 5.X is retained. Signed-off-by: Aurélien Bompard --- diff --git a/fedpkg/__init__.py b/fedpkg/__init__.py index 60a8193..f041b97 100644 --- a/fedpkg/__init__.py +++ b/fedpkg/__init__.py @@ -21,11 +21,7 @@ from datetime import datetime, timedelta from . import cli # noqa from .lookaside import FedoraLookasideCache from pyrpkg.utils import cached_property - -try: - from bodhi.client.bindings import BodhiClient as _BodhiClient -except ImportError: - _BodhiClient = None +from pkg_resources import get_distribution, parse_version try: from distro import linux_distribution # noqa @@ -33,56 +29,11 @@ except ImportError: from platform import linux_distribution # noqa -if _BodhiClient is not None: - from fedora.client import AuthError - - def clear_csrf_and_retry(func): - """Clear csrf token and retry - - fedpkg uses Bodhi Python binding API list_overrides first before other - save and extend APIs. That causes a readonly csrf token is received, - which will be got again when next time to construct request data to - modify updates. That is not expected and AuthError will be raised. - - So, the solution is to capture the AuthError error, clear the token and - try to modify update again by requesting another token with user's - credential. - """ - def _decorator(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except AuthError: - self._session.cookies.clear() - self.csrf_token = None - return func(self, *args, **kwargs) - return _decorator - - class BodhiClient(_BodhiClient): - """Customized BodhiClient for fedpkg""" - - UPDATE_TYPES = ['bugfix', 'security', 'enhancement', 'newpackage'] - REQUEST_TYPES = ['testing', 'stable'] - SUGGEST_TYPES = ['unspecified', 'reboot', 'logout'] - - @clear_csrf_and_retry - def save(self, *args, **kwargs): - return super(BodhiClient, self).save(*args, **kwargs) - - @clear_csrf_and_retry - def save_override(self, *args, **kwargs): - return super(BodhiClient, self).save_override(*args, **kwargs) - - @clear_csrf_and_retry - def extend_override(self, override, expiration_date): - data = dict( - nvr=override['nvr'], - notes=override['notes'], - expiration_date=expiration_date, - edited=override['nvr'], - csrf_token=self.csrf(), - ) - return self.send_request( - 'overrides/', verb='POST', auth=True, data=data) +bodhi_version = get_distribution('bodhi-client').version +if parse_version(bodhi_version) < parse_version("6.0.0"): + from .bodhi_5 import BodhiClient, UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES +else: + from .bodhi_6 import BodhiClient, UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES class Commands(pyrpkg.Commands): @@ -354,13 +305,13 @@ class Commands(pyrpkg.Commands): if not detail['type']: raise ValueError( 'Missing update type, which is required to create update.') - if detail['type'] not in BodhiClient.UPDATE_TYPES: + if detail['type'] not in UPDATE_TYPES: raise ValueError( 'Incorrect update type {0}'.format(detail['type'])) - if detail['request'] not in BodhiClient.REQUEST_TYPES: + if detail['request'] not in REQUEST_TYPES: raise ValueError( 'Incorrect request type {0}'.format(detail['request'])) - if detail['suggest'] not in BodhiClient.SUGGEST_TYPES: + if detail['suggest'] not in SUGGEST_TYPES: raise ValueError( 'Incorrect suggest type {0}'.format(detail['suggest'])) diff --git a/fedpkg/bodhi_5.py b/fedpkg/bodhi_5.py new file mode 100644 index 0000000..9ffa1df --- /dev/null +++ b/fedpkg/bodhi_5.py @@ -0,0 +1,63 @@ +# fedpkg - a Python library for RPM Packagers +# +# Copyright (C) 2011 Red Hat Inc. +# Author(s): Jesse Keating +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See http://www.gnu.org/copyleft/gpl.html for +# the full text of the license. + +from bodhi.client.bindings import BodhiClient as _BodhiClient +from fedora.client import AuthError + + +UPDATE_TYPES = ['bugfix', 'security', 'enhancement', 'newpackage'] +REQUEST_TYPES = ['testing', 'stable'] +SUGGEST_TYPES = ['unspecified', 'reboot', 'logout'] + + +def clear_csrf_and_retry(func): + """Clear csrf token and retry + + fedpkg uses Bodhi Python binding API list_overrides first before other + save and extend APIs. That causes a readonly csrf token is received, + which will be got again when next time to construct request data to + modify updates. That is not expected and AuthError will be raised. + + So, the solution is to capture the AuthError error, clear the token and + try to modify update again by requesting another token with user's + credential. + """ + def _decorator(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except AuthError: + self._session.cookies.clear() + self.csrf_token = None + return func(self, *args, **kwargs) + return _decorator + + +class BodhiClient(_BodhiClient): + """Customized BodhiClient for fedpkg""" + + @clear_csrf_and_retry + def save(self, *args, **kwargs): + return super(BodhiClient, self).save(*args, **kwargs) + + @clear_csrf_and_retry + def save_override(self, *args, **kwargs): + return super(BodhiClient, self).save_override(*args, **kwargs) + + @clear_csrf_and_retry + def extend_override(self, override, expiration_date): + data = dict( + nvr=override['nvr'], + notes=override['notes'], + expiration_date=expiration_date, + csrf_token=self.csrf(), + ) + return self.send_request( + 'overrides/', verb='POST', auth=True, data=data) diff --git a/fedpkg/bodhi_6.py b/fedpkg/bodhi_6.py new file mode 100644 index 0000000..3b72cb0 --- /dev/null +++ b/fedpkg/bodhi_6.py @@ -0,0 +1,26 @@ +# fedpkg - a Python library for RPM Packagers +# +# Copyright (C) 2011 Red Hat Inc. +# Author(s): Jesse Keating +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See http://www.gnu.org/copyleft/gpl.html for +# the full text of the license. + +from bodhi.client.bindings import BodhiClient as BodhiClient_ +from bodhi.client.constants import UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES # noqa + + +class BodhiClient(BodhiClient_): + + def __init__(self, username, *args, **kwargs): + super().__init__(*args, **kwargs) + + def extend_override(self, override, new_expiration_date): + return self.save_override( + nvr=override["nvr"], + notes=override["notes"], + expiration_date=new_expiration_date + ) diff --git a/requirements.txt b/requirements.txt index 7e52a2c..f880e99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ openidc-client python-bugzilla rpkg six +python-fedora diff --git a/test/test_cli.py b/test/test_cli.py index 6a9864d..03c9403 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -26,6 +26,7 @@ from six.moves import StringIO from six.moves.configparser import NoOptionError, NoSectionError import fedpkg.cli +from fedpkg import parse_version, bodhi_version from fedpkg.bugzilla import BugzillaClient from fedpkg.cli import check_bodhi_version from freezegun import freeze_time @@ -1712,6 +1713,10 @@ class TestBodhiOverride(CliTestCase): 'Buildroot override for %s already exists and not ' 'expired.', 'rpkg-1.54-2.fc28') + @unittest.skipIf( + parse_version(bodhi_version) >= parse_version("6.0.0"), + "Retrying is built in Bodhi 6" + ) @patch('fedora.client.OpenIdBaseClient._load_cookies') @patch('bodhi.client.bindings.BodhiClient.list_overrides') @patch('bodhi.client.bindings.BodhiClient.save_override') @@ -1888,7 +1893,6 @@ class TestBodhiOverrideExtend(CliTestCase): 'expiration_date': expected_expiration_date, 'nvr': build_nvr, 'notes': build_override['notes'], - 'edited': build_nvr, 'csrf_token': csrf.return_value, } send_request.assert_called_once_with( @@ -1945,7 +1949,6 @@ class TestBodhiOverrideExtend(CliTestCase): 'expiration_date': expected_expiration_date, 'nvr': build_nvr, 'notes': build_override['notes'], - 'edited': build_nvr, 'csrf_token': csrf.return_value, } send_request.assert_called_once_with( @@ -2003,7 +2006,6 @@ class TestBodhiOverrideExtend(CliTestCase): 'expiration_date': expected_expiration_date, 'nvr': build_nvr, 'notes': build_override['notes'], - 'edited': build_nvr, 'csrf_token': csrf.return_value, } send_request.assert_called_once_with( @@ -2042,6 +2044,10 @@ class TestBodhiOverrideExtend(CliTestCase): six.assertRaisesRegex(self, rpkgError, '', cli.extend_buildroot_override) + @unittest.skipIf( + parse_version(bodhi_version) >= parse_version("6.0.0"), + "Retrying is built in Bodhi 6" + ) @patch('fedpkg.BodhiClient.list_overrides') @patch('fedpkg.BodhiClient.csrf') @patch('fedpkg.BodhiClient.send_request') @@ -2102,7 +2108,6 @@ class TestBodhiOverrideExtend(CliTestCase): 'expiration_date': expected_expiration_date, 'nvr': build_nvr, 'notes': build_override['notes'], - 'edited': build_nvr, 'csrf_token': token, }) for token in csrf.side_effect diff --git a/tox.ini b/tox.ini index 009f3ae..1be6026 100644 --- a/tox.ini +++ b/tox.ini @@ -18,6 +18,7 @@ commands = python -m pytest {posargs} setenv= PYCURL_SSL_LIBRARY=openssl + HOME={envtmpdir}/home [testenv:py27] deps =