Don't try to resolve server version for old hubs

Related: https://pagure.io/koji/issue/3890
This commit is contained in:
Tomas Kopecek 2023-09-05 12:38:58 +02:00
parent d43ad529c1
commit 7a9b0561eb
7 changed files with 69 additions and 21 deletions

View file

@ -324,9 +324,8 @@ def handle_add_channel(goptions, session, args):
if 'channel %s already exists' % channel_name in msg:
error("channel %s already exists" % channel_name)
elif 'Invalid method:' in msg:
version = session.getKojiVersion()
error("addChannel is available on hub from Koji 1.26 version, your version is %s" %
version)
session.hub_version_str)
else:
error(msg)
print("%s added: id %d" % (args[0], channel_id))
@ -356,9 +355,8 @@ def handle_edit_channel(goptions, session, args):
except koji.GenericError as ex:
msg = str(ex)
if 'Invalid method:' in msg:
version = session.getKojiVersion()
error("editChannel is available on hub from Koji 1.26 version, your version is %s" %
version)
session.hub_version_str)
else:
warn(msg)
if not result:
@ -6295,14 +6293,6 @@ def handle_cancel(goptions, session, args):
if len(args) == 0:
parser.error("You must specify at least one task id or build")
activate_session(session, goptions)
older_hub = False
try:
hub_version = session.getKojiVersion()
v = tuple([int(x) for x in hub_version.split('.')])
if v < (1, 33, 0):
older_hub = True
except koji.GenericError:
older_hub = True
tlist = []
blist = []
for arg in args:
@ -6329,7 +6319,7 @@ def handle_cancel(goptions, session, args):
for task_id in tlist:
results.append(remote_fn(task_id, **opts))
for build in blist:
if not older_hub:
if session.hub_version >= (1, 33, 0):
results.append(m.cancelBuild(build, strict=True))
else:
results.append(m.cancelBuild(build))

View file

@ -2625,6 +2625,27 @@ class ClientSession(object):
self.opts.setdefault('timeout', DEFAULT_REQUEST_TIMEOUT)
self.exclusive = False
self.auth_method = auth_method
self.__hub_version = None
@property
def hub_version(self):
"""Cached version of getKojiVersion call for use in version checks"""
# If any call was made before, it should be populated by Koji-Version header
# for hub >= 1.35
if self.__hub_version is None:
try:
# no call was made yet AND 1.22.0 < hub_version < 1.35
self.__hub_version = self.getKojiVersion()
except GenericError:
# hub is older than 1.23, return latest version without the getKojiVersion
self.__hub_version = '1.22.0'
return tuple([int(x) for x in self.__hub_version.split('.')])
@property
def hub_version_str(self):
# fill cache
self.hub_version
return self.__hub_version
@property
def multicall(self):
@ -3056,6 +3077,7 @@ class ClientSession(object):
warnings.simplefilter("ignore")
r = self.rsession.post(handler, **callopts)
r.raise_for_status()
self.__hub_version = r.headers.get('Koji-Version')
try:
ret = self._read_xmlrpc_response(r)
finally:

View file

@ -44,6 +44,12 @@ from . import db
from . import scheduler
# HTTP headers included in every request
GLOBAL_HEADERS = [
('Koji-Version', koji.__version__),
]
class Marshaller(ExtendedMarshaller):
dispatch = ExtendedMarshaller.dispatch.copy()
@ -389,7 +395,7 @@ def offline_reply(start_response, msg=None):
else:
faultString = msg
response = dumps(Fault(faultCode, faultString)).encode()
headers = [
headers = GLOBAL_HEADERS + [
('Content-Length', str(len(response))),
('Content-Type', "text/xml"),
]
@ -399,7 +405,7 @@ def offline_reply(start_response, msg=None):
def error_reply(start_response, status, response, extra_headers=None):
response = response.encode()
headers = [
headers = GLOBAL_HEADERS + [
('Content-Length', str(len(response))),
('Content-Type', "text/plain"),
]
@ -816,7 +822,7 @@ def application(environ, start_response):
except RequestTimeout as e:
return error_reply(start_response, '408 Request Timeout', str(e) + '\n')
response = response.encode()
headers = [
headers = GLOBAL_HEADERS + [
('Content-Length', str(len(response))),
('Content-Type', "text/xml"),
]

View file

@ -60,7 +60,7 @@ class TestAddChannel(utils.CliTestCase):
expected_api = 'Invalid method: addChannel'
expected = 'addChannel is available on hub from Koji 1.26 version, your version ' \
'is 1.25.1\n'
self.session.getKojiVersion.return_value = '1.25.1'
self.session.hub_version_str = '1.25.1'
self.session.addChannel.side_effect = koji.GenericError(expected_api)
arguments = ['--description', self.description, self.channel_name]

View file

@ -32,7 +32,8 @@ class TestCancel(utils.CliTestCase):
%s: error: {message}
""" % (self.progname, self.progname)
self.session.getKojiVersion.return_value = '1.33.0'
self.session.hub_version = (1, 33, 0)
self.session.hub_version_str = '1.33.0'
def test_anon_cancel(self):
args = ['123']
@ -154,7 +155,7 @@ No such build: '%s'
self.session.cancelBuild.assert_called_once_with(args[1], strict=True)
def test_non_exist_build_and_task_older_hub(self):
self.session.getKojiVersion.return_value = '1.32.0'
self.session.hub_version = (1, 32, 0)
args = ['11111', 'nvr-1-30.1']
expected_warn = """No such task: %s
""" % (args[0])

View file

@ -78,7 +78,7 @@ Options:
expected_api = 'Invalid method: editChannel'
expected = 'editChannel is available on hub from Koji 1.26 version, your version ' \
'is 1.25.1\n'
self.session.getKojiVersion.return_value = '1.25.1'
self.session.hub_version_str = '1.25.1'
self.session.editChannel.side_effect = koji.GenericError(expected_api)
self.assert_system_exit(
@ -94,7 +94,6 @@ Options:
self.session.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new,
description=self.description)
self.session.getChannel.assert_called_once_with(self.channel_old)
self.session.getKojiVersion.assert_called_once_with()
def test_handle_edit_channel_non_exist_channel(self):
expected = 'No such channel: %s\n' % self.channel_old

View file

@ -30,6 +30,36 @@ class TestClientSession(unittest.TestCase):
my_rsession.close.assert_called()
self.assertNotEqual(ksession.rsession, my_rsession)
@mock.patch('requests.Session')
def test_hub_version_old(self, rsession):
ksession = koji.ClientSession('http://koji.example.com/kojihub')
ksession.getKojiVersion = mock.MagicMock()
ksession.getKojiVersion.side_effect = koji.GenericError
self.assertEqual(ksession.hub_version, (1, 22, 0))
ksession.getKojiVersion.assert_called_once()
@mock.patch('requests.Session')
def test_hub_version_interim(self, rsession):
ksession = koji.ClientSession('http://koji.example.com/kojihub')
ksession.getKojiVersion = mock.MagicMock()
ksession.getKojiVersion.return_value = '1.23.1'
self.assertEqual(ksession.hub_version, (1, 23, 1))
ksession.getKojiVersion.assert_called_once()
def test_hub_version_str_interim(self):
ksession = koji.ClientSession('http://koji.example.com/kojihub')
ksession.getKojiVersion = mock.MagicMock()
ksession.getKojiVersion.return_value = '1.23.1'
self.assertEqual(ksession.hub_version_str, '1.23.1')
def test_hub_version_new(self):
ksession = koji.ClientSession('http://koji.example.com/kojihub')
ksession.getKojiVersion = mock.MagicMock()
# would be filled by random call
ksession._ClientSession__hub_version = '1.35.0'
self.assertEqual(ksession.hub_version, (1, 35, 0))
ksession.getKojiVersion.assert_not_called()
class TestFastUpload(unittest.TestCase):