Skip to content

Commit

Permalink
WIP Add labels apis
Browse files Browse the repository at this point in the history
fixes pulp#3332
  • Loading branch information
mdellweg committed Aug 30, 2023
1 parent 2d02e9f commit e0a139c
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGES/3332.feature
@@ -0,0 +1 @@
Added set_label and delets_label endpoints to allow manipulating individual labels synchronously.
4 changes: 3 additions & 1 deletion pulpcore/app/serializers/__init__.py
Expand Up @@ -4,20 +4,22 @@

from .base import (
AsyncOperationResponseSerializer,
DeleteLabelSerializer,
DetailIdentityField,
DetailRelatedField,
DomainUniqueValidator,
GetOrCreateSerializerMixin,
HiddenFieldsMixin,
IdentityField,
ModelSerializer,
NestedIdentityField,
NestedRelatedField,
RelatedField,
RelatedResourceField,
SetLabelSerializer,
TaskGroupOperationResponseSerializer,
ValidateFieldsMixin,
validate_unknown_fields,
HiddenFieldsMixin,
)
from .fields import (
BaseURLField,
Expand Down
24 changes: 24 additions & 0 deletions pulpcore/app/serializers/base.py
Expand Up @@ -504,3 +504,27 @@ class TaskGroupOperationResponseSerializer(serializers.Serializer):
view_name="task-groups-detail",
allow_null=False,
)


class DeleteLabelSerializer(serializers.Serializer):
"""
Serializer for synchronously setting a label.
"""

label = serializers.SlugField(required=True)

def validate_label(self, value):
if value not in self.context["content_object"].pulp_labels:
raise serializers.ValidationError(
_("Label '{label}' is not set on the object.").format(label=value)
)
return value


class SetLabelSerializer(serializers.Serializer):
"""
Serializer for synchronously setting a label.
"""

label = serializers.SlugField(required=True)
value = serializers.CharField(required=True, allow_null=True, allow_blank=True)
1 change: 1 addition & 0 deletions pulpcore/app/viewsets/__init__.py
Expand Up @@ -2,6 +2,7 @@
AsyncCreateMixin,
AsyncRemoveMixin,
AsyncUpdateMixin,
LabelsMixin,
NamedModelViewSet,
RolesMixin,
NAME_FILTER_OPTIONS,
Expand Down
51 changes: 50 additions & 1 deletion pulpcore/app/viewsets/base.py
Expand Up @@ -4,6 +4,7 @@

from django.conf import settings
from django.db import transaction
from django.db.models.expressions import RawSQL
from django.core.exceptions import FieldError, ValidationError
from django.urls import Resolver404, resolve
from django.contrib.contenttypes.models import ContentType
Expand All @@ -20,7 +21,12 @@
from pulpcore.app.models.role import GroupRole, UserRole
from pulpcore.app.response import OperationPostponedResponse
from pulpcore.app.role_util import get_objects_for_user
from pulpcore.app.serializers import AsyncOperationResponseSerializer, NestedRoleSerializer
from pulpcore.app.serializers import (
AsyncOperationResponseSerializer,
NestedRoleSerializer,
DeleteLabelSerializer,
SetLabelSerializer,
)
from pulpcore.app.util import get_viewset_for_model
from pulpcore.tasking.tasks import dispatch

Expand Down Expand Up @@ -626,3 +632,46 @@ def my_permissions(self, request, pk=None):
".".join((app_label, codename)) for codename in request.user.get_all_permissions(obj)
]
return Response({"permissions": permissions})


class LabelsMixin:
@extend_schema(
summary="Set a label",
description="Set a single pulp_label on the object to a specific value or null.",
responses={
200: SetLabelSerializer,
},
)
@action(detail=True, methods=["put"], serializer_class=SetLabelSerializer)
def set_label(self, request, pk=None):
obj = self.get_object()
serializer = SetLabelSerializer(
data=request.data, context={"request": request, "content_object": obj}
)
serializer.is_valid(raise_exception=True)
obj._meta.model.objects.filter(pk=obj.pk).update(
pulp_labels=RawSQL(
"pulp_labels || hstore(%s, %s)",
[serializer.validated_data["label"], serializer.validated_data["value"]],
)
)
return Response(serializer.validated_data)

@extend_schema(
summary="Delete a label",
description="Delete a single pulp_label on the object.",
responses={
204: None,
},
)
@action(detail=True, methods=["post"], serializer_class=DeleteLabelSerializer)
def delete_label(self, request, pk=None):
obj = self.get_object()
serializer = DeleteLabelSerializer(
data=request.data, context={"request": request, "content_object": obj}
)
serializer.is_valid(raise_exception=True)
obj._meta.model.objects.filter(pk=obj.pk).update(
pulp_labels=RawSQL("pulp_labels - %s::text", [serializer.validated_data["label"]])
)
return Response(status=204)
2 changes: 2 additions & 0 deletions pulpcore/app/viewsets/publication.py
Expand Up @@ -27,6 +27,7 @@
AsyncCreateMixin,
AsyncRemoveMixin,
AsyncUpdateMixin,
LabelsMixin,
NamedModelViewSet,
RolesMixin,
)
Expand Down Expand Up @@ -434,6 +435,7 @@ class DistributionViewSet(
AsyncCreateMixin,
AsyncRemoveMixin,
AsyncUpdateMixin,
LabelsMixin,
):
"""
Provides read and list methods and also provides asynchronous CUD methods to dispatch tasks
Expand Down
4 changes: 3 additions & 1 deletion pulpcore/app/viewsets/repository.py
Expand Up @@ -30,6 +30,7 @@
from pulpcore.app.viewsets import (
AsyncRemoveMixin,
AsyncUpdateMixin,
LabelsMixin,
NamedModelViewSet,
)
from pulpcore.app.viewsets.base import (
Expand Down Expand Up @@ -168,7 +169,7 @@ class ImmutableRepositoryViewSet(
"""


class RepositoryViewSet(ImmutableRepositoryViewSet, AsyncUpdateMixin):
class RepositoryViewSet(ImmutableRepositoryViewSet, AsyncUpdateMixin, LabelsMixin):
"""
A ViewSet for an ordinary repository.
"""
Expand Down Expand Up @@ -369,6 +370,7 @@ class RemoteViewSet(
mixins.ListModelMixin,
AsyncUpdateMixin,
AsyncRemoveMixin,
LabelsMixin,
):
endpoint_name = "remotes"
serializer_class = RemoteSerializer
Expand Down
1 change: 1 addition & 0 deletions pulpcore/plugin/viewsets/__init__.py
Expand Up @@ -18,6 +18,7 @@
ImmutableRepositoryViewSet,
ImporterViewSet,
ImportViewSet,
LabelsMixin,
NamedModelViewSet,
NAME_FILTER_OPTIONS,
NULLABLE_NUMERIC_FILTER_OPTIONS,
Expand Down

0 comments on commit e0a139c

Please sign in to comment.