From 3d2e657675be1a4df90e724a081614f812ed3ad6 Mon Sep 17 00:00:00 2001 From: git-hyagi <45576767+git-hyagi@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:04:05 -0300 Subject: [PATCH] Handles a `PushRepository.DoesNotExist` exception fixes: #1712 --- CHANGES/1712.bugfix | 2 ++ docs/user/guides/push-image.md | 3 ++- pulp_container/app/registry_api.py | 24 +++++++++++++------ .../tests/functional/api/test_push_content.py | 21 ++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 CHANGES/1712.bugfix diff --git a/CHANGES/1712.bugfix b/CHANGES/1712.bugfix new file mode 100644 index 000000000..c323cb5ac --- /dev/null +++ b/CHANGES/1712.bugfix @@ -0,0 +1,2 @@ +Fixed an HTTP 500 error returned when pushing an image with the same name as the name of an existing +read-only repository. diff --git a/docs/user/guides/push-image.md b/docs/user/guides/push-image.md index 544e7083e..79d8bc979 100644 --- a/docs/user/guides/push-image.md +++ b/docs/user/guides/push-image.md @@ -47,7 +47,8 @@ X-Frame-Options: SAMEORIGIN !!! note Content is pushed to a push repository type. A push repository does not support mirroring of the - remote content via the Pulp API. + remote content via the Pulp API. Trying to push content with the same name as an existing + "regular" repository will fail. !!! note diff --git a/pulp_container/app/registry_api.py b/pulp_container/app/registry_api.py index 7b975d620..83c95e78e 100644 --- a/pulp_container/app/registry_api.py +++ b/pulp_container/app/registry_api.py @@ -17,6 +17,7 @@ from urllib.parse import urljoin, urlparse, urlunparse, parse_qs, urlencode from tempfile import NamedTemporaryFile +from django.core.exceptions import ObjectDoesNotExist from django.core.files.storage import default_storage as storage from django.core.files.base import ContentFile, File from django.db import IntegrityError, transaction @@ -320,9 +321,13 @@ def get_pull_through_drv(self, path): upstream_name = path.split(pull_through_cache_distribution.base_path, maxsplit=1)[1].strip( "/" ) - pull_through_remote = models.ContainerPullThroughRemote.objects.get( - pk=pull_through_cache_distribution.remote_id - ) + try: + pull_through_remote = models.ContainerPullThroughRemote.objects.get( + pk=pull_through_cache_distribution.remote_id + ) + except ObjectDoesNotExist: + raise RepositoryNotFound(name=path) + if not filter_resource( upstream_name, pull_through_remote.includes, pull_through_remote.excludes ): @@ -392,10 +397,15 @@ def get_dr_push(self, request, path, create=False): def create_dr(self, path, request): 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)} - ) + try: + 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, message="Repository is read-only.") if distribution.repository: dist_repository = distribution.repository.cast() diff --git a/pulp_container/tests/functional/api/test_push_content.py b/pulp_container/tests/functional/api/test_push_content.py index 3c761035d..baf659f62 100644 --- a/pulp_container/tests/functional/api/test_push_content.py +++ b/pulp_container/tests/functional/api/test_push_content.py @@ -27,6 +27,7 @@ ) from pulpcore.client.pulp_container import ( + ContainerContainerRepository, ContentManifestsApi, ContentTagsApi, DistributionsContainerApi, @@ -394,6 +395,26 @@ def test_push_matching_username( add_to_cleanup(container_namespace_api, distribution.namespace) +def test_push_to_existing_regular_repository( + container_repository_api, + gen_object_with_cleanup, + local_registry, + registry_client, +): + """ + Test the push to an existing non-push repository. + + It should fail to create a new push repository. + """ + gen_object_with_cleanup(container_repository_api, ContainerContainerRepository(name="foo")) + image_path = f"{REGISTRY_V2_REPO_PULP}:manifest_a" + local_url = "foo:1.0" + + registry_client.pull(image_path) + with pytest.raises(CalledProcessError): + local_registry.tag_and_push(image_path, local_url) + + class PushManifestListTestCase(PulpTestCase, rbac_base.BaseRegistryTest): """A test case that verifies if a container client can push manifest lists to the registry."""