Repository: netbox-community/netbox-bgp (language: python)

Issue:
Fixes: #193 - add TenancyFilterset to Tenant filtered models

 * Fixes #193 - Adds TenancyFilterSet to Tenant filterable models to correct filtering bug


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 04b3846..436880d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ __pycache__
 dist
 build
 *.egg-info
+.idea/
\ No newline at end of file
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..1d3b141
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,1 @@
+*    @k01ek @cruse1977 @natm
diff --git a/README.md b/README.md
index c4c58f3..371a6f4 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ This plugin provide following Models:
 | NetBox 3.5  | >= 0.10.0 |
 | NetBox 3.6  | >= 0.11.0 |
 | NetBox 3.7  | >= 0.12.0 |
-| NetBox 4.0  | >= 0.13.0 |
+| NetBox 4.0  | >= 0.13.2 |
 
 ## Installation
 
diff --git a/develop/Dockerfile b/develop/Dockerfile
index f15dc4c..a2c56d2 100644
--- a/develop/Dockerfile
+++ b/develop/Dockerfile
@@ -1,4 +1,4 @@
-ARG python_ver=3.8
+ARG python_ver=3.12
 FROM python:${python_ver}
 
 ARG netbox_ver=master
diff --git a/netbox_bgp/choices.py b/netbox_bgp/choices.py
index d804e52..03d849e 100644
--- a/netbox_bgp/choices.py
+++ b/netbox_bgp/choices.py
@@ -2,34 +2,37 @@
 
 
 class CommunityStatusChoices(ChoiceSet):
+    key = "Community.status"
 
     STATUS_ACTIVE = 'active'
     STATUS_RESERVED = 'reserved'
     STATUS_DEPRECATED = 'deprecated'
 
-    CHOICES = (
+    CHOICES = [
         (STATUS_ACTIVE, 'Active', 'blue'),
         (STATUS_RESERVED, 'Reserved', 'cyan'),
         (STATUS_DEPRECATED, 'Deprecated', 'red'),
-     )
+    ]
 
 
 class SessionStatusChoices(ChoiceSet):
+    key = "Session.status"
 
     STATUS_OFFLINE = 'offline'
     STATUS_ACTIVE = 'active'
     STATUS_PLANNED = 'planned'
     STATUS_FAILED = 'failed'
 
-    CHOICES = (
+    CHOICES = [
         (STATUS_OFFLINE, 'Offline', 'orange'),
         (STATUS_ACTIVE, 'Active', 'green'),
         (STATUS_PLANNED, 'Planned', 'cyan'),
         (STATUS_FAILED, 'Failed', 'red'),
-    )
+    ]
 
 
 class ActionChoices(ChoiceSet):
+    key = "Action.status"
 
     CHOICES = [
         ('permit', 'Permit', 'green'),
@@ -38,6 +41,8 @@ class ActionChoices(ChoiceSet):
 
 
 class AFISAFIChoices(ChoiceSet):
+    key = "AFISAFI.options"
+
     AFISAFI_IPV4_UNICAST = 'ipv4-unicast'
     AFISAFI_IPV4_MULTICAST = 'ipv4-multicast'
     AFISAFI_IPV4_FLOWSPEC = 'ipv4-flowspec'
@@ -57,7 +62,7 @@ class AFISAFIChoices(ChoiceSet):
     AFISAFI_VPNV6_MULTICAST = 'vpnv6-multicast'
     AFISAFI_VPNV6_FLOWSPEC = 'vpnv6-flowspec'
 
-    CHOICES = (
+    CHOICES = [
         (AFISAFI_IPV4_UNICAST, 'IPv4 Unicast'),
         (AFISAFI_IPV4_MULTICAST, 'IPv4 Multicast'),
         (AFISAFI_IPV4_FLOWSPEC, 'IPv4 Flowspec'),
@@ -71,7 +76,7 @@ class AFISAFIChoices(ChoiceSet):
         (AFISAFI_VPNV6_UNICAST, 'VPNv6 Unicast'),
         (AFISAFI_VPNV6_MULTICAST, 'VPNv6 Multicast'),
         (AFISAFI_VPNV6_FLOWSPEC, 'VPNv6 Flowspec')
-    )
+    ]
 
 
 class IPAddressFamilyChoices(ChoiceSet):
diff --git a/netbox_bgp/filtersets.py b/netbox_bgp/filtersets.py
index b12b6ff..ae4b0a1 100644
--- a/netbox_bgp/filtersets.py
+++ b/netbox_bgp/filtersets.py
@@ -3,6 +3,7 @@
 from django.db.models import Q
 from netaddr.core import AddrFormatError
 from netbox.filtersets import NetBoxModelFilterSet
+from tenancy.filtersets import TenancyFilterSet
 
 from .models import (
     Community, BGPSession, RoutingPolicy, RoutingPolicyRule,
@@ -13,7 +14,7 @@
 from dcim.models import Device, Site
 
 
-class CommunityFilterSet(NetBoxModelFilterSet):
+class CommunityFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
 
     class Meta:
         model = Community
@@ -65,7 +66,7 @@ def search(self, queryset, name, value):
         return queryset.filter(qs_filter)
 
 
-class BGPSessionFilterSet(NetBoxModelFilterSet):
+class BGPSessionFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
 
     remote_as = django_filters.ModelMultipleChoiceFilter(
         field_name='remote_as__asn',
diff --git a/netbox_bgp/graphql/types.py b/netbox_bgp/graphql/types.py
index 716c01e..d44e858 100644
--- a/netbox_bgp/graphql/types.py
+++ b/netbox_bgp/graphql/types.py
@@ -36,7 +36,7 @@ class CommunityType(NetBoxObjectType):
     site: Annotated["SiteType", strawberry.lazy("dcim.graphql.types")] | None
     tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
     status: str
-    role: str
+    role: Annotated["RoleType", strawberry.lazy("ipam.graphql.types")] | None
     description: str
 
 
@@ -45,7 +45,7 @@ class BGPSessionType(NetBoxObjectType):
     name: str
     site: Annotated["SiteType", strawberry.lazy("dcim.graphql.types")] | None
     tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
-    device: Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")]
+    device: Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")] | None
     local_address: Annotated["IPAddressType", strawberry.lazy("ipam.graphql.types")]
     remote_address: Annotated["IPAddressType", strawberry.lazy("ipam.graphql.types")]
     local_as: Annotated["ASNType", strawberry.lazy("ipam.graphql.types")]
@@ -62,12 +62,8 @@ class BGPSessionType(NetBoxObjectType):
     export_policies: List[
         Annotated["RoutingPolicyType", strawberry.lazy("netbox_bgp.graphql.types")]
     ]
-    prefix_list_in: List[
-        Annotated["PrefixListType", strawberry.lazy("netbox_bgp.graphql.types")]
-    ]
-    prefix_list_out: List[
-        Annotated["PrefixListType", strawberry.lazy("netbox_bgp.graphql.types")]
-    ]
+    prefix_list_in: Annotated["PrefixListType", strawberry.lazy("netbox_bgp.graphql.types")] | None
+    prefix_list_out: Annotated["PrefixListType", strawberry.lazy("netbox_bgp.graphql.types")] | None
 
 
 @strawberry_django.type(BGPPeerGroup, fields="__all__", filters=BGPPeerGroupFilter)
@@ -98,7 +94,7 @@ class RoutingPolicyRuleType(NetBoxObjectType):
     index: BigInt
     action: str
     description: str
-    continue_entry: BigInt
+    continue_entry: BigInt | None
     match_community: List[
         Annotated["CommunityType", strawberry.lazy("netbox_bgp.graphql.types")]
     ]
@@ -127,8 +123,8 @@ class PrefixListRuleType(NetBoxObjectType):
     ]
     index: BigInt
     action: str
-    prefix: Annotated["PrefixType", strawberry.lazy("ipam.graphql.types")]
-    prefix_custom: str
+    prefix: Annotated["PrefixType", strawberry.lazy("ipam.graphql.types")] | None
+    prefix_custom: str | None
     ge: BigInt
     le: BigInt
     description: str
diff --git a/netbox_bgp/version.py b/netbox_bgp/version.py
index f23a6b3..83ce76f 100644
--- a/netbox_bgp/version.py
+++ b/netbox_bgp/version.py
@@ -1,1 +1,1 @@
-__version__ = "0.13.0"
+__version__ = "0.13.2"


Test patch:
diff --git a/netbox_bgp/tests/test_api.py b/netbox_bgp/tests/test_api.py
index 51f1036..56d0526 100644
--- a/netbox_bgp/tests/test_api.py
+++ b/netbox_bgp/tests/test_api.py
@@ -24,7 +24,7 @@
     IPAddressFamilyChoices,
     ActionChoices,
 )
-from netbox_bgp.choices import IPAddressFamilyChoices, SessionStatusChoices
+
 
 class CommunityAPITestCase(
     APIViewTestCases.GetObjectViewTestCase,
@@ -32,11 +32,12 @@ class CommunityAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = Community
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "url", "value"]
+    graphql_base_name = "netbox_bgp_community"
 
     create_data = [
         {"value": "65001:65000"},
@@ -64,11 +65,12 @@ class CommunityListAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = CommunityList
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "name", "url"]
+    graphql_base_name = "netbox_bgp_communitylist"
 
     create_data = [
         {"name": "CL1", "description": "cl1_api"},
@@ -96,11 +98,12 @@ class CommunityListRuleAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = CommunityListRule
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id"]
+    graphql_base_name = "netbox_bgp_communitylist_rule"
 
     bulk_update_data = {
         "description": "Test Community List rules desc",
@@ -172,11 +175,12 @@ class BGPPeerGroupAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = BGPPeerGroup
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "name", "url"]
+    graphql_base_name = "netbox_bgp_peer_group"
 
     create_data = [
         {
@@ -222,11 +226,12 @@ class BGPSessionAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = BGPSession
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "name", "url"]
+    graphql_base_name = "netbox_bgp_session"
 
     bulk_update_data = {
         "description": "Test BGP session desc",
@@ -353,11 +358,12 @@ class RoutingPolicyAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = RoutingPolicy
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "name", "url"]
+    graphql_base_name = "netbox_bgp_routing_policy"
 
     create_data = [
         {
@@ -403,11 +409,12 @@ class RoutingPolicyRuleAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = RoutingPolicyRule
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id"]
+    graphql_base_name = "netbox_bgp_routing_policy_rule"
 
     bulk_update_data = {
         "description": "Test Routing policy rules desc",
@@ -498,11 +505,12 @@ class PrefixListAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = PrefixList
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id", "name", "url"]
+    graphql_base_name = "netbox_bgp_prefixlist"
 
     create_data = [
         {
@@ -561,11 +569,12 @@ class PrefixListRuleAPITestCase(
     APIViewTestCases.CreateObjectViewTestCase,
     APIViewTestCases.UpdateObjectViewTestCase,
     APIViewTestCases.DeleteObjectViewTestCase,
-    # APIViewTestCases.GraphQLTestCase,
+    APIViewTestCases.GraphQLTestCase,
 ):
     model = PrefixListRule
     view_namespace = "plugins-api:netbox_bgp"
     brief_fields = ["description", "display", "id"]
+    graphql_base_name = "netbox_bgp_prefixlist_rule"
 
     bulk_update_data = {"description": "Test Prefix list rules desc", "action": "deny"}
 
@@ -646,12 +655,9 @@ def setUpTestData(cls):
         ]
 
 
-# class TestAPISchema(APITestCase):
-#     def setUp(self):
-#         super().setUp()
-#         self.base_url_lookup = 'schema'
+class TestAPISchema(APITestCase):
+    def test_api_schema(self):
+        url = reverse("plugins-api:netbox_bgp-api:api-root")
+        response = self.client.get(f"{url}?format=api", **self.header)
 
-#     def test_api_schema(self):
-#         url = reverse(f'{self.base_url_lookup}')
-#         response = self.client.get(url)
-#         self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.status_code, 200)