From f4d617cfb982fef1f381ec3880a860eb0ad3493f Mon Sep 17 00:00:00 2001 From: hoang Date: Mon, 18 Nov 2024 15:43:38 +0700 Subject: [PATCH] Implement retrieval "Farm" APIs We intend to improve the UI/UX when adding a new Project by enhancing the registration process for Farms on the "Register Project" page. To prepare for this improvement, we have added two API endpoints to retrieve Farm's data. --- promgen/filters.py | 7 +++++ promgen/rest.py | 21 +++++++++++++ promgen/serializers.py | 16 ++++++++++ promgen/tests/examples/rest.farm.1.json | 12 ++++++++ promgen/tests/examples/rest.farm.json | 7 +++++ promgen/tests/test_rest.py | 39 +++++++++++++++++++++++++ promgen/urls.py | 1 + 7 files changed, 103 insertions(+) create mode 100644 promgen/tests/examples/rest.farm.1.json create mode 100644 promgen/tests/examples/rest.farm.json diff --git a/promgen/filters.py b/promgen/filters.py index 39354798f..7d22e7503 100644 --- a/promgen/filters.py +++ b/promgen/filters.py @@ -1,3 +1,5 @@ +from distutils.util import strtobool + import django_filters @@ -19,3 +21,8 @@ class RuleFilter(django_filters.rest_framework.FilterSet): name = django_filters.CharFilter(field_name="name", lookup_expr="contains") parent = django_filters.CharFilter(field_name="parent__name", lookup_expr="contains") enabled = django_filters.BooleanFilter(field_name="enabled") + + +class FarmFilter(django_filters.rest_framework.FilterSet): + name = django_filters.CharFilter(field_name="name", lookup_expr="contains") + source = django_filters.CharFilter(field_name="source", lookup_expr="exact") diff --git a/promgen/rest.py b/promgen/rest.py index a080dbd10..2e7624970 100644 --- a/promgen/rest.py +++ b/promgen/rest.py @@ -1,6 +1,7 @@ # Copyright (c) 2019 LINE Corporation # These sources are released under the terms of the MIT license: see LICENSE +from django.core.serializers import get_serializer from django.http import HttpResponse from django.views.generic import View from rest_framework import permissions, viewsets @@ -110,3 +111,23 @@ def targets(self, request, name): prometheus.render_config(project=self.get_object()), content_type="application/json", ) + + +class FarmViewSet(viewsets.ModelViewSet): + queryset = models.Farm.objects.all() + filterset_class = filters.FarmFilter + serializer_class = serializers.FarmSerializer + lookup_value_regex = "[^/]+" + lookup_field = "id" + + def retrieve(self, request, id): + farm = self.get_object() + farm_data = self.get_serializer(farm).data + + hosts = farm.host_set.all() + hosts_data = serializers.HostSerializer(hosts, many=True).data + farm_detail = { + **farm_data, + "hosts": hosts_data + } + return Response(farm_detail) diff --git a/promgen/serializers.py b/promgen/serializers.py index 7f32faa71..6ae6ccb8d 100644 --- a/promgen/serializers.py +++ b/promgen/serializers.py @@ -102,3 +102,19 @@ def to_representation(self, obj): "labels": obj.labels, "annotations": annotations, } + + +class FarmSerializer(serializers.ModelSerializer): + url = WebLinkField() + + class Meta: + model = models.Farm + fields = '__all__' + + +class HostSerializer(serializers.ModelSerializer): + url = WebLinkField() + + class Meta: + model = models.Host + exclude = ("id", "farm") diff --git a/promgen/tests/examples/rest.farm.1.json b/promgen/tests/examples/rest.farm.1.json new file mode 100644 index 000000000..19338e61c --- /dev/null +++ b/promgen/tests/examples/rest.farm.1.json @@ -0,0 +1,12 @@ +{ + "id": 1, + "url": "http://promgen.example.com/farm/1", + "name": "test-farm", + "source": "promgen", + "hosts": [ + { + "name": "host.example.com", + "url": "http://promgen.example.com/host/host.example.com" + } + ] +} \ No newline at end of file diff --git a/promgen/tests/examples/rest.farm.json b/promgen/tests/examples/rest.farm.json new file mode 100644 index 000000000..57dddaec7 --- /dev/null +++ b/promgen/tests/examples/rest.farm.json @@ -0,0 +1,7 @@ +[ + { + "id": 1, + "url": "http://promgen.example.com/farm/1", + "name": "test-farm","source":"promgen" + } +] \ No newline at end of file diff --git a/promgen/tests/test_rest.py b/promgen/tests/test_rest.py index 18ff2775f..04c77cf4c 100644 --- a/promgen/tests/test_rest.py +++ b/promgen/tests/test_rest.py @@ -3,6 +3,7 @@ from django.test import override_settings +from django.urls import reverse from promgen import models, rest, tests @@ -21,3 +22,41 @@ def test_alert(self): response = self.fireAlert() self.assertEqual(response.status_code, 202) self.assertCount(models.Alert, 1, "Alert Queued") + + @override_settings(PROMGEN=tests.SETTINGS) + def test_retrieve_farm(self): + expected = tests.Data("examples", "rest.farm.json").json() + + # Check retrieving all farms + response = self.client.get(reverse("api:farm-list")) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), expected) + + # Check retrieving all farms whose "name" contains "farm" + response = self.client.get(reverse("api:farm-list"), {"name": "farm"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), expected) + + # Check retrieving all farms whose "source" is "promgen" + response = self.client.get(reverse("api:farm-list"), {"source": "promgen"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), expected) + + # Check retrieving farms with a non-existent "name" returns an empty list + response = self.client.get(reverse("api:farm-list"), {"name": "other-name"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 0) + + # Check retrieving farms with a non-existent "source" returns an empty list + response = self.client.get(reverse("api:farm-list"), {"source": "other-source"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 0) + + + farm = models.Farm.objects.get(id=1) + models.Host.objects.create(name="host.example.com", farm=farm) + expected = tests.Data("examples", "rest.farm.1.json").json() + + # Check retrieving the farm whose "id" is "1", including the list of hosts. + response = self.client.get(reverse("api:farm-detail", args=[1])) + self.assertEqual(response.json(), expected) diff --git a/promgen/urls.py b/promgen/urls.py index 3f1ebc0ee..70b69252f 100644 --- a/promgen/urls.py +++ b/promgen/urls.py @@ -28,6 +28,7 @@ router.register("service", rest.ServiceViewSet) router.register("shard", rest.ShardViewSet) router.register("project", rest.ProjectViewSet) +router.register("farm", rest.FarmViewSet) urlpatterns = [