From e8a8b16f1abef8fa52956faad0f3792a06fde099 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Nov 09 2022 13:47:33 +0000 Subject: copr: don't play with sessions if using ApiToken This actually caused a weird situation leading to an unsuccessful build upload, if user had a valid API token, but also an outdated session cookie. The attempts failed with: 408 Request Timeout What was happening client-side: base_proxy.auth_check() (to check before upload...) auth.make() // sets outdated auth.cookies, but not auth.auth! => fails auth.make(reauth) make_expensive() sets auth.auth keeps auth.cookies (outdated) succeeds (auth.cookies set, auth.auth set, too) build_proxy.create_from_file() auth.make() // sets outdated auth.cookies, but not auth.auth request attempt 1. => fails auth.make(reauth) make_expensive() sets auth.auth keeps auth.cookies (outdated) request attempt 2. => timeouts serverside The second attempt leading to server timeout is reproducible, and needs further debugging (the bug is still present!). Seems like the request (FileRequest class) in the 2nd attempt is somewhat broken, and leads to wsgi/flask/werkzeug timeout (our code is not even called): OSError: Apache/mod_wsgi request data read error: Partial results are valid but processing is incomplete. I even tried to restart server between the 1st and 2nd upload attempt, and the server fails reproducibly. This also shows us that the Client stores the "auth" object in multiple instances, per each proxy. We should ideally fix this in the future. Relates: #2232 (very likely) Fixes: #2303 --- diff --git a/python/copr/test/client_v3/test_auth.py b/python/copr/test/client_v3/test_auth.py index 055023f..b20cead 100644 --- a/python/copr/test/client_v3/test_auth.py +++ b/python/copr/test/client_v3/test_auth.py @@ -13,11 +13,7 @@ class TestApiToken: """ config = mock.MagicMock() auth = ApiToken(config) - assert not auth.auth - assert not auth.username - # Make sure all auth values are loaded from the config - auth.make_expensive() assert auth.auth assert auth.username diff --git a/python/copr/v3/auth/base.py b/python/copr/v3/auth/base.py index 927b8c9..2f3e454 100644 --- a/python/copr/v3/auth/base.py +++ b/python/copr/v3/auth/base.py @@ -14,7 +14,7 @@ except ImportError: from urlparse import urlparse -class BaseAuth: +class BaseAuth(object): """ Base authentication class There is a more standard way of implementing custom authentication classes, diff --git a/python/copr/v3/auth/token.py b/python/copr/v3/auth/token.py index 1d97894..a0db59a 100644 --- a/python/copr/v3/auth/token.py +++ b/python/copr/v3/auth/token.py @@ -7,8 +7,25 @@ from copr.v3.auth.base import BaseAuth class ApiToken(BaseAuth): """ - The standard authentication via `(login, token)` from `~/.config/copr` + The standard authentication via `(login, token)` from `~/.config/copr`. """ - def make_expensive(self): + + def __init__(self, *args, **kwargs): + super(ApiToken, self).__init__(*args, **kwargs) + # No need to lazy-login + self.make() + + def make(self, reauth=False): + """ + Override the higher abstraction method BaseAuth.make() because we don't + need the complicated logic with API tokens at all (working with caches + or sessions, etc.). We also don't use make_expensive() at all. + """ self.auth = self.config["login"], self.config["token"] self.username = self.config.get("username") + + def make_expensive(self): + """ + This is never called. We have overridden the parent's make() method. + """ + raise RuntimeError("ApiToken.make_expensive() should never be called")