diff --git a/netbox_bgp/api/serializers.py b/netbox_bgp/api/serializers.py index f085dce..d0a0c61 100644 --- a/netbox_bgp/api/serializers.py +++ b/netbox_bgp/api/serializers.py @@ -8,6 +8,7 @@ from dcim.api.nested_serializers import NestedSiteSerializer, NestedDeviceSerializer from tenancy.api.nested_serializers import NestedTenantSerializer from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedASNSerializer, NestedPrefixSerializer +from ipam.api.field_serializers import IPNetworkField from netbox_bgp.models import ( @@ -31,7 +32,7 @@ def to_representation(self, value): class RoutingPolicySerializer(NetBoxModelSerializer): class Meta: model = RoutingPolicy - fields = '__all__' + fields = ['id', 'name', 'description'] class NestedRoutingPolicySerializer(WritableNestedSerializer): @@ -42,6 +43,7 @@ class Meta: fields = ['id', 'url', 'name', 'display', 'description'] validators = [] + class BGPPeerGroupSerializer(NetBoxModelSerializer): import_policies = SerializedPKRelatedField( queryset=RoutingPolicy.objects.all(), @@ -60,7 +62,7 @@ class BGPPeerGroupSerializer(NetBoxModelSerializer): class Meta: model = BGPPeerGroup - fields = '__all__' + fields = ['id', 'name', 'description', 'import_policies', 'export_policies'] class NestedBGPPeerGroupSerializer(WritableNestedSerializer): @@ -164,10 +166,12 @@ class Meta: model = PrefixList fields = ['id', 'url', 'display', 'name'] + class PrefixListSerializer(NetBoxModelSerializer): class Meta: model = PrefixList - fields = '__all__' + fields = ['id', 'name', 'description', 'family'] + class RoutingPolicyRuleSerializer(NetBoxModelSerializer): match_ip_address = SerializedPKRelatedField( @@ -189,11 +193,13 @@ class RoutingPolicyRuleSerializer(NetBoxModelSerializer): class Meta: model = RoutingPolicyRule - fields = '__all__' + fields = ['id', 'index', 'action', 'match_ip_address', 'routing_policy', 'match_community'] + class PrefixListRuleSerializer(NetBoxModelSerializer): prefix_list = NestedPrefixListSerializer() prefix = NestedPrefixSerializer(required=False, allow_null=True) + prefix_custom = IPNetworkField(required=False, allow_null=True) class Meta: model = PrefixListRule diff --git a/netbox_bgp/filters.py b/netbox_bgp/filters.py index 6922fb5..70dc396 100644 --- a/netbox_bgp/filters.py +++ b/netbox_bgp/filters.py @@ -7,38 +7,27 @@ from .models import Community, BGPSession, RoutingPolicy, RoutingPolicyRule, BGPPeerGroup, PrefixList, PrefixListRule from ipam.models import IPAddress, ASN -from dcim.models import Device +from dcim.models import Device, Site class CommunityFilterSet(NetBoxModelFilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() class Meta: model = Community - fields = ['value', 'description', 'status', 'tenant'] + fields = ['id', 'value', 'description', 'status', 'tenant'] def search(self, queryset, name, value): """Perform the filtered search.""" if not value.strip(): return queryset qs_filter = ( - Q(id__icontains=value) - | Q(value__icontains=value) + Q(value__icontains=value) | Q(description__icontains=value) ) return queryset.filter(qs_filter) class BGPSessionFilterSet(NetBoxModelFilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() remote_as = django_filters.ModelMultipleChoiceFilter( field_name='remote_as__asn', @@ -109,6 +98,18 @@ class BGPSessionFilterSet(NetBoxModelFilterSet): to_field_name='name', label='Device (name)', ) + site_id = django_filters.ModelMultipleChoiceFilter( + field_name='site__id', + queryset=Site.objects.all(), + to_field_name='id', + label='Site (ID)', + ) + site = django_filters.ModelMultipleChoiceFilter( + field_name='site__name', + queryset=Site.objects.all(), + to_field_name='name', + label='DSite (name)', + ) by_remote_address = django_filters.CharFilter( method='search_by_remote_ip', label='Remote Address', @@ -120,7 +121,7 @@ class BGPSessionFilterSet(NetBoxModelFilterSet): class Meta: model = BGPSession - fields = ['name', 'description', 'status', 'tenant'] + fields = ['id', 'name', 'description', 'status', 'tenant'] def search(self, queryset, name, value): """Perform the filtered search.""" @@ -154,15 +155,10 @@ def search_by_local_ip(self, queryset, name, value): class RoutingPolicyFilterSet(NetBoxModelFilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() class Meta: model = RoutingPolicy - fields = ['name', 'description'] + fields = ['id', 'name', 'description'] def search(self, queryset, name, value): """Perform the filtered search.""" @@ -175,12 +171,7 @@ def search(self, queryset, name, value): return queryset.filter(qs_filter) -class RoutingPolicyRuleFilterSet(django_filters.FilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() +class RoutingPolicyRuleFilterSet(NetBoxModelFilterSet): class Meta: model = RoutingPolicyRule @@ -191,8 +182,7 @@ def search(self, queryset, name, value): if not value.strip(): return queryset qs_filter = ( - Q(id__icontains=value) - | Q(index__icontains=value) + Q(index__icontains=value) | Q(action__icontains=value) | Q(description__icontains=value) | Q(routing_policy_id__icontains=value) @@ -201,16 +191,11 @@ def search(self, queryset, name, value): return queryset.filter(qs_filter) -class BGPPeerGroupFilterSet(django_filters.FilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() +class BGPPeerGroupFilterSet(NetBoxModelFilterSet): class Meta: model = BGPPeerGroup - fields = ['name', 'description'] + fields = ['id', 'name', 'description'] def search(self, queryset, name, value): """Perform the filtered search.""" @@ -224,15 +209,10 @@ def search(self, queryset, name, value): class PrefixListFilterSet(NetBoxModelFilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() class Meta: model = PrefixList - fields = ['name', 'description'] + fields = ['id', 'name', 'description'] def search(self, queryset, name, value): """Perform the filtered search.""" @@ -244,12 +224,7 @@ def search(self, queryset, name, value): ) return queryset.filter(qs_filter) -class PrefixListRuleFilterSet(django_filters.FilterSet): - q = django_filters.CharFilter( - method='search', - label='Search', - ) - tag = TagFilter() +class PrefixListRuleFilterSet(NetBoxModelFilterSet): class Meta: model = PrefixListRule @@ -261,8 +236,7 @@ def search(self, queryset, name, value): if not value.strip(): return queryset qs_filter = ( - Q(id__icontains=value) - | Q(index__icontains=value) + Q(index__icontains=value) | Q(action__icontains=value) #| Q(prefix_custom__icontains=value) | Q(ge__icontains=value) diff --git a/netbox_bgp/forms.py b/netbox_bgp/forms.py index 8f6be43..063ab08 100644 --- a/netbox_bgp/forms.py +++ b/netbox_bgp/forms.py @@ -3,7 +3,6 @@ from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist, ValidationError from django.utils.translation import gettext as _ -from extras.models import Tag from tenancy.models import Tenant from dcim.models import Device, Site from ipam.models import IPAddress, Prefix, ASN @@ -25,10 +24,6 @@ class CommunityForm(NetBoxModelForm): - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) status = forms.ChoiceField( required=False, choices=CommunityStatusChoices, @@ -114,10 +109,6 @@ class BGPSessionForm(NetBoxModelForm): max_length=64, required=True ) - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False @@ -236,6 +227,11 @@ class BGPSessionFilterForm(NetBoxModelFilterSetForm): required=False, label=_('Device') ) + site_id = DynamicModelMultipleChoiceField( + queryset=Site.objects.all(), + required=False, + label=_('Site') + ) status = forms.MultipleChoiceField( choices=SessionStatusChoices, required=False, @@ -280,10 +276,6 @@ class RoutingPolicyFilterForm(NetBoxModelFilterSetForm): class RoutingPolicyForm(NetBoxModelForm): - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) class Meta: model = RoutingPolicy @@ -315,10 +307,6 @@ class BGPPeerGroupForm(NetBoxModelForm): api_url='/api/plugins/bgp/routing-policy/' ) ) - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) class Meta: model = BGPPeerGroup @@ -361,7 +349,7 @@ class Meta: fields = [ 'routing_policy', 'index', 'action', 'continue_entry', 'match_community', 'match_ip_address', 'match_ipv6_address', 'match_custom', - 'set_actions', 'description', + 'set_actions', 'description', 'tags' ] @@ -376,10 +364,6 @@ class PrefixListFilterForm(NetBoxModelFilterSetForm): class PrefixListForm(NetBoxModelForm): - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) class Meta: model = PrefixList @@ -411,5 +395,5 @@ class Meta: fields = [ 'prefix_list', 'index', 'action', 'prefix', 'prefix_custom', - 'ge', 'le' + 'ge', 'le', 'tags' ] diff --git a/netbox_bgp/tests/test_api.py b/netbox_bgp/tests/test_api.py index 7dd998b..ee26ce4 100644 --- a/netbox_bgp/tests/test_api.py +++ b/netbox_bgp/tests/test_api.py @@ -14,7 +14,10 @@ from dcim.models import Site, DeviceRole, DeviceType, Manufacturer, Device, Interface from ipam.models import IPAddress, ASN, RIR -from netbox_bgp.models import Community, BGPPeerGroup, BGPSession +from netbox_bgp.models import ( + Community, BGPPeerGroup, BGPSession, + RoutingPolicy, RoutingPolicyRule, PrefixList, PrefixListRule +) class BaseTestCase(TestCase): @@ -278,4 +281,79 @@ def test_graphql_list(self): json.dumps({'query': query}), content_type='application/json' ) - self.assertEqual(response.status_code, status.HTTP_200_OK) \ No newline at end of file + self.assertEqual(response.status_code, status.HTTP_200_OK) + + +class RoutingPolicyTestCase(BaseTestCase): + def setUp(self): + super().setUp() + self.base_url_lookup = 'plugins-api:netbox_bgp-api:routingpolicy' + self.rp = RoutingPolicy.objects.create(name='rp1', description='test_rp') + + def test_list_routing_policy(self): + url = reverse(f'{self.base_url_lookup}-list') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 1) + + def test_get_routing_policy(self): + url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.rp.pk}) + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['name'], self.rp.name) + self.assertEqual(response.data['description'], self.rp.description) + + def test_create_routing_policy(self): + url = reverse(f'{self.base_url_lookup}-list') + data = {'name': 'testrp', 'description': 'test_rp1'} + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(RoutingPolicy.objects.get(pk=response.data['id']).name, 'testrp') + self.assertEqual(RoutingPolicy.objects.get(pk=response.data['id']).description, 'test_rp1') + + +class PrefixListTestCase(BaseTestCase): + def setUp(self): + super().setUp() + self.base_url_lookup = 'plugins-api:netbox_bgp-api:prefixlist' + self.obj = PrefixList.objects.create(name='pl1', description='test_pl', family='ipv4') + + def test_list_prefix_list(self): + url = reverse(f'{self.base_url_lookup}-list') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 1) + + def test_get_prefix_list(self): + url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.obj.pk}) + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['name'], self.obj.name) + self.assertEqual(response.data['description'], self.obj.description) + + def test_create_prefix_list(self): + url = reverse(f'{self.base_url_lookup}-list') + data = {'name': 'testrp', 'description': 'test_rp1', 'family': 'ipv4'} + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(PrefixList.objects.get(pk=response.data['id']).name, 'testrp') + self.assertEqual(PrefixList.objects.get(pk=response.data['id']).description, 'test_rp1') + + +class RoutingPolicyRuleTestCase(BaseTestCase): + pass + + +class PrefixListRuleTestCase(BaseTestCase): + pass + + +class TestAPISchema(BaseTestCase): + def setUp(self): + super().setUp() + self.base_url_lookup = 'schema' + + def test_api_schema(self): + url = reverse(f'{self.base_url_lookup}') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/netbox_bgp/version.py b/netbox_bgp/version.py index ae6db5f..fee46bd 100644 --- a/netbox_bgp/version.py +++ b/netbox_bgp/version.py @@ -1 +1 @@ -__version__ = "0.11.0" +__version__ = "0.11.1"