Browse Source

Merge pull request #10218 from netbox-community/10043-available-vlans-limit

Closes #10043: Add support for 'limit' query parameter to available VLANs API endpoint
Jeremy Stretch 3 years ago
parent
commit
6019b738a4
3 changed files with 36 additions and 15 deletions
  1. 1 0
      docs/release-notes/version-3.3.md
  2. 18 11
      netbox/ipam/api/views.py
  3. 17 4
      netbox/ipam/tests/test_api.py

+ 1 - 0
docs/release-notes/version-3.3.md

@@ -4,6 +4,7 @@
 
 ### Enhancements
 
+* [#10043](https://github.com/netbox-community/netbox/issues/10043) - Add support for `limit` query parameter to available VLANs API endpoint
 * [#10060](https://github.com/netbox-community/netbox/issues/10060) - Add journal entries to global search
 
 ### Bug Fixes

+ 18 - 11
netbox/ipam/api/views.py

@@ -174,6 +174,21 @@ class L2VPNTerminationViewSet(NetBoxModelViewSet):
 # Views
 #
 
+def get_results_limit(request):
+    """
+    Return the lesser of the specified limit (if any) and the configured MAX_PAGE_SIZE.
+    """
+    config = get_config()
+    try:
+        limit = int(request.query_params.get('limit', config.PAGINATE_COUNT)) or config.MAX_PAGE_SIZE
+    except ValueError:
+        limit = config.PAGINATE_COUNT
+    if config.MAX_PAGE_SIZE:
+        limit = min(limit, config.MAX_PAGE_SIZE)
+
+    return limit
+
+
 class AvailablePrefixesView(ObjectValidationMixin, APIView):
     queryset = Prefix.objects.all()
 
@@ -265,16 +280,7 @@ class AvailableIPAddressesView(ObjectValidationMixin, APIView):
     @swagger_auto_schema(responses={200: serializers.AvailableIPSerializer(many=True)})
     def get(self, request, pk):
         parent = self.get_parent(request, pk)
-        config = get_config()
-        PAGINATE_COUNT = config.PAGINATE_COUNT
-        MAX_PAGE_SIZE = config.MAX_PAGE_SIZE
-
-        try:
-            limit = int(request.query_params.get('limit', PAGINATE_COUNT))
-        except ValueError:
-            limit = PAGINATE_COUNT
-        if MAX_PAGE_SIZE:
-            limit = min(limit, MAX_PAGE_SIZE)
+        limit = get_results_limit(request)
 
         # Calculate available IPs within the parent
         ip_list = []
@@ -357,8 +363,9 @@ class AvailableVLANsView(ObjectValidationMixin, APIView):
     @swagger_auto_schema(responses={200: serializers.AvailableVLANSerializer(many=True)})
     def get(self, request, pk):
         vlangroup = get_object_or_404(VLANGroup.objects.restrict(request.user), pk=pk)
-        available_vlans = vlangroup.get_available_vids()
+        limit = get_results_limit(request)
 
+        available_vlans = vlangroup.get_available_vids()[:limit]
         serializer = serializers.AvailableVLANSerializer(available_vlans, many=True, context={
             'request': request,
             'group': vlangroup,

+ 17 - 4
netbox/ipam/tests/test_api.py

@@ -699,9 +699,18 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
         """
         Test retrieval of all available VLANs within a group.
         """
+        MIN_VID = 100
+        MAX_VID = 199
+
         self.add_permissions('ipam.view_vlangroup', 'ipam.view_vlan')
-        vlangroup = VLANGroup.objects.first()
+        vlangroup = VLANGroup.objects.create(
+            name='VLAN Group X',
+            slug='vlan-group-x',
+            min_vid=MIN_VID,
+            max_vid=MAX_VID
+        )
 
+        # Create a set of VLANs within the group
         vlans = (
             VLAN(vid=10, name='VLAN 10', group=vlangroup),
             VLAN(vid=20, name='VLAN 20', group=vlangroup),
@@ -711,13 +720,17 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
 
         # Retrieve all available VLANs
         url = reverse('ipam-api:vlangroup-available-vlans', kwargs={'pk': vlangroup.pk})
-        response = self.client.get(url, **self.header)
-
-        self.assertEqual(len(response.data), 4094 - len(vlans))
+        response = self.client.get(f'{url}?limit=0', **self.header)
+        self.assertEqual(len(response.data), MAX_VID - MIN_VID + 1)
         available_vlans = {vlan['vid'] for vlan in response.data}
         for vlan in vlans:
             self.assertNotIn(vlan.vid, available_vlans)
 
+        # Retrieve a maximum number of available VLANs
+        url = reverse('ipam-api:vlangroup-available-vlans', kwargs={'pk': vlangroup.pk})
+        response = self.client.get(f'{url}?limit=10', **self.header)
+        self.assertEqual(len(response.data), 10)
+
     def test_create_single_available_vlan(self):
         """
         Test the creation of a single available VLAN.