Ver código fonte

16424 - Allow filtering of Devices by Cluster and Cluster Group (#16674)

* Allow filtering Devices by Cluster and Cluster Group.

* Allow filtering Devices by Cluster and Cluster Group.

* Added tests for cluster and cluster_groups filterset.

* Add missing filter & complete tests

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Julio Oliveira at Encora 1 ano atrás
pai
commit
c506f60f12

+ 12 - 1
netbox/dcim/filtersets.py

@@ -20,7 +20,7 @@ from utilities.filters import (
     ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
     ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
     NumericArrayFilter, TreeNodeMultipleChoiceFilter,
     NumericArrayFilter, TreeNodeMultipleChoiceFilter,
 )
 )
-from virtualization.models import Cluster
+from virtualization.models import Cluster, ClusterGroup
 from vpn.models import L2VPN
 from vpn.models import L2VPN
 from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
 from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
 from wireless.models import WirelessLAN, WirelessLink
 from wireless.models import WirelessLAN, WirelessLink
@@ -1018,6 +1018,17 @@ class DeviceFilterSet(
         queryset=Cluster.objects.all(),
         queryset=Cluster.objects.all(),
         label=_('VM cluster (ID)'),
         label=_('VM cluster (ID)'),
     )
     )
+    cluster_group = django_filters.ModelMultipleChoiceFilter(
+        field_name='cluster__group__slug',
+        queryset=ClusterGroup.objects.all(),
+        to_field_name='slug',
+        label=_('Cluster group (slug)'),
+    )
+    cluster_group_id = django_filters.ModelMultipleChoiceFilter(
+        field_name='cluster__group',
+        queryset=ClusterGroup.objects.all(),
+        label=_('Cluster group (ID)'),
+    )
     model = django_filters.ModelMultipleChoiceFilter(
     model = django_filters.ModelMultipleChoiceFilter(
         field_name='device_type__slug',
         field_name='device_type__slug',
         queryset=DeviceType.objects.all(),
         queryset=DeviceType.objects.all(),

+ 12 - 0
netbox/dcim/forms/filtersets.py

@@ -14,6 +14,7 @@ from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_ch
 from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
 from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
 from utilities.forms.rendering import FieldSet
 from utilities.forms.rendering import FieldSet
 from utilities.forms.widgets import NumberWithOptions
 from utilities.forms.widgets import NumberWithOptions
+from virtualization.models import Cluster, ClusterGroup
 from vpn.models import L2VPN
 from vpn.models import L2VPN
 from wireless.choices import *
 from wireless.choices import *
 
 
@@ -655,6 +656,7 @@ class DeviceFilterForm(
             'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', 'pass_through_ports',
             'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', 'pass_through_ports',
             name=_('Components')
             name=_('Components')
         ),
         ),
+        FieldSet('cluster_group_id', 'cluster_id', name=_('Cluster')),
         FieldSet(
         FieldSet(
             'has_primary_ip', 'has_oob_ip', 'virtual_chassis_member', 'config_template_id', 'local_context_data',
             'has_primary_ip', 'has_oob_ip', 'virtual_chassis_member', 'config_template_id', 'local_context_data',
             'has_virtual_device_context',
             'has_virtual_device_context',
@@ -821,6 +823,16 @@ class DeviceFilterForm(
             choices=BOOLEAN_WITH_BLANK_CHOICES
             choices=BOOLEAN_WITH_BLANK_CHOICES
         )
         )
     )
     )
+    cluster_id = DynamicModelMultipleChoiceField(
+        queryset=Cluster.objects.all(),
+        required=False,
+        label=_('Cluster')
+    )
+    cluster_group_id = DynamicModelMultipleChoiceField(
+        queryset=ClusterGroup.objects.all(),
+        required=False,
+        label=_('Cluster group')
+    )
     tag = TagFilterField(model)
     tag = TagFilterField(model)
 
 
 
 

+ 17 - 4
netbox/dcim/tests/test_filtersets.py

@@ -9,7 +9,7 @@ from ipam.models import ASN, IPAddress, RIR, VRF
 from netbox.choices import ColorChoices
 from netbox.choices import ColorChoices
 from tenancy.models import Tenant, TenantGroup
 from tenancy.models import Tenant, TenantGroup
 from utilities.testing import ChangeLoggedFilterSetTests, create_test_device
 from utilities.testing import ChangeLoggedFilterSetTests, create_test_device
-from virtualization.models import Cluster, ClusterType
+from virtualization.models import Cluster, ClusterType, ClusterGroup
 from wireless.choices import WirelessChannelChoices, WirelessRoleChoices
 from wireless.choices import WirelessChannelChoices, WirelessRoleChoices
 
 
 User = get_user_model()
 User = get_user_model()
@@ -1959,10 +1959,16 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
         Rack.objects.bulk_create(racks)
         Rack.objects.bulk_create(racks)
 
 
         cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
         cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
+        cluster_groups = (
+            ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
+            ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
+            ClusterGroup(name='Cluster Group 3', slug='cluster-group-3'),
+        )
+        ClusterGroup.objects.bulk_create(cluster_groups)
         clusters = (
         clusters = (
-            Cluster(name='Cluster 1', type=cluster_type),
-            Cluster(name='Cluster 2', type=cluster_type),
-            Cluster(name='Cluster 3', type=cluster_type),
+            Cluster(name='Cluster 1', type=cluster_type, group=cluster_groups[0]),
+            Cluster(name='Cluster 2', type=cluster_type, group=cluster_groups[1]),
+            Cluster(name='Cluster 3', type=cluster_type, group=cluster_groups[2]),
         )
         )
         Cluster.objects.bulk_create(clusters)
         Cluster.objects.bulk_create(clusters)
 
 
@@ -2213,6 +2219,13 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
         params = {'cluster_id': [clusters[0].pk, clusters[1].pk]}
         params = {'cluster_id': [clusters[0].pk, clusters[1].pk]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
 
+    def test_cluster_group(self):
+        cluster_groups = ClusterGroup.objects.all()[:2]
+        params = {'cluster_group_id': [cluster_groups[0].pk, cluster_groups[1].pk]}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+        params = {'cluster_group': [cluster_groups[0].slug, cluster_groups[1].slug]}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+
     def test_model(self):
     def test_model(self):
         params = {'model': ['model-1', 'model-2']}
         params = {'model': ['model-1', 'model-2']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)