Skip to content

Commit

Permalink
Fix 500 when distribution doesn't have a repository
Browse files Browse the repository at this point in the history
fixes: #909
  • Loading branch information
gerrod3 committed Apr 20, 2022
1 parent 1eabe05 commit 234364b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 61 deletions.
1 change: 1 addition & 0 deletions CHANGES/909.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed 500 error when accessing Galaxy APIs when distribution is not pointing to a repository.
10 changes: 5 additions & 5 deletions pulp_ansible/app/galaxy/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def get_source(self, obj) -> str:
"""
Get source.
"""
distro_base = self.context["request"].parser_context["kwargs"]["path"]
distro_base = self.context["path"]
distro_path = "".join([settings.CONTENT_ORIGIN, settings.CONTENT_PATH_PREFIX, distro_base])

return "".join([distro_path, "/", obj.relative_path])
Expand Down Expand Up @@ -79,7 +79,7 @@ def get_versions_url(self, obj) -> str:
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/{name}/"
"versions/".format(
path=obj.path,
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.namespace,
name=obj.name,
Expand All @@ -93,7 +93,7 @@ def get_href(self, obj) -> str:
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/"
"{name}/".format(
path=obj.path,
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.namespace,
name=obj.name,
Expand All @@ -109,7 +109,7 @@ def get_latest_version(self, obj):
href = reverse(
"collection-versions-detail",
kwargs={
"path": obj.path,
"path": self.context["path"],
"namespace": obj.namespace,
"name": obj.name,
"version": rv.version,
Expand Down Expand Up @@ -150,7 +150,7 @@ def get_href(self, obj) -> str:
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/{name}/"
"versions/{version}/".format(
path=obj.path,
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.collection.namespace,
name=obj.collection.name,
Expand Down
2 changes: 1 addition & 1 deletion pulp_ansible/app/galaxy/v3/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def _repository_version(self):
self.pulp_context = {path: distro.repository_version}
return distro.repository_version

repo_version = distro.repository.latest_version()
repo_version = distro.repository.latest_version() if distro.repository else None
self.pulp_context = {path: repo_version}
return repo_version

Expand Down
112 changes: 57 additions & 55 deletions pulp_ansible/app/galaxy/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re

from django.conf import settings
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, HttpResponse
from rest_framework import generics, pagination, response, views

from pulpcore.plugin.models import PulpTemporaryFile
Expand All @@ -20,6 +20,46 @@
)


class DistributionMixin:
"""
Mixin for getting the content for the view.
"""

@property
def _repository_version(self):
"""Returns repository version."""
path = self.kwargs["path"]

context = getattr(self, "pulp_context", None)
if context and context.get(path, None):
return self.pulp_context[path]

distro = get_object_or_404(AnsibleDistribution, base_path=path)
if distro.repository_version:
self.pulp_context = {path: distro.repository_version}
return distro.repository_version

repo_version = distro.repository.latest_version() if distro.repository else None
self.pulp_context = {path: repo_version}
return repo_version

@property
def _distro_content(self):
"""Returns distribution content."""
repo_version = self._repository_version
if repo_version is None:
return self.model.objects.none()

return repo_version.content

def get_serializer_context(self):
"""Inserts distribution path to a serializer context."""
context = super().get_serializer_context()
if "path" in self.kwargs:
context["path"] = self.kwargs["path"]
return context


class GalaxyVersionView(views.APIView):
"""
APIView for Galaxy versions.
Expand All @@ -46,7 +86,7 @@ def get(self, request, **kwargs):
return response.Response(api_info)


class RoleList(generics.ListAPIView):
class RoleList(DistributionMixin, generics.ListAPIView):
"""
APIView for Roles.
"""
Expand All @@ -60,13 +100,7 @@ def get_queryset(self):
"""
Get the list of items for this view.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=self.kwargs["path"])

if distro.repository_version:
distro_content = distro.repository_version.content
else:
distro_content = distro.repository.latest_version().content
roles = Role.objects.distinct("namespace", "name").filter(pk__in=distro_content)
roles = Role.objects.distinct("namespace", "name").filter(pk__in=self._distro_content)

namespace = self.request.query_params.get("owner__username", None)
if namespace:
Expand All @@ -78,7 +112,7 @@ def get_queryset(self):
return roles


class RoleVersionList(generics.ListAPIView):
class RoleVersionList(DistributionMixin, generics.ListAPIView):
"""
APIView for Role Versions.
"""
Expand All @@ -92,20 +126,12 @@ def get_queryset(self):
"""
Get the list of items for this view.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=self.kwargs["path"])

if distro.repository_version:
distro_content = distro.repository_version.content
else:
distro_content = distro.repository.latest_version().content
namespace, name = re.split(r"\.", self.kwargs["role_pk"])
versions = Role.objects.filter(pk__in=distro_content, name=name, namespace=namespace)
for version in versions:
version.distro_path = distro.base_path
versions = Role.objects.filter(pk__in=self._distro_content, name=name, namespace=namespace)
return versions


class GalaxyCollectionDetailView(generics.RetrieveAPIView):
class GalaxyCollectionDetailView(DistributionMixin, generics.RetrieveAPIView):
"""
View for a Collection Detail.
"""
Expand All @@ -119,12 +145,12 @@ def get(self, request, path=None, namespace=None, name=None):
"""
Get the detail view of a Collection.
"""
# This seems wrong, no repository scoping occurring
collection = get_object_or_404(Collection, namespace=namespace, name=name)
collection.path = path
return response.Response(GalaxyCollectionSerializer(collection).data)


class GalaxyCollectionView(generics.ListAPIView, UploadGalaxyCollectionMixin):
class GalaxyCollectionView(DistributionMixin, UploadGalaxyCollectionMixin, generics.ListAPIView):
"""
View for Collection models.
"""
Expand All @@ -139,24 +165,16 @@ def get_queryset(self):
"""
Get the list of Collections for this view.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=self.kwargs["path"])
if distro.repository_version:
distro_content = distro.repository_version.content
else:
distro_content = distro.repository.latest_version().content

collections = Collection.objects.filter(versions__pk__in=distro_content).distinct()

for c in collections:
c.path = self.kwargs["path"] # annotation needed by the serializer

return collections
return Collection.objects.filter(versions__pk__in=self._distro_content).distinct()

def post(self, request, path):
"""
Queues a task that creates a new Collection from an uploaded artifact.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=path)
if not distro.repository and not distro.repository_version:
return HttpResponse(status=400, reason="Distribution has no repository.")

serializer = GalaxyCollectionUploadSerializer(
data=request.data, context={"request": request}
)
Expand All @@ -169,7 +187,7 @@ def post(self, request, path):
return OperationPostponedResponse(async_result, request)


class GalaxyCollectionVersionList(generics.ListAPIView):
class GalaxyCollectionVersionList(DistributionMixin, generics.ListAPIView):
"""
APIView for Collections by namespace/name.
"""
Expand All @@ -184,24 +202,15 @@ def get_queryset(self):
"""
Get the list of items for this view.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=self.kwargs["path"])
if distro.repository_version:
distro_content = distro.repository_version.content
else:
distro_content = distro.repository.latest_version().content

collection = get_object_or_404(
Collection, namespace=self.kwargs["namespace"], name=self.kwargs["name"]
)
versions = collection.versions.filter(pk__in=distro_content)

for c in versions:
c.path = self.kwargs["path"] # annotation needed by the serializer
versions = collection.versions.filter(pk__in=self._distro_content)

return versions


class GalaxyCollectionVersionDetail(views.APIView):
class GalaxyCollectionVersionDetail(DistributionMixin, views.APIView):
"""
APIView for Galaxy Collections Detail view.
"""
Expand All @@ -213,27 +222,20 @@ def get(self, request, path, namespace, name, version):
"""
Return a response to the "GET" action.
"""
distro = get_object_or_404(AnsibleDistribution, base_path=self.kwargs["path"])
if distro.repository_version:
distro_content = distro.repository_version.content
else:
distro_content = distro.repository.latest_version().content

version = CollectionVersion.objects.get(
collection__namespace=namespace, collection__name=name, version=version
)

get_object_or_404(
ContentArtifact, content__in=distro_content, relative_path=version.relative_path
ContentArtifact, content__in=self._distro_content, relative_path=version.relative_path
)

download_url = "{content_hostname}/{base_path}/{relative_path}".format(
content_hostname=settings.ANSIBLE_CONTENT_HOSTNAME,
base_path=distro.base_path,
base_path=self.kwargs["path"],
relative_path=version.relative_path,
)

version.path = path
data = GalaxyCollectionVersionSerializer(version).data
data["download_url"] = download_url
return response.Response(data)

0 comments on commit 234364b

Please sign in to comment.