Skip to content

Commit

Permalink
Refactor the repository retrieval in get_dr_push
Browse files Browse the repository at this point in the history
closes #1275
  • Loading branch information
lubosmj committed Oct 31, 2023
1 parent efe2772 commit ef0d823
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGES/1275.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Ensured repositories are correctly retrieved or initialized when handling concurrent requests
during the push operation.
56 changes: 29 additions & 27 deletions pulp_container/app/registry_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from django.core.files.storage import default_storage as storage
from django.core.files.base import ContentFile, File
from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError, transaction
from django.shortcuts import get_object_or_404

Expand All @@ -25,7 +26,7 @@
from pulpcore.plugin.models import Artifact, ContentArtifact, UploadChunk
from pulpcore.plugin.files import PulpTemporaryUploadedFile
from pulpcore.plugin.tasking import add_and_remove, dispatch
from pulpcore.plugin.util import get_objects_for_user
from pulpcore.plugin.util import get_objects_for_user, get_url
from rest_framework.exceptions import (
AuthenticationFailed,
NotAuthenticated,
Expand Down Expand Up @@ -291,32 +292,7 @@ def get_dr_push(self, request, path, create=False):
distribution = models.ContainerDistribution.objects.get(base_path=path)
except models.ContainerDistribution.DoesNotExist:
if create:
try:
with transaction.atomic():
repo_serializer = serializers.ContainerPushRepositorySerializer(
data={"name": path}, context={"request": request}
)
repo_serializer.is_valid(raise_exception=True)
repository = repo_serializer.create(repo_serializer.validated_data)
repo_href = serializers.ContainerPushRepositorySerializer(
repository, context={"request": request}
).data["pulp_href"]

dist_serializer = serializers.ContainerDistributionSerializer(
data={"base_path": path, "name": path, "repository": repo_href}
)
dist_serializer.is_valid(raise_exception=True)
distribution = dist_serializer.create(dist_serializer.validated_data)
except ValidationError:
raise RepositoryInvalid(name=path)
except IntegrityError:
# Seems like another process created our stuff already. Retry fetching it.
distribution = models.ContainerDistribution.objects.get(base_path=path)
repository = distribution.repository
if repository:
repository = repository.cast()
if not repository.PUSH_ENABLED:
raise RepositoryInvalid(name=path, message="Repository is read-only.")
distribution, repository = self.create_dr(path, request)
else:
raise RepositoryNotFound(name=path)
else:
Expand Down Expand Up @@ -349,6 +325,32 @@ def get_dr_push(self, request, path, create=False):
raise RepositoryNotFound(name=path)
return distribution, repository

@transaction.atomic
def create_dr(self, path, request):
try:
repository = serializers.ContainerPushRepositorySerializer.get_or_create({"name": path})
except ObjectDoesNotExist:
# The repository of the push type could not be found or could not be created
raise RepositoryInvalid(name=path)

dist_serializer = serializers.ContainerDistributionSerializer(
data={"base_path": path, "name": path, "repository": get_url(repository)},
context={"request": request},
)
try:
dist_serializer.is_valid(raise_exception=True)
distribution = dist_serializer.create(dist_serializer.validated_data)
except (IntegrityError, ValidationError):
# seems like another process created our stuff already. Retry fetching it.
distribution = models.ContainerDistribution.objects.get(base_path=path)
repository = distribution.repository
if repository:
repository = repository.cast()
if not repository.PUSH_ENABLED:
raise RepositoryInvalid(name=path, message="Repository is read-only.")

return distribution, repository


class BearerTokenView(APIView):
"""
Expand Down
2 changes: 1 addition & 1 deletion pulp_container/app/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class Meta:
model = models.ContainerRepository


class ContainerPushRepositorySerializer(RepositorySerializer):
class ContainerPushRepositorySerializer(RepositorySerializer, GetOrCreateSerializerMixin):
"""
Serializer for Container Push Repositories.
"""
Expand Down

0 comments on commit ef0d823

Please sign in to comment.