diff --git a/CHANGES/1275.misc b/CHANGES/1275.misc new file mode 100644 index 000000000..715055d3f --- /dev/null +++ b/CHANGES/1275.misc @@ -0,0 +1,2 @@ +Ensured repositories are correctly retrieved or initialized when handling client's parallel blob +uploading. diff --git a/pulp_container/app/registry_api.py b/pulp_container/app/registry_api.py index cda1cbcf9..a6289fea3 100644 --- a/pulp_container/app/registry_api.py +++ b/pulp_container/app/registry_api.py @@ -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 @@ -25,14 +26,13 @@ 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, PermissionDenied, ParseError, Throttled, - ValidationError, ) from rest_framework.generics import ListAPIView from rest_framework.pagination import BasePagination @@ -291,32 +291,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: @@ -349,6 +324,24 @@ def get_dr_push(self, request, path, create=False): raise RepositoryNotFound(name=path) return distribution, repository + def create_dr(self, path, request): + try: + with transaction.atomic(): + repository = serializers.ContainerPushRepositorySerializer.get_or_create( + {"name": path} + ) + distribution = serializers.ContainerDistributionSerializer.get_or_create( + {"base_path": path, "name": path}, {"repository": get_url(repository)} + ) + except ObjectDoesNotExist: + raise RepositoryInvalid(name=path) + + repository = repository.cast() + if not repository.PUSH_ENABLED: + raise RepositoryInvalid(name=path, message="Repository is read-only.") + + return distribution, repository + class BearerTokenView(APIView): """ diff --git a/pulp_container/app/serializers.py b/pulp_container/app/serializers.py index 87393a713..dd4de64d8 100644 --- a/pulp_container/app/serializers.py +++ b/pulp_container/app/serializers.py @@ -196,7 +196,7 @@ class Meta: model = models.ContainerRepository -class ContainerPushRepositorySerializer(RepositorySerializer): +class ContainerPushRepositorySerializer(RepositorySerializer, GetOrCreateSerializerMixin): """ Serializer for Container Push Repositories. """ @@ -277,7 +277,7 @@ class Meta: model = models.ContainerRemote -class ContainerDistributionSerializer(DistributionSerializer): +class ContainerDistributionSerializer(DistributionSerializer, GetOrCreateSerializerMixin): """ A serializer for ContainerDistribution. """