From 71c2ef020cb5364a02d3c96f5762bf63c9a5e9fc Mon Sep 17 00:00:00 2001 From: Vincent Simonin <vincent.simonin@ext.ec.europa.eu> Date: Mon, 20 Nov 2023 10:33:05 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Made=20protocol=20and=20array=20of?= =?UTF-8?q?=20choice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Available choices: "http_https" and "websocket" --- .../netbox_rps_plugin/api/serializers.py | 2 +- .../netbox_rps_plugin/filtersets.py | 5 +- .../netbox_rps_plugin/forms.py | 8 +- ..._options_alter_mapping_options_and_more.py | 10 ++- .../netbox_rps_plugin/models.py | 23 +++-- .../netbox_rps_plugin/tables.py | 4 +- .../templates/netbox_rps_plugin/mapping.html | 2 +- .../tests/e2e/test_mapping_creation.py | 2 +- .../tests/e2e/test_mapping_protocols.py | 84 +++++++++++++++++++ 9 files changed, 121 insertions(+), 19 deletions(-) create mode 100644 plugins/netbox-rps-plugin/tests/e2e/test_mapping_protocols.py diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/api/serializers.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/api/serializers.py index ddbd1a1..8b59c3e 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/api/serializers.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/api/serializers.py @@ -123,7 +123,7 @@ class MappingSerializer(NetBoxModelSerializer): "proxy_cache", "proxy_read_timeout", "client_max_body_size", - "protocol", + "protocols", "sorry_page", "custom_fields", "created", diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/filtersets.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/filtersets.py index 5af9c7e..75b2202 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/filtersets.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/filtersets.py @@ -1,5 +1,6 @@ """Filtersets definitions""" +from django_filters import filters from netbox.filtersets import NetBoxModelFilterSet from django.db.models import Q from .models import Mapping, HttpHeader @@ -8,6 +9,8 @@ from .models import Mapping, HttpHeader class MappingFilterSet(NetBoxModelFilterSet): """Mapping filterset definition class""" + protocols = filters.CharFilter(lookup_expr="icontains") + class Meta: model = Mapping fields = ( @@ -17,7 +20,7 @@ class MappingFilterSet(NetBoxModelFilterSet): "target", "Comment", "webdav", - "protocol", + "protocols", "testingpage", "gzip_proxied", "keepalive_requests", diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/forms.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/forms.py index 09b1cde..eb869af 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/forms.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/forms.py @@ -23,6 +23,8 @@ from .models import ( class MappingForm(NetBoxModelForm): """Mapping form definition class""" + protocols = forms.MultipleChoiceField(choices=ProtocolChoices) + class Meta: model = Mapping fields = ( @@ -30,7 +32,7 @@ class MappingForm(NetBoxModelForm): "target", "authentication", "webdav", - "protocol", + "protocols", "testingpage", "gzip_proxied", "keepalive_requests", @@ -57,7 +59,7 @@ class MappingForm(NetBoxModelForm): "proxy_read_timeout": " Proxy read timeout (s)", "client_max_body_size": "Client max body size (MB)", "sorry_page": "Sorry Page URL", - "protocol": "Protocol", + "protocols": "Protocols", } @@ -78,7 +80,7 @@ class MappingFilterForm(NetBoxModelFilterSetForm): webdav = forms.BooleanField( required=False, widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES) ) - protocol = forms.MultipleChoiceField( + protocols = forms.MultipleChoiceField( choices=ProtocolChoices, required=False, ) diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0010_alter_httpheader_options_alter_mapping_options_and_more.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0010_alter_httpheader_options_alter_mapping_options_and_more.py index 1c86d06..faef190 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0010_alter_httpheader_options_alter_mapping_options_and_more.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0010_alter_httpheader_options_alter_mapping_options_and_more.py @@ -1,9 +1,11 @@ """Migration File""" # pylint: disable=C0103 +import django.contrib.postgres.fields import django.core.validators from django.db import migrations, models import django.db.models.deletion +import netbox_rps_plugin.models class Migration(migrations.Migration): @@ -28,8 +30,12 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name="mapping", - name="protocol", - field=models.CharField(default="http_https", max_length=32), + name="protocols", + field=django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=32), + default=netbox_rps_plugin.models.default_protocol, + size=None, + ), ), migrations.AlterField( model_name="httpheader", diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py index f1a8753..a647b47 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py @@ -4,6 +4,7 @@ from django.conf import settings from django.db import models from django.urls import reverse from django.core.validators import URLValidator, MaxValueValidator, MinValueValidator +from django.contrib.postgres.fields.array import ArrayField from netbox.models import NetBoxModel from utilities.choices import ChoiceSet @@ -43,14 +44,20 @@ class ProtocolChoices(ChoiceSet): key = "Mapping.protocol" - DEFAULT_VALUE = "http_https" + HTTP_HTTPS = "http_https" + WEBSOCKET = "websocket" CHOICES = [ - ("http_https", "HTTP / HTTPS", "dark"), - ("websocket", "Websocket", "blue"), + (HTTP_HTTPS, "HTTP / HTTPS", "dark"), + (WEBSOCKET, "Websocket", "blue"), ] +def default_protocol(): + """Return the default protocols""" + return [ProtocolChoices.HTTP_HTTPS] + + class Mapping(NetBoxModel): """Mapping definition class""" @@ -105,12 +112,12 @@ class Mapping(NetBoxModel): validators=[URLValidator(message="It must be a url")], default=DEFAULT_SORRY_PAGE, ) - protocol = models.CharField( - max_length=32, - choices=ProtocolChoices, - default=ProtocolChoices.DEFAULT_VALUE, + protocols = ArrayField( + base_field=models.CharField(max_length=32, choices=ProtocolChoices), + null=False, blank=False, - verbose_name="Protocol", + verbose_name="Protocols", + default=default_protocol, ) class Meta: diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/tables.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/tables.py index 82ad1dd..eee2f2a 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/tables.py +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/tables.py @@ -27,7 +27,7 @@ class MappingTable(NetBoxTable): "authentication", "testingpage", "webdav", - "protocol", + "protocols", "Comment", "gzip_proxied", "keepalive_requests", @@ -46,7 +46,7 @@ class MappingTable(NetBoxTable): "target", "authentication", "webdav", - "protocol", + "protocols", "gzip_proxied", "keepalive_requests", "keepalive_timeout", diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/templates/netbox_rps_plugin/mapping.html b/plugins/netbox-rps-plugin/netbox_rps_plugin/templates/netbox_rps_plugin/mapping.html index 6fd40a6..27ef305 100644 --- a/plugins/netbox-rps-plugin/netbox_rps_plugin/templates/netbox_rps_plugin/mapping.html +++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/templates/netbox_rps_plugin/mapping.html @@ -68,7 +68,7 @@ </tr> <tr> <th scope="row">Protocol</th> - <td>{{ object.get_protocol_display|placeholder }}</td> + <td>{{ object.protocols|placeholder }}</td> </tr> <tr> <th scope="row">Comment</th> diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py index c70afbb..2ba1bb2 100644 --- a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py +++ b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py @@ -54,7 +54,7 @@ class TestMappingCreation(Base): content = json.loads(response.content) self.assertEqual(content["authentication"], "none") - self.assertEqual(content["protocol"], "http_https") + self.assertEqual(content["protocols"], ["http_https"]) if __name__ == "__main__": diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_protocols.py b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_protocols.py new file mode 100644 index 0000000..7b2e2cb --- /dev/null +++ b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_protocols.py @@ -0,0 +1,84 @@ +"""Test case for Mapping protocols""" + +import unittest +import json +import os +import requests +from .base import Base + + +HOST = os.getenv("HOST", default="localhost") +PORT = os.getenv("PORT", default="8080") +API_KEY = os.getenv("API_KEY", "only4testingpurpose") + + +class TestMappingProtocols(Base): + """Test case for Mapping protocols class""" + + def test_that_mapping_protocols_default_value_is_set(self) -> None: + """Test that mapping protocols default value is set""" + + response = requests.post( + url=f"http://{HOST}:{PORT}/api/plugins/rps/mapping/", + json={ + "source": "https://truc00.com/api", + "target": "http://10.10.10.10:1800/api", + }, + headers={"Authorization": f"Token {API_KEY}"}, + timeout=5, + ) + + self.assertEqual(response.status_code, 201) + + self.mapping_id = json.loads(response.content)["id"] + + content = json.loads(response.content) + + self.assertEqual(content["protocols"], ["http_https"]) + + def test_that_mapping_protocols_are_not_valid(self) -> None: + """Test that mapping protocols are not valid""" + + response = requests.post( + url=f"http://{HOST}:{PORT}/api/plugins/rps/mapping/", + json={ + "source": "https://truc00.com/api", + "target": "http://10.10.10.10:1800/api", + "protocols": ["thisisnotavalidprotocol", "websocket", "anotherone"], + }, + headers={"Authorization": f"Token {API_KEY}"}, + timeout=5, + ) + + self.assertEqual(response.status_code, 400) + self.assertEqual( + response.content, + b'{"protocols":{"0":["\\"thisisnotavalidprotocol\\" is not a valid choice."],' + + b'"2":["\\"anotherone\\" is not a valid choice."]}}', + ) + + def test_that_mapping_protocols_are_valid(self) -> None: + """Test that mapping protocols are not valid""" + + response = requests.post( + url=f"http://{HOST}:{PORT}/api/plugins/rps/mapping/", + json={ + "source": "https://truc00.com/api", + "target": "http://10.10.10.10:1800/api", + "protocols": ["http_https", "websocket"], + }, + headers={"Authorization": f"Token {API_KEY}"}, + timeout=5, + ) + + self.assertEqual(response.status_code, 201) + + self.mapping_id = json.loads(response.content)["id"] + + content = json.loads(response.content) + + self.assertEqual(content["protocols"], ["http_https", "websocket"]) + + +if __name__ == "__main__": + unittest.main() -- GitLab