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>
This commit is contained in:
Julio Oliveira at Encora 2024-06-26 11:13:32 -03:00 committed by GitHub
parent b241c97e00
commit c506f60f12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 5 deletions

View File

@ -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(),

View File

@ -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)

View File

@ -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 1', type=cluster_type, group=cluster_groups[0]),
Cluster(name='Cluster 2', type=cluster_type), Cluster(name='Cluster 2', type=cluster_type, group=cluster_groups[1]),
Cluster(name='Cluster 3', type=cluster_type), 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)