Skip to content

Commit

Permalink
WIP: Remove api v2
Browse files Browse the repository at this point in the history
Removed the routing from urls.

fixes #691
  • Loading branch information
mdellweg committed Dec 11, 2023
1 parent 7fa7fdf commit 9e3cf4b
Show file tree
Hide file tree
Showing 7 changed files with 6 additions and 736 deletions.
1 change: 1 addition & 0 deletions CHANGES/691.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed the galaxy v2 apis. The v3 apis should be used instead.
145 changes: 0 additions & 145 deletions pulp_ansible/app/galaxy/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,148 +52,3 @@ def get_source(self, obj) -> str:
class Meta:
fields = ("name", "source")
model = Role


class GalaxyCollectionSerializer(serializers.Serializer):
"""
A serializer for a Collection.
"""

id = serializers.CharField(source="pulp_id")
name = serializers.CharField()
namespace = serializers.SerializerMethodField()
href = serializers.SerializerMethodField(read_only=True)
versions_url = serializers.SerializerMethodField(read_only=True)
created = serializers.DateTimeField(source="pulp_created")
modified = serializers.DateTimeField(source="pulp_last_updated")
latest_version = serializers.SerializerMethodField()

@extend_schema_field(OpenApiTypes.OBJECT)
def get_namespace(self, obj):
"""Create a namespace dict."""
return {"name": obj.namespace}

def get_versions_url(self, obj) -> str:
"""
Get versions_url.
"""
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/{name}/"
"versions/".format(
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.namespace,
name=obj.name,
)
)

def get_href(self, obj) -> str:
"""
Get href.
"""
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/"
"{name}/".format(
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.namespace,
name=obj.name,
)
)

@extend_schema_field(OpenApiTypes.OBJECT)
def get_latest_version(self, obj):
"""
Get latest version.
"""
rv = obj.versions.filter(is_highest=True).first()
href = reverse(
"v2-collection-versions-detail",
kwargs={
"path": self.context["path"],
"namespace": obj.namespace,
"name": obj.name,
"version": rv.version,
},
)
return {"href": href, "version": rv.version}

class Meta:
fields = (
"id",
"href",
"name",
"namespace",
"versions_url",
"latest_version",
"created",
"modified",
)
model = Collection


class GalaxyCollectionVersionSerializer(serializers.Serializer):
"""
A serializer for a CollectionVersion.
"""

version = serializers.CharField()
href = serializers.SerializerMethodField(read_only=True)
namespace = serializers.SerializerMethodField(read_only=True)
collection = serializers.SerializerMethodField(read_only=True)
artifact = serializers.SerializerMethodField(read_only=True)
metadata = CollectionMetadataSerializer(source="*")

def get_href(self, obj) -> str:
"""
Get href.
"""
return (
"{hostname}/pulp_ansible/galaxy/{path}/api/v2/collections/{namespace}/{name}/"
"versions/{version}/".format(
path=self.context["path"],
hostname=settings.ANSIBLE_API_HOSTNAME,
namespace=obj.collection.namespace,
name=obj.collection.name,
version=obj.version,
)
)

@extend_schema_field(OpenApiTypes.OBJECT)
def get_namespace(self, obj):
"""Create a namespace dict."""
return {"name": obj.collection.namespace}

@extend_schema_field(OpenApiTypes.OBJECT)
def get_collection(self, obj):
"""Create a collection dict."""
return {"name": obj.collection.name}

@extend_schema_field(OpenApiTypes.OBJECT)
def get_artifact(self, obj):
"""Create an artifact dict."""
artifact = obj.contentartifact_set.get().artifact
return {"sha256": artifact.sha256, "size": artifact.size}

class Meta:
fields = ("version", "href", "metadata")
model = CollectionVersion


class GalaxyCollectionUploadSerializer(serializers.Serializer):
"""
A serializer for Collection Uploads.
"""

file = serializers.FileField(
help_text=_("The file containing the Artifact binary data."), required=True
)

def validate(self, data):
"""Ensure duplicate artifact isn't uploaded."""
data = super().validate(data)
sha256 = data["file"].hashers["sha256"].hexdigest()
artifact = Artifact.objects.filter(sha256=sha256).first()
if artifact:
raise serializers.ValidationError(_("Artifact already exists"))
return data
144 changes: 5 additions & 139 deletions pulp_ansible/app/galaxy/views.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
import re

from django.conf import settings
from django.shortcuts import get_object_or_404, HttpResponse
from django.shortcuts import get_object_or_404
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import generics, pagination, response, views
from rest_framework.reverse import reverse
from rest_framework import generics, response, views

from pulpcore.plugin.models import PulpTemporaryFile
from pulpcore.plugin.viewsets import OperationPostponedResponse
from pulpcore.plugin.models import ContentArtifact
from pulp_ansible.app.models import AnsibleDistribution, Role

from pulp_ansible.app.galaxy.mixins import UploadGalaxyCollectionMixin
from pulp_ansible.app.models import AnsibleDistribution, Collection, CollectionVersion, Role

from .serializers import (
GalaxyCollectionSerializer,
GalaxyCollectionUploadSerializer,
GalaxyCollectionVersionSerializer,
GalaxyRoleSerializer,
GalaxyRoleVersionSerializer,
)
from .serializers import GalaxyRoleSerializer, GalaxyRoleVersionSerializer


class DistributionMixin:
Expand Down Expand Up @@ -76,7 +63,7 @@ def get(self, request, **kwargs):
"""
Return a response to the "GET" action.
"""
available_versions = {"v1": "v1/", "v2": "v2/", "v3": "v3/"}
available_versions = {"v1": "v1/", "v3": "v3/"}
if self.v3_only:
available_versions = {"v3": "v3/"}

Expand Down Expand Up @@ -132,124 +119,3 @@ def get_queryset(self):
namespace, name = re.split(r"\.", self.kwargs["role_pk"])
versions = Role.objects.filter(pk__in=self._distro_content, name=name, namespace=namespace)
return versions


class GalaxyCollectionDetailView(DistributionMixin, generics.RetrieveAPIView):
"""
View for a Collection Detail.
"""

model = Collection
serializer_class = GalaxyCollectionSerializer
authentication_classes = []
permission_classes = []

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)
context = self.get_serializer_context()
return response.Response(GalaxyCollectionSerializer(collection, context=context).data)


class GalaxyCollectionView(DistributionMixin, UploadGalaxyCollectionMixin, generics.ListAPIView):
"""
View for Collection models.
"""

model = Collection
serializer_class = GalaxyCollectionSerializer
authentication_classes = []
permission_classes = []
pagination_class = pagination.PageNumberPagination

def get_queryset(self):
"""
Get the list of Collections for this view.
"""
return Collection.objects.filter(versions__pk__in=self._distro_content).distinct()

@extend_schema(deprecated=True)
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}
)
serializer.is_valid(raise_exception=True)

temp_file = PulpTemporaryFile.init_and_validate(serializer.validated_data["file"])
temp_file.save()

async_result = self._dispatch_import_collection_task(temp_file.pk, distro.repository)
return OperationPostponedResponse(async_result, request)


@extend_schema_view(get=extend_schema(operation_id="api_v2_collection_versions_list"))
class GalaxyCollectionVersionList(DistributionMixin, generics.ListAPIView):
"""
APIView for Collections by namespace/name.
"""

model = CollectionVersion
serializer_class = GalaxyCollectionVersionSerializer
pagination_class = pagination.PageNumberPagination
authentication_classes = []
permission_classes = []

def get_queryset(self):
"""
Get the list of items for this view.
"""
collection = get_object_or_404(
Collection, namespace=self.kwargs["namespace"], name=self.kwargs["name"]
)
versions = collection.versions.filter(pk__in=self._distro_content)

return versions


class GalaxyCollectionVersionDetail(DistributionMixin, generics.GenericAPIView):
"""
APIView for Galaxy Collections Detail view.
"""

authentication_classes = []
permission_classes = []

def get(self, request, path, namespace, name, version):
"""
Return a response to the "GET" action.
"""
version = CollectionVersion.objects.get(
collection__namespace=namespace, collection__name=name, version=version
)

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

# Normally would just pass request to reverse and DRF would automatically build the
# absolute URI for us. However there's a weird bug where, because there's a kwarg
# in the URL for this view called "version" (the collection version), DRF gets
# confused and thinks we're using a versioning scheme
# (https://www.django-rest-framework.org/api-guide/versioning/) and attempts to insert
# the version into kwargs, which causes the reverse lookup to fail.
path = reverse(
settings.ANSIBLE_URL_NAMESPACE + "collection-artifact-download",
kwargs={"distro_base_path": self.kwargs["path"], "filename": version.relative_path},
)
context = self.get_serializer_context()
request = context["request"]
download_url = request.build_absolute_uri(path)

data = GalaxyCollectionVersionSerializer(version, context=context).data
data["download_url"] = download_url
return response.Response(data)
20 changes: 0 additions & 20 deletions pulp_ansible/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
from django.urls import include, path, re_path

from pulp_ansible.app.galaxy.views import (
GalaxyCollectionVersionDetail,
GalaxyCollectionVersionList,
GalaxyCollectionDetailView,
GalaxyCollectionView,
GalaxyVersionView,
RoleList,
RoleVersionList,
Expand All @@ -25,21 +21,6 @@
path("roles/<str:role_pk>/versions/", RoleVersionList.as_view()),
]

v2_urls = [
path("collections/", GalaxyCollectionView.as_view()),
path("collections/<str:namespace>/<str:name>/", GalaxyCollectionDetailView.as_view()),
path("collections/<str:namespace>/<str:name>/versions/", GalaxyCollectionVersionList.as_view()),
path(
"collections/<str:namespace>/<str:name>/versions/<str:version>/",
GalaxyCollectionVersionDetail.as_view(),
name="v2-collection-versions-detail",
),
path(
"collection-imports/<uuid:pk>/",
views_v3.CollectionImportViewSet.as_view({"get": "retrieve"}),
),
]

# Legacy urls that need to be redirected to plugin/ansible/collections/<base_path>/
legacy_v3_collection_urls = [
path(
Expand Down Expand Up @@ -266,7 +247,6 @@
GalaxyVersionView.as_view(v3_only=True),
),
path(GALAXY_API_ROOT + "v1/", include(v1_urls)),
path(GALAXY_API_ROOT + "v2/", include(v2_urls)),
path(GALAXY_API_ROOT + "v3/", include(v3_urls)),
path(GALAXY_API_ROOT, GalaxyVersionView.as_view()),
re_path(r"^pulp/api/v3/ansible/copy/$", CopyViewSet.as_view({"post": "create"})),
Expand Down
Empty file.
Loading

0 comments on commit 9e3cf4b

Please sign in to comment.