From b78c3fa3066ab9a7751ed7e668a283bbb59181b9 Mon Sep 17 00:00:00 2001 From: hoang Date: Mon, 18 Nov 2024 15:43:38 +0700 Subject: [PATCH] Implement retrieval "Farm" APIs --- promgen/filters.py | 17 +++++++++++++ promgen/rest.py | 22 ++++++++++++++++- promgen/serializers.py | 16 +++++++++++++ promgen/tests/test_rest.py | 49 ++++++++++++++++++++++++++++++++++++++ promgen/urls.py | 1 + 5 files changed, 104 insertions(+), 1 deletion(-) diff --git a/promgen/filters.py b/promgen/filters.py index 39354798f..f3e4dfbf8 100644 --- a/promgen/filters.py +++ b/promgen/filters.py @@ -1,3 +1,5 @@ +from distutils.util import strtobool + import django_filters @@ -19,3 +21,18 @@ 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(method="filter_by_name") + source = django_filters.CharFilter(field_name="source", lookup_expr="exact") + + def filter_by_name(self, queryset, name, value): + name_exact_match_param = self.request.GET.get('name_exact_match', 'true') + name_exact_match = strtobool(name_exact_match_param) + if name_exact_match: + lookup_expr = 'exact' + else: + lookup_expr = 'contains' + filter_kwargs = {f'name__{lookup_expr}': value} + return queryset.filter(**filter_kwargs) diff --git a/promgen/rest.py b/promgen/rest.py index a080dbd10..3a396c71a 100644 --- a/promgen/rest.py +++ b/promgen/rest.py @@ -1,6 +1,6 @@ # 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 +110,23 @@ def targets(self, request, name): prometheus.render_config(project=self.get_object()), content_type="application/json", ) + + +class FarmViewSet(NotifierMixin, RuleMixin, 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/test_rest.py b/promgen/tests/test_rest.py index 18ff2775f..b985a1c23 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,51 @@ 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): + response = self.client.get(reverse("api:farm-list")) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]["id"], 1) + self.assertEqual(response.data[0]["name"], "test-farm") + self.assertEqual(response.data[0]["source"], "promgen") + self.assertEqual(response.data[0]["url"], "http://promgen.example.com/farm/1") + + response = self.client.get(reverse("api:farm-list"), {"name": "test-farm"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + + response = self.client.get(reverse("api:farm-list"), {"source": "promgen"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + + response = self.client.get(reverse("api:farm-list"), {"name": "farm", "name_exact_match": "false"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + + response = self.client.get(reverse("api:farm-list"), {"source": "other-source"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 0) + + response = self.client.get(reverse("api:farm-list"), {"name": "farm", "name_exact_match": "true"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 0) + + response = self.client.get(reverse("api:farm-list"), {"name": "farm"}) + 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) + + response = self.client.get(reverse("api:farm-detail", args=[1])) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data["id"], 1) + self.assertEqual(response.data["name"], "test-farm") + self.assertEqual(response.data["source"], "promgen") + self.assertEqual(response.data["url"], "http://promgen.example.com/farm/1") + self.assertEqual(len(response.data["hosts"]), 1) + self.assertEqual(response.data["hosts"][0]["url"], "http://promgen.example.com/host/host.example.com") + self.assertEqual(response.data["hosts"][0]["name"], "host.example.com") 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 = [