diff --git a/.changelog/4227.yml b/.changelog/4227.yml new file mode 100644 index 00000000000..f9972d699fb --- /dev/null +++ b/.changelog/4227.yml @@ -0,0 +1,4 @@ +changes: +- description: Fixed an issue where requests to dockerhub failed on rate-limits when authenticating with username and password. + type: fix +pr_number: 4227 diff --git a/demisto_sdk/commands/common/docker/dockerhub_client.py b/demisto_sdk/commands/common/docker/dockerhub_client.py index a26f7dd16d5..9cb8ccda335 100644 --- a/demisto_sdk/commands/common/docker/dockerhub_client.py +++ b/demisto_sdk/commands/common/docker/dockerhub_client.py @@ -105,7 +105,12 @@ def get_token( logger.warning( f"Error when trying to get dockerhub token, error\n:{_error}" ) - if _error.response.status_code == requests.codes.unauthorized and self.auth: + if ( + _error.response.status_code + in (requests.codes.unauthorized, requests.codes.too_many_requests) + and self.auth + ): + # in case of rate-limits with a username:password, retrieve the token without username:password logger.debug("Trying to get dockerhub token without username:password") try: response = self._session.get( diff --git a/demisto_sdk/commands/common/docker/tests/dockerhub_client_test.py b/demisto_sdk/commands/common/docker/tests/dockerhub_client_test.py index f07baf2a23a..5f33b2fcedf 100644 --- a/demisto_sdk/commands/common/docker/tests/dockerhub_client_test.py +++ b/demisto_sdk/commands/common/docker/tests/dockerhub_client_test.py @@ -15,6 +15,7 @@ def dockerhub_client() -> DockerHubClient: dockerhub_client = DockerHubClient(username="test", password="test") dockerhub_client.do_registry_get_request.cache_clear() dockerhub_client.do_docker_hub_get_request.cache_clear() + dockerhub_client._docker_hub_auth_tokens = {} return dockerhub_client @@ -71,6 +72,35 @@ def test_get_token_with_existing_not_expired_token( assert not requests_mock.called +def test_get_token_ratelimit_with_username_password( + mocker, dockerhub_client: DockerHubClient +): + """ + Given: + - no token from at the cache + - rate-limit error with username/password + - successful response without username/password + + When: + - running get_token method + + Then: + - ensure that the token is returned successfully + """ + rate_limit_response = Response() + rate_limit_response.status_code = 429 + rate_limit_response._content = b"" + valid_response = Response() + valid_response.status_code = 200 + valid_response._content = json.dumps( + {"token": "token_from_api", "issued_at": "1234", "expires_in": 300} + ).encode("utf-8") + mocker.patch.object( + Session, "get", side_effect=[rate_limit_response, valid_response] + ) + assert dockerhub_client.get_token(repo="test") == "token_from_api" + + @freeze_time("2024-01-01 12:00:00") def test_get_token_with_existing_expired_token( requests_mock, dockerhub_client: DockerHubClient