Skip to content

Commit

Permalink
Catch connection errors when fetching data during pull-through caching
Browse files Browse the repository at this point in the history
closes #1499
  • Loading branch information
lubosmj authored and ipanova committed Jun 3, 2024
1 parent 7cab423 commit 2c7a4da
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES/1499.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Made the pull-through caching machinery resilient to connection errors.
14 changes: 13 additions & 1 deletion pulp_container/app/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
from rest_framework.exceptions import NotFound, ParseError
from rest_framework.exceptions import APIException, NotFound, ParseError


class BadGateway(APIException):
status_code = 502
default_detail = "Invalid response received from the upstream."
default_code = "BAD_GATEWAY"


class GatewayTimeout(APIException):
status_code = 504
default_detail = "Response from the upstream timed out."
default_code = "GATEWAY_TIMEOUT"


class RepositoryNotFound(NotFound):
Expand Down
5 changes: 3 additions & 2 deletions pulp_container/app/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from urllib.parse import urljoin

from aiohttp import web
from aiohttp.client_exceptions import ClientResponseError
from aiohttp.client_exceptions import ClientResponseError, ClientConnectionError
from aiohttp.web_exceptions import HTTPTooManyRequests
from django_guid import set_guid
from django_guid.utils import generate_guid
Expand All @@ -21,6 +21,7 @@
from pulpcore.plugin.models import RemoteArtifact, Content, ContentArtifact
from pulpcore.plugin.content import ArtifactResponse
from pulpcore.plugin.tasking import dispatch
from pulpcore.plugin.exceptions import TimeoutException

from pulp_container.app.cache import RegistryContentCache
from pulp_container.app.models import ContainerDistribution, Tag, Blob, Manifest, BlobManifest
Expand Down Expand Up @@ -157,7 +158,7 @@ async def get_tag(self, request):
response = await downloader.run(
extra_data={"headers": V2_ACCEPT_HEADERS, "http_method": "head"}
)
except ClientResponseError:
except (ClientResponseError, ClientConnectionError, TimeoutException):
# the manifest is not available on the remote anymore
# but the old one is still stored in the database
pass
Expand Down
14 changes: 11 additions & 3 deletions pulp_container/app/registry_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import hashlib
import re

from aiohttp.client_exceptions import ClientResponseError
from aiohttp.client_exceptions import ClientResponseError, ClientConnectionError
from itertools import chain
from urllib.parse import urljoin, urlparse, urlunparse, parse_qs, urlencode
from tempfile import NamedTemporaryFile
Expand All @@ -29,6 +29,8 @@
from pulpcore.plugin.files import PulpTemporaryUploadedFile
from pulpcore.plugin.tasking import add_and_remove, dispatch
from pulpcore.plugin.util import get_objects_for_user, get_url
from pulpcore.plugin.exceptions import TimeoutException

from rest_framework.exceptions import (
AuthenticationFailed,
NotAuthenticated,
Expand All @@ -55,6 +57,8 @@
RegistryApiCache,
)
from pulp_container.app.exceptions import (
BadGateway,
GatewayTimeout,
InvalidRequest,
RepositoryNotFound,
RepositoryInvalid,
Expand Down Expand Up @@ -1117,9 +1121,13 @@ def fetch_manifest(self, remote, pk):
# the client could request the manifest outside the docker hub pull limit;
# it is necessary to pass this information back to the client
raise Throttled()
else:
# TODO: do not mask out relevant errors, like HTTP 502
elif response_error.status == 404:
raise ManifestNotFound(reference=pk)
else:
raise BadGateway(detail=response_error.message)
except (ClientConnectionError, TimeoutException):
# The remote server is not available at the moment
raise GatewayTimeout()
else:
digest = response.headers.get("docker-content-digest")
return models.Manifest.objects.filter(digest=digest).first()
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
jsonschema>=4.4,<4.23
pulpcore>=3.43.0,<3.55
pulpcore>=3.46.0,<3.55
pyjwt[crypto]>=2.4,<2.9

0 comments on commit 2c7a4da

Please sign in to comment.