Skip to content

Commit c4e9c19

Browse files
committed
Add v2 APIs for Farm
We have added several APIs for interacting with Farm, as well as Farm's hosts.
1 parent 07e8311 commit c4e9c19

24 files changed

+541
-25
lines changed

promgen/filters.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,17 @@ class RuleFilter(django_filters.rest_framework.FilterSet):
2323

2424

2525
class FarmFilter(django_filters.rest_framework.FilterSet):
26-
name = django_filters.CharFilter(field_name="name", lookup_expr="contains")
27-
source = django_filters.CharFilter(field_name="source", lookup_expr="exact")
26+
name = django_filters.CharFilter(
27+
field_name="name",
28+
lookup_expr="contains",
29+
help_text="Filter by farm name containing a specific substring. Example: name=Example Farm",
30+
)
31+
source = django_filters.ChoiceFilter(
32+
field_name="source",
33+
choices=[(name, name) for name, _ in models.Farm.driver_set()],
34+
lookup_expr="exact",
35+
help_text="Filter by exact source name. Example: source=Example Source",
36+
)
2837

2938
class UserFilter(django_filters.rest_framework.FilterSet):
3039
username = django_filters.CharFilter(

promgen/fixtures/testcases.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@
5353
fields:
5454
name: test-farm
5555
source: promgen
56+
- model: promgen.farm
57+
pk: 2
58+
fields:
59+
name: other-farm
60+
source: external
5661
- model: promgen.project
5762
pk: 1
5863
fields:
@@ -69,6 +74,11 @@
6974
service: 1
7075
shard: 1
7176
farm: 1
77+
- model: promgen.host
78+
pk: 1
79+
fields:
80+
name: example.com
81+
farm: 1
7282
- model: promgen.exporter
7383
pk: 1
7484
fields:

promgen/rest_v2.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,85 @@ class RuleViewSet(
173173
lookup_value_regex = "[^/]+"
174174
lookup_field = "id"
175175
pagination_class = PromgenPagination
176+
177+
178+
@extend_schema_view(
179+
list=extend_schema(summary="List Farms", description="Retrieve a list of all farms."),
180+
retrieve=extend_schema(
181+
summary="Retrieve Farm", description="Retrieve detailed information about a specific farm."
182+
),
183+
create=extend_schema(summary="Create Farm", description="Create a new farm."),
184+
update=extend_schema(summary="Update Farm", description="Update an existing farm."),
185+
partial_update=extend_schema(
186+
summary="Partially Update Farm", description="Partially update an existing farm."
187+
),
188+
destroy=extend_schema(summary="Delete Farm", description="Delete an existing farm."),
189+
)
190+
@extend_schema(tags=["Farm"])
191+
class FarmViewSet(viewsets.ModelViewSet):
192+
queryset = models.Farm.objects.all()
193+
filterset_class = filters.FarmFilter
194+
serializer_class = serializers.FarmRetrieveSerializer
195+
lookup_value_regex = "[^/]+"
196+
lookup_field = "id"
197+
pagination_class = PromgenPagination
198+
199+
@extend_schema(
200+
summary="List Hosts in Farm",
201+
description="Retrieve all hosts associated with the specified farm.",
202+
parameters=[
203+
OpenApiParameter(name="page_number", required=False, type=int),
204+
OpenApiParameter(name="page_size", required=False, type=int),
205+
],
206+
)
207+
@action(detail=True, methods=["get"])
208+
def hosts(self, request, id):
209+
farm = self.get_object()
210+
hosts = farm.host_set.all()
211+
page = self.paginate_queryset(hosts)
212+
return self.get_paginated_response(serializers.HostRetrieveSerializer(page, many=True).data)
213+
214+
@extend_schema(
215+
summary="List Projects in Farm",
216+
description="Retrieve all projects associated with the specified farm.",
217+
parameters=[
218+
OpenApiParameter(name="page_number", required=False, type=int),
219+
OpenApiParameter(name="page_size", required=False, type=int),
220+
],
221+
)
222+
@action(detail=True, methods=["get"])
223+
def projects(self, request, id):
224+
farm = self.get_object()
225+
projects = farm.project_set.all()
226+
page = self.paginate_queryset(projects)
227+
return self.get_paginated_response(
228+
serializers.ProjectRetrieveSerializer(page, many=True).data
229+
)
230+
231+
@extend_schema(
232+
summary="Register Hosts",
233+
description="Register new hosts for the specified farm.",
234+
request=serializers.HostListSerializer,
235+
responses=serializers.HostRetrieveSerializer(many=True),
236+
)
237+
@action(detail=True, methods=["post"], url_path="hosts/register", pagination_class=None)
238+
def register_host(self, request, id):
239+
farm = self.get_object()
240+
hostnames = request.data.get("hosts", [])
241+
for hostname in hostnames:
242+
models.Host.objects.get_or_create(name=hostname, farm_id=farm.id)
243+
return Response(serializers.HostRetrieveSerializer(farm.host_set, many=True).data)
244+
245+
@extend_schema(
246+
summary="Delete Hosts",
247+
description="Delete hosts from the specified farm.",
248+
request=serializers.HostListSerializer,
249+
responses=serializers.HostRetrieveSerializer(many=True),
250+
)
251+
@action(detail=True, methods=["post"], url_path="hosts/delete", pagination_class=None)
252+
def delete_host(self, request, id):
253+
farm = self.get_object()
254+
hostnames = request.data.get("hosts", [])
255+
for hostname in hostnames:
256+
farm.host_set.filter(name=hostname).delete()
257+
return Response(serializers.HostRetrieveSerializer(farm.host_set, many=True).data)

promgen/serializers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,21 @@ class RuleSerializer(serializers.ModelSerializer):
214214
class Meta:
215215
model = models.Rule
216216
exclude = ("object_id",)
217+
218+
219+
class HostRetrieveSerializer(serializers.ModelSerializer):
220+
class Meta:
221+
model = models.Host
222+
fields = "__all__"
223+
224+
225+
class FarmRetrieveSerializer(serializers.ModelSerializer):
226+
class Meta:
227+
model = models.Farm
228+
fields = "__all__"
229+
230+
231+
class HostListSerializer(serializers.Serializer):
232+
hosts = serializers.ListField(
233+
child=serializers.CharField(), help_text="List of hostnames to add."
234+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": 3,
3+
"name": "new-farm",
4+
"source": "promgen"
5+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"count": 2,
3+
"next": null,
4+
"previous": null,
5+
"results": [
6+
{
7+
"id": 2,
8+
"name": "other-farm",
9+
"source": "external"
10+
},
11+
{
12+
"id": 1,
13+
"name": "test-farm",
14+
"source": "promgen"
15+
}
16+
]
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"farm": 1,
4+
"id": 1,
5+
"name": "example.com"
6+
},
7+
{
8+
"farm": 1,
9+
"id": 2,
10+
"name": "new-host"
11+
}
12+
]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": 1,
3+
"name": "test-farm",
4+
"source": "promgen"
5+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"count": 1,
3+
"next": null,
4+
"previous": null,
5+
"results": [
6+
{
7+
"id": 1,
8+
"name": "test-farm",
9+
"source": "promgen"
10+
}
11+
]
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"count": 1,
3+
"next": null,
4+
"previous": null,
5+
"results": [
6+
{
7+
"id": 1,
8+
"name": "test-farm",
9+
"source": "promgen"
10+
}
11+
]
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"count": 1,
3+
"next": null,
4+
"previous": null,
5+
"results": [
6+
{
7+
"farm": 1,
8+
"id": 1,
9+
"name": "example.com"
10+
}
11+
]
12+
}

promgen/tests/examples/rest.farm.json

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"count": 2,
3+
"next": "http://testserver/rest/v2/farms/?page_number=2&page_size=1",
4+
"previous": null,
5+
"results": [
6+
{
7+
"id": 2,
8+
"name": "other-farm",
9+
"source": "external"
10+
}
11+
]
12+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": 1,
3+
"name": "new-new-name",
4+
"source": "new-source"
5+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"count": 2,
3+
"next": null,
4+
"previous": null,
5+
"results": [
6+
{
7+
"description": "",
8+
"farm": "test-farm",
9+
"id": 2,
10+
"name": "another-project",
11+
"owner": "admin",
12+
"service": "test-service",
13+
"shard": "test-shard"
14+
},
15+
{
16+
"description": "",
17+
"farm": "test-farm",
18+
"id": 1,
19+
"name": "test-project",
20+
"owner": "admin",
21+
"service": "test-service",
22+
"shard": "test-shard"
23+
}
24+
]
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[
2+
{
3+
"farm": 1,
4+
"id": 1,
5+
"name": "example.com"
6+
},
7+
{
8+
"farm": 1,
9+
"id": 2,
10+
"name": "new-host"
11+
},
12+
{
13+
"farm": 1,
14+
"id": 3,
15+
"name": "new-host-2"
16+
}
17+
]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": 1,
3+
"name": "new-name",
4+
"source": "new-source"
5+
}

promgen/tests/examples/rest.farm.1.json renamed to promgen/tests/examples/rest.farm.v1.detail.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"source": "promgen",
66
"hosts": [
77
{
8-
"name": "host.example.com",
9-
"url": "http://promgen.example.com/host/host.example.com"
8+
"name": "example.com",
9+
"url": "http://promgen.example.com/host/example.com"
1010
}
1111
]
1212
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"id": 1,
4+
"name": "test-farm",
5+
"source": "promgen",
6+
"url": "http://promgen.example.com/farm/1"
7+
}
8+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"id": 2,
4+
"name": "other-farm",
5+
"source": "external",
6+
"url": "http://promgen.example.com/farm/2"
7+
},
8+
{
9+
"id": 1,
10+
"name": "test-farm",
11+
"source": "promgen",
12+
"url": "http://promgen.example.com/farm/1"
13+
}
14+
]

promgen/tests/test_host_add.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ def test_newline(self):
2121
{"hosts": "\naaa.example.com\nbbb.example.com\nccc.example.com \n"},
2222
follow=False,
2323
)
24-
self.assertCount(models.Host, 3, "Expected 3 hosts")
24+
self.assertCount(models.Host, 4, "Expected 4 hosts (Fixture has one host)")
2525

2626
def test_comma(self):
2727
self.client.post(
2828
reverse("hosts-add", args=[1]),
2929
{"hosts": ",,aaa.example.com, bbb.example.com,ccc.example.com,"},
3030
follow=False,
3131
)
32-
self.assertCount(models.Host, 3, "Expected 3 hosts")
32+
self.assertCount(models.Host, 4, "Expected 4 hosts (Fixture has one host)")
3333

3434
# Within our new host code, the hosts are split (by newline or comma) and then
3535
# individually tested. Here we will test our validator on specific entries that

0 commit comments

Comments
 (0)