Skip to content

Commit

Permalink
Add retrieve functionality
Browse files Browse the repository at this point in the history
closes pulp#1010

In particular we are adding the new behaviour for:

- ReleaseArchitecture
- ReleaseComponent

but deliberately not for PackageReleaseComponent, which should only be
created indirectly using package actions.
  • Loading branch information
quba42 committed Feb 29, 2024
1 parent adabeae commit 359b7b1
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES/1010.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added retrieve functionality for ReleaseArchitecture and ReleaseComponent content.
2 changes: 2 additions & 0 deletions CHANGES/1010.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The API endpoints for ReleaseArchitecture and ReleaseComponent creation will no longer return a 400 ``non_field_errors`` if the content to be created already exists.
Instead a task is triggered that will list the existing content in its ``created_resources`` field.
30 changes: 30 additions & 0 deletions pulp_deb/app/serializers/content_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,21 @@ class ReleaseArchitectureSerializer(NoArtifactContentSerializer):
architecture = CharField(help_text="Name of the architecture.")
distribution = CharField(help_text="Name of the distribution.")

def get_unique_together_validators(self):
"""
We do not want UniqueTogetherValidator since we have retrieve logic!
"""
return []

def retrieve(self, validated_data):
"""
If the ReleaseArchitecture already exists, retrieve it!
"""
return ReleaseComponent.objects.filter(
architecture=validated_data["architecture"],
distribution=validated_data["distribution"],
).first()

class Meta(NoArtifactContentSerializer.Meta):
model = ReleaseArchitecture
fields = NoArtifactContentSerializer.Meta.fields + (
Expand All @@ -763,6 +778,21 @@ class ReleaseComponentSerializer(NoArtifactContentSerializer):
A Serializer for ReleaseComponent.
"""

def get_unique_together_validators(self):
"""
We do not want UniqueTogetherValidator since we have retrieve logic!
"""
return []

def retrieve(self, validated_data):
"""
If the ReleaseComponent already exists, retrieve it!
"""
return ReleaseComponent.objects.filter(
distribution=validated_data["distribution"],
component=validated_data["component"],
).first()

component = CharField(help_text="Name of the component.")
distribution = CharField(help_text="Name of the distribution.")

Expand Down
39 changes: 37 additions & 2 deletions pulp_deb/app/viewsets/content.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
from gettext import gettext as _ # noqa

from django_filters import Filter
from drf_spectacular.utils import extend_schema
from pulpcore.plugin.tasking import general_create
from pulpcore.plugin.models import Repository, RepositoryVersion
from pulpcore.plugin.serializers import AsyncOperationResponseSerializer
from pulpcore.plugin.serializers.content import ValidationError
from pulpcore.plugin.tasking import dispatch
from pulpcore.plugin.viewsets import (
NAME_FILTER_OPTIONS,
ContentFilter,
ContentViewSet,
NamedModelViewSet,
OperationPostponedResponse,
SingleArtifactContentUploadViewSet,
)
from pulpcore.plugin.viewsets.content import DefaultDeferredContextMixin

from pulp_deb.app import models, serializers


class NoArtifactContentViewSet(DefaultDeferredContextMixin, ContentViewSet):
"""A ViewSet for content creation that does not require a file to be uploaded."""

@extend_schema(
description="Trigger an asynchronous task to create content,"
"optionally create new repository version.",
responses={202: AsyncOperationResponseSerializer},
)
def create(self, request):
"""Create a content unit."""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)

exclusive_resources = [
item for item in (serializer.validated_data.get(key) for key in ("repository",)) if item
]

task = dispatch(
general_create,
exclusive_resources=exclusive_resources,
args=(self.queryset.model._meta.app_label, serializer.__class__.__name__),
kwargs={
"data": {k: v for k, v in request.data.items()},
"context": self.get_deferred_context(request),
},
)
return OperationPostponedResponse(task, request)


class GenericContentFilter(ContentFilter):
"""
FilterSet for GenericContent.
Expand Down Expand Up @@ -440,7 +475,7 @@ class Meta:
fields = ["architecture", "distribution"]


class ReleaseArchitectureViewSet(ContentViewSet):
class ReleaseArchitectureViewSet(NoArtifactContentViewSet):
# The doc string is a top level element of the user facing REST API documentation:
"""
A ReleaseArchitecture represents a single dpkg architecture string.
Expand Down Expand Up @@ -479,7 +514,7 @@ class Meta:
fields = ["component", "distribution"]


class ReleaseComponentViewSet(ContentViewSet):
class ReleaseComponentViewSet(NoArtifactContentViewSet):
# The doc string is a top level element of the user facing REST API documentation:
"""
A ReleaseComponent represents a single APT repository component.
Expand Down

0 comments on commit 359b7b1

Please sign in to comment.