diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 61683fc75..0cc02076e 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -4,13 +4,17 @@ * [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link * [#2113](https://github.com/netbox-community/netbox/issues/2113) - Allow NAPALM driver settings to be changed with request headers +* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses * [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations +* [#3851](https://github.com/netbox-community/netbox/issues/3851) - Allow passing initial data to custom script forms ## Bug Fixes * [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface * [#3853](https://github.com/netbox-community/netbox/issues/3853) - Fix device role link on config context view * [#3856](https://github.com/netbox-community/netbox/issues/3856) - Allow filtering VM interfaces by multiple MAC addresses +* [#3857](https://github.com/netbox-community/netbox/issues/3857) - Fix group custom links rendering +* [#3862](https://github.com/netbox-community/netbox/issues/3862) - Allow filtering device components by multiple device names --- diff --git a/netbox/circuits/filters.py b/netbox/circuits/filters.py index 0ac5ec170..1f1d078f6 100644 --- a/netbox/circuits/filters.py +++ b/netbox/circuits/filters.py @@ -8,6 +8,13 @@ from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilte from .constants import * from .models import Circuit, CircuitTermination, CircuitType, Provider +__all__ = ( + 'CircuitFilter', + 'CircuitTerminationFilter', + 'CircuitTypeFilter', + 'ProviderFilter', +) + class ProviderFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet): id__in = NumericInFilter( diff --git a/netbox/circuits/tests/test_filters.py b/netbox/circuits/tests/test_filters.py new file mode 100644 index 000000000..a715ad757 --- /dev/null +++ b/netbox/circuits/tests/test_filters.py @@ -0,0 +1,287 @@ +from django.test import TestCase + +from circuits.constants import CIRCUIT_STATUS_ACTIVE, CIRCUIT_STATUS_OFFLINE, CIRCUIT_STATUS_PLANNED +from circuits.filters import * +from circuits.models import Circuit, CircuitTermination, CircuitType, Provider +from dcim.models import Region, Site + + +class ProviderTestCase(TestCase): + queryset = Provider.objects.all() + filterset = ProviderFilter + + @classmethod + def setUpTestData(cls): + + providers = ( + Provider(name='Provider 1', slug='provider-1', asn=65001, account='1234'), + Provider(name='Provider 2', slug='provider-2', asn=65002, account='2345'), + Provider(name='Provider 3', slug='provider-3', asn=65003, account='3456'), + Provider(name='Provider 4', slug='provider-4', asn=65004, account='4567'), + Provider(name='Provider 5', slug='provider-5', asn=65005, account='5678'), + ) + Provider.objects.bulk_create(providers) + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1', region=regions[0]), + Site(name='Test Site 2', slug='test-site-2', region=regions[1]), + ) + Site.objects.bulk_create(sites) + + circuit_types = ( + CircuitType(name='Test Circuit Type 1', slug='test-circuit-type-1'), + CircuitType(name='Test Circuit Type 2', slug='test-circuit-type-2'), + ) + CircuitType.objects.bulk_create(circuit_types) + + circuits = ( + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 1'), + Circuit(provider=providers[1], type=circuit_types[1], cid='Test Circuit 1'), + ) + Circuit.objects.bulk_create(circuits) + + CircuitTermination.objects.bulk_create(( + CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000), + CircuitTermination(circuit=circuits[1], site=sites[0], term_side='A', port_speed=1000), + )) + + def test_name(self): + params = {'name': ['Provider 1', 'Provider 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['provider-1', 'provider-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_asn(self): + params = {'asn': ['65001', '65002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_account(self): + params = {'account': ['1234', '2345']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class CircuitTypeTestCase(TestCase): + queryset = CircuitType.objects.all() + filterset = CircuitTypeFilter + + @classmethod + def setUpTestData(cls): + + CircuitType.objects.bulk_create(( + CircuitType(name='Circuit Type 1', slug='circuit-type-1'), + CircuitType(name='Circuit Type 2', slug='circuit-type-2'), + CircuitType(name='Circuit Type 3', slug='circuit-type-3'), + )) + + def test_id(self): + params = {'id': [self.queryset.first().pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_name(self): + params = {'name': ['Circuit Type 1']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_slug(self): + params = {'slug': ['circuit-type-1']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class CircuitTestCase(TestCase): + queryset = Circuit.objects.all() + filterset = CircuitFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + Region(name='Test Region 3', slug='test-region-3'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1', region=regions[0]), + Site(name='Test Site 2', slug='test-site-2', region=regions[1]), + Site(name='Test Site 3', slug='test-site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + circuit_types = ( + CircuitType(name='Test Circuit Type 1', slug='test-circuit-type-1'), + CircuitType(name='Test Circuit Type 2', slug='test-circuit-type-2'), + ) + CircuitType.objects.bulk_create(circuit_types) + + providers = ( + Provider(name='Provider 1', slug='provider-1'), + Provider(name='Provider 2', slug='provider-2'), + ) + Provider.objects.bulk_create(providers) + + circuits = ( + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 1', install_date='2020-01-01', commit_rate=1000, status=CIRCUIT_STATUS_ACTIVE), + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 2', install_date='2020-01-02', commit_rate=2000, status=CIRCUIT_STATUS_ACTIVE), + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 3', install_date='2020-01-03', commit_rate=3000, status=CIRCUIT_STATUS_PLANNED), + Circuit(provider=providers[1], type=circuit_types[1], cid='Test Circuit 4', install_date='2020-01-04', commit_rate=4000, status=CIRCUIT_STATUS_PLANNED), + Circuit(provider=providers[1], type=circuit_types[1], cid='Test Circuit 5', install_date='2020-01-05', commit_rate=5000, status=CIRCUIT_STATUS_OFFLINE), + Circuit(provider=providers[1], type=circuit_types[1], cid='Test Circuit 6', install_date='2020-01-06', commit_rate=6000, status=CIRCUIT_STATUS_OFFLINE), + ) + Circuit.objects.bulk_create(circuits) + + circuit_terminations = (( + CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000), + CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A', port_speed=1000), + CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A', port_speed=1000), + )) + CircuitTermination.objects.bulk_create(circuit_terminations) + + def test_cid(self): + params = {'cid': ['Test Circuit 1', 'Test Circuit 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_install_date(self): + params = {'install_date': ['2020-01-01', '2020-01-02']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_commit_rate(self): + params = {'commit_rate': ['1000', '2000']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_provider(self): + provider = Provider.objects.first() + params = {'provider_id': [provider.pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'provider': [provider.slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_type(self): + circuit_type = CircuitType.objects.first() + params = {'type_id': [circuit_type.pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'type': [circuit_type.slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_status(self): + params = {'status': [CIRCUIT_STATUS_ACTIVE, CIRCUIT_STATUS_PLANNED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class CircuitTerminationTestCase(TestCase): + queryset = CircuitTermination.objects.all() + filterset = CircuitTerminationFilter + + @classmethod + def setUpTestData(cls): + + sites = ( + Site(name='Test Site 1', slug='test-site-1'), + Site(name='Test Site 2', slug='test-site-2'), + Site(name='Test Site 3', slug='test-site-3'), + ) + Site.objects.bulk_create(sites) + + circuit_types = ( + CircuitType(name='Test Circuit Type 1', slug='test-circuit-type-1'), + ) + CircuitType.objects.bulk_create(circuit_types) + + providers = ( + Provider(name='Provider 1', slug='provider-1'), + ) + Provider.objects.bulk_create(providers) + + circuits = ( + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 1'), + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 2'), + Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 3'), + ) + Circuit.objects.bulk_create(circuits) + + circuit_terminations = (( + CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000, upstream_speed=1000, xconnect_id='ABC'), + CircuitTermination(circuit=circuits[0], site=sites[1], term_side='Z', port_speed=1000, upstream_speed=1000, xconnect_id='DEF'), + CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A', port_speed=2000, upstream_speed=2000, xconnect_id='GHI'), + CircuitTermination(circuit=circuits[1], site=sites[2], term_side='Z', port_speed=2000, upstream_speed=2000, xconnect_id='JKL'), + CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A', port_speed=3000, upstream_speed=3000, xconnect_id='MNO'), + CircuitTermination(circuit=circuits[2], site=sites[0], term_side='Z', port_speed=3000, upstream_speed=3000, xconnect_id='PQR'), + )) + CircuitTermination.objects.bulk_create(circuit_terminations) + + def test_term_side(self): + params = {'term_side': 'A'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_port_speed(self): + params = {'port_speed': ['1000', '2000']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_upstream_speed(self): + params = {'upstream_speed': ['1000', '2000']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_xconnect_id(self): + params = {'xconnect_id': ['ABC', 'DEF']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_circuit_id(self): + circuits = Circuit.objects.all()[:2] + params = {'circuit_id': [circuits[0].pk, circuits[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 638313507..9d6a0ae6a 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -21,6 +21,45 @@ from .models import ( ) +__all__ = ( + 'CableFilter', + 'ConsoleConnectionFilter', + 'ConsolePortFilter', + 'ConsolePortTemplateFilter', + 'ConsoleServerPortFilter', + 'ConsoleServerPortTemplateFilter', + 'DeviceBayFilter', + 'DeviceBayTemplateFilter', + 'DeviceFilter', + 'DeviceRoleFilter', + 'DeviceTypeFilter', + 'FrontPortFilter', + 'FrontPortTemplateFilter', + 'InterfaceConnectionFilter', + 'InterfaceFilter', + 'InterfaceTemplateFilter', + 'InventoryItemFilter', + 'ManufacturerFilter', + 'PlatformFilter', + 'PowerConnectionFilter', + 'PowerFeedFilter', + 'PowerOutletFilter', + 'PowerOutletTemplateFilter', + 'PowerPanelFilter', + 'PowerPortFilter', + 'PowerPortTemplateFilter', + 'RackFilter', + 'RackGroupFilter', + 'RackReservationFilter', + 'RackRoleFilter', + 'RearPortFilter', + 'RearPortTemplateFilter', + 'RegionFilter', + 'SiteFilter', + 'VirtualChassisFilter', +) + + class RegionFilter(NameSlugSearchFilterSet): parent_id = django_filters.ModelMultipleChoiceFilter( queryset=Region.objects.all(), @@ -646,7 +685,8 @@ class DeviceComponentFilterSet(django_filters.FilterSet): queryset=Device.objects.all(), label='Device (ID)', ) - device = django_filters.ModelChoiceFilter( + device = django_filters.ModelMultipleChoiceFilter( + field_name='device__name', queryset=Device.objects.all(), to_field_name='name', label='Device (name)', diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py new file mode 100644 index 000000000..1feacc5c5 --- /dev/null +++ b/netbox/dcim/tests/test_filters.py @@ -0,0 +1,2381 @@ +from django.contrib.auth.models import User +from django.test import TestCase + +from dcim.constants import * +from dcim.filters import * +from dcim.models import ( + Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, + DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, + InventoryItem, Manufacturer, Platform, PowerFeed, PowerPanel, PowerPort, PowerPortTemplate, PowerOutlet, + PowerOutletTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, + VirtualChassis, +) +from ipam.models import IPAddress +from virtualization.models import Cluster, ClusterType + + +class RegionTestCase(TestCase): + queryset = Region.objects.all() + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + child_regions = ( + Region(name='Region 1A', slug='region-1a', parent=regions[0]), + Region(name='Region 1B', slug='region-1b', parent=regions[0]), + Region(name='Region 2A', slug='region-2a', parent=regions[1]), + Region(name='Region 2B', slug='region-2b', parent=regions[1]), + Region(name='Region 3A', slug='region-3a', parent=regions[2]), + Region(name='Region 3B', slug='region-3b', parent=regions[2]), + ) + for region in child_regions: + region.save() + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(RegionFilter(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Region 1', 'Region 2']} + self.assertEqual(RegionFilter(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['region-1', 'region-2']} + self.assertEqual(RegionFilter(params, self.queryset).qs.count(), 2) + + def test_parent(self): + parent_regions = Region.objects.filter(parent__isnull=True)[:2] + params = {'parent_id': [parent_regions[0].pk, parent_regions[1].pk]} + self.assertEqual(RegionFilter(params, self.queryset).qs.count(), 4) + params = {'parent': [parent_regions[0].slug, parent_regions[1].slug]} + self.assertEqual(RegionFilter(params, self.queryset).qs.count(), 4) + + +class SiteTestCase(TestCase): + queryset = Site.objects.all() + filterset = SiteFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0], status=SITE_STATUS_ACTIVE, facility='Facility 1', asn=65001, latitude=10, longitude=10, contact_name='Contact 1', contact_phone='123-555-0001', contact_email='contact1@example.com'), + Site(name='Site 2', slug='site-2', region=regions[1], status=SITE_STATUS_PLANNED, facility='Facility 2', asn=65002, latitude=20, longitude=20, contact_name='Contact 2', contact_phone='123-555-0002', contact_email='contact2@example.com'), + Site(name='Site 3', slug='site-3', region=regions[2], status=SITE_STATUS_RETIRED, facility='Facility 3', asn=65003, latitude=30, longitude=30, contact_name='Contact 3', contact_phone='123-555-0003', contact_email='contact3@example.com'), + ) + Site.objects.bulk_create(sites) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Site 1', 'Site 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['site-1', 'site-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_facility(self): + params = {'facility': ['Facility 1', 'Facility 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_asn(self): + params = {'asn': [65001, 65002]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_latitude(self): + params = {'latitude': [10, 20]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_longitude(self): + params = {'longitude': [10, 20]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_contact_name(self): + params = {'contact_name': ['Contact 1', 'Contact 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_contact_phone(self): + params = {'contact_phone': ['123-555-0001', '123-555-0002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_contact_email(self): + params = {'contact_email': ['contact1@example.com', 'contact2@example.com']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + params = {'status': [SITE_STATUS_ACTIVE, SITE_STATUS_PLANNED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class RackGroupTestCase(TestCase): + queryset = RackGroup.objects.all() + filterset = RackGroupFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + rack_groups = ( + RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]), + RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2]), + ) + RackGroup.objects.bulk_create(rack_groups) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Rack Group 1', 'Rack Group 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['rack-group-1', 'rack-group-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class RackRoleTestCase(TestCase): + queryset = RackRole.objects.all() + filterset = RackRoleFilter + + @classmethod + def setUpTestData(cls): + + rack_roles = ( + RackRole(name='Rack Role 1', slug='rack-role-1', color='ff0000'), + RackRole(name='Rack Role 2', slug='rack-role-2', color='00ff00'), + RackRole(name='Rack Role 3', slug='rack-role-3', color='0000ff'), + ) + RackRole.objects.bulk_create(rack_roles) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Rack Role 1', 'Rack Role 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['rack-role-1', 'rack-role-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_color(self): + params = {'color': ['ff0000', '00ff00']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class RackTestCase(TestCase): + queryset = Rack.objects.all() + filterset = RackFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + rack_groups = ( + RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]), + RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2]), + ) + RackGroup.objects.bulk_create(rack_groups) + + rack_roles = ( + RackRole(name='Rack Role 1', slug='rack-role-1'), + RackRole(name='Rack Role 2', slug='rack-role-2'), + RackRole(name='Rack Role 3', slug='rack-role-3'), + ) + RackRole.objects.bulk_create(rack_roles) + + racks = ( + Rack(name='Rack 1', facility_id='rack-1', site=sites[0], group=rack_groups[0], status=RACK_STATUS_ACTIVE, role=rack_roles[0], serial='ABC', asset_tag='1001', type=RACK_TYPE_2POST, width=RACK_WIDTH_19IN, u_height=42, desc_units=False, outer_width=100, outer_depth=100, outer_unit=LENGTH_UNIT_MILLIMETER), + Rack(name='Rack 2', facility_id='rack-2', site=sites[1], group=rack_groups[1], status=RACK_STATUS_PLANNED, role=rack_roles[1], serial='DEF', asset_tag='1002', type=RACK_TYPE_4POST, width=RACK_WIDTH_19IN, u_height=43, desc_units=False, outer_width=200, outer_depth=200, outer_unit=LENGTH_UNIT_MILLIMETER), + Rack(name='Rack 3', facility_id='rack-3', site=sites[2], group=rack_groups[2], status=RACK_STATUS_RESERVED, role=rack_roles[2], serial='GHI', asset_tag='1003', type=RACK_TYPE_CABINET, width=RACK_WIDTH_23IN, u_height=44, desc_units=True, outer_width=300, outer_depth=300, outer_unit=LENGTH_UNIT_INCH), + ) + Rack.objects.bulk_create(racks) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Rack 1', 'Rack 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_facility_id(self): + params = {'facility_id': ['rack-1', 'rack-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_asset_tag(self): + params = {'asset_tag': ['1001', '1002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Test for multiple values + params = {'type': RACK_TYPE_2POST} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_width(self): + # TODO: Test for multiple values + params = {'width': RACK_WIDTH_19IN} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_u_height(self): + params = {'u_height': [42, 43]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_desc_units(self): + params = {'desc_units': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'desc_units': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_outer_width(self): + params = {'outer_width': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_outer_depth(self): + params = {'outer_depth': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_outer_unit(self): + self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 3) + params = {'outer_unit': LENGTH_UNIT_MILLIMETER} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_group(self): + groups = RackGroup.objects.all()[:2] + params = {'group_id': [groups[0].pk, groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'group': [groups[0].slug, groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + params = {'status': [RACK_STATUS_ACTIVE, RACK_STATUS_PLANNED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_role(self): + roles = RackRole.objects.all()[:2] + params = {'role_id': [roles[0].pk, roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'role': [roles[0].slug, roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_serial(self): + params = {'serial': 'ABC'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'serial': 'abc'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class RackReservationTestCase(TestCase): + queryset = RackReservation.objects.all() + filterset = RackReservationFilter + + @classmethod + def setUpTestData(cls): + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + Site(name='Site 3', slug='site-3'), + ) + Site.objects.bulk_create(sites) + + rack_groups = ( + RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]), + RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2]), + ) + RackGroup.objects.bulk_create(rack_groups) + + racks = ( + Rack(name='Rack 1', site=sites[0], group=rack_groups[0]), + Rack(name='Rack 2', site=sites[1], group=rack_groups[1]), + Rack(name='Rack 3', site=sites[2], group=rack_groups[2]), + ) + Rack.objects.bulk_create(racks) + + users = ( + User(username='User 1'), + User(username='User 2'), + User(username='User 3'), + ) + User.objects.bulk_create(users) + + reservations = ( + RackReservation(rack=racks[0], units=[1, 2, 3], user=users[0]), + RackReservation(rack=racks[1], units=[4, 5, 6], user=users[1]), + RackReservation(rack=racks[2], units=[7, 8, 9], user=users[2]), + ) + RackReservation.objects.bulk_create(reservations) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_group(self): + groups = RackGroup.objects.all()[:2] + params = {'group_id': [groups[0].pk, groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'group': [groups[0].slug, groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_user(self): + users = User.objects.all()[:2] + params = {'user_id': [users[0].pk, users[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + # TODO: Filtering by username is broken + # params = {'user': [users[0].username, users[1].username]} + # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class ManufacturerTestCase(TestCase): + queryset = Manufacturer.objects.all() + filterset = ManufacturerFilter + + @classmethod + def setUpTestData(cls): + + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), + ) + Manufacturer.objects.bulk_create(manufacturers) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Manufacturer 1', 'Manufacturer 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['manufacturer-1', 'manufacturer-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class DeviceTypeTestCase(TestCase): + queryset = DeviceType.objects.all() + filterset = DeviceTypeFilter + + @classmethod + def setUpTestData(cls): + + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), + ) + Manufacturer.objects.bulk_create(manufacturers) + + device_types = ( + DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', part_number='Part Number 1', u_height=1, is_full_depth=True, subdevice_role=None), + DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', part_number='Part Number 2', u_height=2, is_full_depth=True, subdevice_role=SUBDEVICE_ROLE_PARENT), + DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', part_number='Part Number 3', u_height=3, is_full_depth=False, subdevice_role=SUBDEVICE_ROLE_CHILD), + ) + DeviceType.objects.bulk_create(device_types) + + # Add component templates for filtering + ConsolePortTemplate.objects.bulk_create(( + ConsolePortTemplate(device_type=device_types[0], name='Console Port 1'), + ConsolePortTemplate(device_type=device_types[1], name='Console Port 2'), + )) + ConsoleServerPortTemplate.objects.bulk_create(( + ConsoleServerPortTemplate(device_type=device_types[0], name='Console Server Port 1'), + ConsoleServerPortTemplate(device_type=device_types[1], name='Console Server Port 2'), + )) + PowerPortTemplate.objects.bulk_create(( + PowerPortTemplate(device_type=device_types[0], name='Power Port 1'), + PowerPortTemplate(device_type=device_types[1], name='Power Port 2'), + )) + PowerOutletTemplate.objects.bulk_create(( + PowerOutletTemplate(device_type=device_types[0], name='Power Outlet 1'), + PowerOutletTemplate(device_type=device_types[1], name='Power Outlet 2'), + )) + InterfaceTemplate.objects.bulk_create(( + InterfaceTemplate(device_type=device_types[0], name='Interface 1'), + InterfaceTemplate(device_type=device_types[1], name='Interface 2'), + )) + rear_ports = ( + RearPortTemplate(device_type=device_types[0], name='Rear Port 1', type=PORT_TYPE_8P8C), + RearPortTemplate(device_type=device_types[1], name='Rear Port 2', type=PORT_TYPE_8P8C), + ) + RearPortTemplate.objects.bulk_create(rear_ports) + FrontPortTemplate.objects.bulk_create(( + FrontPortTemplate(device_type=device_types[0], name='Front Port 1', type=PORT_TYPE_8P8C, rear_port=rear_ports[0]), + FrontPortTemplate(device_type=device_types[1], name='Front Port 2', type=PORT_TYPE_8P8C, rear_port=rear_ports[1]), + )) + DeviceBayTemplate.objects.bulk_create(( + DeviceBayTemplate(device_type=device_types[0], name='Device Bay 1'), + DeviceBayTemplate(device_type=device_types[1], name='Device Bay 2'), + )) + + def test_model(self): + params = {'model': ['Model 1', 'Model 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['model-1', 'model-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_part_number(self): + params = {'part_number': ['Part Number 1', 'Part Number 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_u_height(self): + params = {'u_height': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_is_full_depth(self): + params = {'is_full_depth': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'is_full_depth': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_subdevice_role(self): + params = {'subdevice_role': SUBDEVICE_ROLE_PARENT} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_manufacturer(self): + manufacturers = Manufacturer.objects.all()[:2] + params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_console_ports(self): + params = {'console_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'console_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_console_server_ports(self): + params = {'console_server_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'console_server_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_power_ports(self): + params = {'power_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'power_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_power_outlets(self): + params = {'power_outlets': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'power_outlets': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_interfaces(self): + params = {'interfaces': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'interfaces': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_pass_through_ports(self): + params = {'pass_through_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'pass_through_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + # TODO: Add device_bay filter + # def test_device_bays(self): + # params = {'device_bays': 'true'} + # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + # params = {'device_bays': 'false'} + # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class ConsolePortTemplateTestCase(TestCase): + queryset = ConsolePortTemplate.objects.all() + filterset = ConsolePortTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + ConsolePortTemplate.objects.bulk_create(( + ConsolePortTemplate(device_type=device_types[0], name='Console Port 1'), + ConsolePortTemplate(device_type=device_types[1], name='Console Port 2'), + ConsolePortTemplate(device_type=device_types[2], name='Console Port 3'), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Console Port 1', 'Console Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class ConsoleServerPortTemplateTestCase(TestCase): + queryset = ConsoleServerPortTemplate.objects.all() + filterset = ConsoleServerPortTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + ConsoleServerPortTemplate.objects.bulk_create(( + ConsoleServerPortTemplate(device_type=device_types[0], name='Console Server Port 1'), + ConsoleServerPortTemplate(device_type=device_types[1], name='Console Server Port 2'), + ConsoleServerPortTemplate(device_type=device_types[2], name='Console Server Port 3'), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Console Server Port 1', 'Console Server Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class PowerPortTemplateTestCase(TestCase): + queryset = PowerPortTemplate.objects.all() + filterset = PowerPortTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + PowerPortTemplate.objects.bulk_create(( + PowerPortTemplate(device_type=device_types[0], name='Power Port 1', maximum_draw=100, allocated_draw=50), + PowerPortTemplate(device_type=device_types[1], name='Power Port 2', maximum_draw=200, allocated_draw=100), + PowerPortTemplate(device_type=device_types[2], name='Power Port 3', maximum_draw=300, allocated_draw=150), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Power Port 1', 'Power Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_maximum_draw(self): + params = {'maximum_draw': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_allocated_draw(self): + params = {'allocated_draw': [50, 100]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class PowerOutletTemplateTestCase(TestCase): + queryset = PowerOutletTemplate.objects.all() + filterset = PowerOutletTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + PowerOutletTemplate.objects.bulk_create(( + PowerOutletTemplate(device_type=device_types[0], name='Power Outlet 1', feed_leg=POWERFEED_LEG_A), + PowerOutletTemplate(device_type=device_types[1], name='Power Outlet 2', feed_leg=POWERFEED_LEG_B), + PowerOutletTemplate(device_type=device_types[2], name='Power Outlet 3', feed_leg=POWERFEED_LEG_C), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Power Outlet 1', 'Power Outlet 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_feed_leg(self): + # TODO: Support filtering for multiple values + params = {'feed_leg': POWERFEED_LEG_A} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class InterfaceTemplateTestCase(TestCase): + queryset = InterfaceTemplate.objects.all() + filterset = InterfaceTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + InterfaceTemplate.objects.bulk_create(( + InterfaceTemplate(device_type=device_types[0], name='Interface 1', type=IFACE_TYPE_1GE_FIXED, mgmt_only=True), + InterfaceTemplate(device_type=device_types[1], name='Interface 2', type=IFACE_TYPE_1GE_GBIC, mgmt_only=False), + InterfaceTemplate(device_type=device_types[2], name='Interface 3', type=IFACE_TYPE_1GE_SFP, mgmt_only=False), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Interface 1', 'Interface 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Support filtering for multiple values + params = {'type': IFACE_TYPE_1GE_FIXED} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_mgmt_only(self): + params = {'mgmt_only': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'mgmt_only': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class FrontPortTemplateTestCase(TestCase): + queryset = FrontPortTemplate.objects.all() + filterset = FrontPortTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + rear_ports = ( + RearPortTemplate(device_type=device_types[0], name='Rear Port 1', type=PORT_TYPE_8P8C), + RearPortTemplate(device_type=device_types[1], name='Rear Port 2', type=PORT_TYPE_8P8C), + RearPortTemplate(device_type=device_types[2], name='Rear Port 3', type=PORT_TYPE_8P8C), + ) + RearPortTemplate.objects.bulk_create(rear_ports) + + FrontPortTemplate.objects.bulk_create(( + FrontPortTemplate(device_type=device_types[0], name='Front Port 1', rear_port=rear_ports[0], type=PORT_TYPE_8P8C), + FrontPortTemplate(device_type=device_types[1], name='Front Port 2', rear_port=rear_ports[1], type=PORT_TYPE_110_PUNCH), + FrontPortTemplate(device_type=device_types[2], name='Front Port 3', rear_port=rear_ports[2], type=PORT_TYPE_BNC), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Front Port 1', 'Front Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Support filtering for multiple values + params = {'type': PORT_TYPE_8P8C} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class RearPortTemplateTestCase(TestCase): + queryset = RearPortTemplate.objects.all() + filterset = RearPortTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + RearPortTemplate.objects.bulk_create(( + RearPortTemplate(device_type=device_types[0], name='Rear Port 1', type=PORT_TYPE_8P8C, positions=1), + RearPortTemplate(device_type=device_types[1], name='Rear Port 2', type=PORT_TYPE_110_PUNCH, positions=2), + RearPortTemplate(device_type=device_types[2], name='Rear Port 3', type=PORT_TYPE_BNC, positions=3), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Rear Port 1', 'Rear Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Support filtering for multiple values + params = {'type': PORT_TYPE_8P8C} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_positions(self): + params = {'positions': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class DeviceBayTemplateTestCase(TestCase): + queryset = DeviceBayTemplate.objects.all() + filterset = DeviceBayTemplateFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Model 1', slug='model-1'), + DeviceType(manufacturer=manufacturer, model='Model 2', slug='model-2'), + DeviceType(manufacturer=manufacturer, model='Model 3', slug='model-3'), + ) + DeviceType.objects.bulk_create(device_types) + + DeviceBayTemplate.objects.bulk_create(( + DeviceBayTemplate(device_type=device_types[0], name='Device Bay 1'), + DeviceBayTemplate(device_type=device_types[1], name='Device Bay 2'), + DeviceBayTemplate(device_type=device_types[2], name='Device Bay 3'), + )) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Device Bay 1', 'Device Bay 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype_id(self): + device_types = DeviceType.objects.all()[:2] + params = {'devicetype_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class DeviceRoleTestCase(TestCase): + queryset = DeviceRole.objects.all() + filterset = DeviceRoleFilter + + @classmethod + def setUpTestData(cls): + + device_roles = ( + DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000', vm_role=True), + DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00', vm_role=True), + DeviceRole(name='Device Role 3', slug='device-role-3', color='0000ff', vm_role=False), + ) + DeviceRole.objects.bulk_create(device_roles) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Device Role 1', 'Device Role 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['device-role-1', 'device-role-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_color(self): + params = {'color': ['ff0000', '00ff00']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_vm_role(self): + params = {'vm_role': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'vm_role': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class PlatformTestCase(TestCase): + queryset = Platform.objects.all() + filterset = PlatformFilter + + @classmethod + def setUpTestData(cls): + + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), + ) + Manufacturer.objects.bulk_create(manufacturers) + + platforms = ( + Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturers[0], napalm_driver='driver-1'), + Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturers[1], napalm_driver='driver-2'), + Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturers[2], napalm_driver='driver-3'), + ) + Platform.objects.bulk_create(platforms) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Platform 1', 'Platform 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['platform-1', 'platform-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_napalm_driver(self): + params = {'napalm_driver': ['driver-1', 'driver-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_manufacturer(self): + manufacturers = Manufacturer.objects.all()[:2] + params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class DeviceTestCase(TestCase): + queryset = Device.objects.all() + filterset = DeviceFilter + + @classmethod + def setUpTestData(cls): + + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), + ) + Manufacturer.objects.bulk_create(manufacturers) + + device_types = ( + DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', is_full_depth=True), + DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', is_full_depth=True), + DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', is_full_depth=False), + ) + DeviceType.objects.bulk_create(device_types) + + device_roles = ( + DeviceRole(name='Device Role 1', slug='device-role-1'), + DeviceRole(name='Device Role 2', slug='device-role-2'), + DeviceRole(name='Device Role 3', slug='device-role-3'), + ) + DeviceRole.objects.bulk_create(device_roles) + + platforms = ( + Platform(name='Platform 1', slug='platform-1'), + Platform(name='Platform 2', slug='platform-2'), + Platform(name='Platform 3', slug='platform-3'), + ) + Platform.objects.bulk_create(platforms) + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + rack_groups = ( + RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]), + RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2]), + ) + RackGroup.objects.bulk_create(rack_groups) + + racks = ( + Rack(name='Rack 1', site=sites[0], group=rack_groups[0]), + Rack(name='Rack 2', site=sites[1], group=rack_groups[1]), + Rack(name='Rack 3', site=sites[2], group=rack_groups[2]), + ) + Rack.objects.bulk_create(racks) + + cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + clusters = ( + Cluster(name='Cluster 1', type=cluster_type), + Cluster(name='Cluster 2', type=cluster_type), + Cluster(name='Cluster 3', type=cluster_type), + ) + Cluster.objects.bulk_create(clusters) + + devices = ( + Device(name='Device 1', device_type=device_types[0], device_role=device_roles[0], platform=platforms[0], serial='ABC', asset_tag='1001', site=sites[0], rack=racks[0], position=1, face=RACK_FACE_FRONT, status=DEVICE_STATUS_ACTIVE, cluster=clusters[0]), + Device(name='Device 2', device_type=device_types[1], device_role=device_roles[1], platform=platforms[1], serial='DEF', asset_tag='1002', site=sites[1], rack=racks[1], position=2, face=RACK_FACE_FRONT, status=DEVICE_STATUS_STAGED, cluster=clusters[1]), + Device(name='Device 3', device_type=device_types[2], device_role=device_roles[2], platform=platforms[2], serial='GHI', asset_tag='1003', site=sites[2], rack=racks[2], position=3, face=RACK_FACE_REAR, status=DEVICE_STATUS_FAILED, cluster=clusters[2]), + ) + Device.objects.bulk_create(devices) + + # Add components for filtering + ConsolePort.objects.bulk_create(( + ConsolePort(device=devices[0], name='Console Port 1'), + ConsolePort(device=devices[1], name='Console Port 2'), + )) + ConsoleServerPort.objects.bulk_create(( + ConsoleServerPort(device=devices[0], name='Console Server Port 1'), + ConsoleServerPort(device=devices[1], name='Console Server Port 2'), + )) + PowerPort.objects.bulk_create(( + PowerPort(device=devices[0], name='Power Port 1'), + PowerPort(device=devices[1], name='Power Port 2'), + )) + PowerOutlet.objects.bulk_create(( + PowerOutlet(device=devices[0], name='Power Outlet 1'), + PowerOutlet(device=devices[1], name='Power Outlet 2'), + )) + interfaces = ( + Interface(device=devices[0], name='Interface 1', mac_address='00-00-00-00-00-01'), + Interface(device=devices[1], name='Interface 2', mac_address='00-00-00-00-00-02'), + ) + Interface.objects.bulk_create(interfaces) + rear_ports = ( + RearPort(device=devices[0], name='Rear Port 1', type=PORT_TYPE_8P8C), + RearPort(device=devices[1], name='Rear Port 2', type=PORT_TYPE_8P8C), + ) + RearPort.objects.bulk_create(rear_ports) + FrontPort.objects.bulk_create(( + FrontPort(device=devices[0], name='Front Port 1', type=PORT_TYPE_8P8C, rear_port=rear_ports[0]), + FrontPort(device=devices[1], name='Front Port 2', type=PORT_TYPE_8P8C, rear_port=rear_ports[1]), + )) + DeviceBay.objects.bulk_create(( + DeviceBay(device=devices[0], name='Device Bay 1'), + DeviceBay(device=devices[1], name='Device Bay 2'), + )) + + # Assign primary IPs for filtering + ipaddresses = ( + IPAddress(family=4, address='192.0.2.1/24', interface=interfaces[0]), + IPAddress(family=4, address='192.0.2.2/24', interface=interfaces[1]), + ) + IPAddress.objects.bulk_create(ipaddresses) + Device.objects.filter(pk=devices[0].pk).update(primary_ip4=ipaddresses[0]) + Device.objects.filter(pk=devices[1].pk).update(primary_ip4=ipaddresses[1]) + + # VirtualChassis assignment for filtering + virtual_chassis = VirtualChassis.objects.create(master=devices[0]) + Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis, vc_position=1, vc_priority=1) + Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis, vc_position=2, vc_priority=2) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Device 1', 'Device 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_asset_tag(self): + params = {'asset_tag': ['1001', '1002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_face(self): + params = {'face': RACK_FACE_FRONT} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_position(self): + params = {'position': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_vc_position(self): + params = {'vc_position': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_vc_priority(self): + params = {'vc_priority': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_manufacturer(self): + manufacturers = Manufacturer.objects.all()[:2] + params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicetype(self): + device_types = DeviceType.objects.all()[:2] + params = {'device_type_id': [device_types[0].pk, device_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_devicerole(self): + device_roles = DeviceRole.objects.all()[:2] + params = {'role_id': [device_roles[0].pk, device_roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'role': [device_roles[0].slug, device_roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_platform(self): + platforms = Platform.objects.all()[:2] + params = {'platform_id': [platforms[0].pk, platforms[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'platform': [platforms[0].slug, platforms[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rackgroup(self): + rack_groups = RackGroup.objects.all()[:2] + params = {'rack_group_id': [rack_groups[0].pk, rack_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rack(self): + racks = Rack.objects.all()[:2] + params = {'rack_id': [racks[0].pk, racks[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cluster(self): + clusters = Cluster.objects.all()[:2] + params = {'cluster_id': [clusters[0].pk, clusters[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_model(self): + params = {'model': ['model-1', 'model-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + params = {'status': [DEVICE_STATUS_ACTIVE, DEVICE_STATUS_STAGED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_is_full_depth(self): + params = {'is_full_depth': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'is_full_depth': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_mac_address(self): + params = {'mac_address': ['00-00-00-00-00-01', '00-00-00-00-00-02']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_serial(self): + params = {'serial': 'ABC'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'serial': 'abc'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_has_primary_ip(self): + params = {'has_primary_ip': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'has_primary_ip': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_virtual_chassis_id(self): + params = {'virtual_chassis_id': [VirtualChassis.objects.first().pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_virtual_chassis_member(self): + params = {'virtual_chassis_member': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_chassis_member': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_console_ports(self): + params = {'console_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'console_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_console_server_ports(self): + params = {'console_server_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'console_server_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_power_ports(self): + params = {'power_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'power_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_power_outlets(self): + params = {'power_outlets': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'power_outlets': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_interfaces(self): + params = {'interfaces': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'interfaces': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_pass_through_ports(self): + params = {'pass_through_ports': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'pass_through_ports': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + # TODO: Add device_bay filter + # def test_device_bays(self): + # params = {'device_bays': 'true'} + # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + # params = {'device_bays': 'false'} + # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class ConsolePortTestCase(TestCase): + queryset = ConsolePort.objects.all() + filterset = ConsolePortFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + console_server_ports = ( + ConsoleServerPort(device=devices[3], name='Console Server Port 1'), + ConsoleServerPort(device=devices[3], name='Console Server Port 2'), + ) + ConsoleServerPort.objects.bulk_create(console_server_ports) + + console_ports = ( + ConsolePort(device=devices[0], name='Console Port 1', description='First'), + ConsolePort(device=devices[1], name='Console Port 2', description='Second'), + ConsolePort(device=devices[2], name='Console Port 3', description='Third'), + ) + ConsolePort.objects.bulk_create(console_ports) + + # Cables + Cable(termination_a=console_ports[0], termination_b=console_server_ports[0]).save() + Cable(termination_a=console_ports[1], termination_b=console_server_ports[1]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Console Port 1', 'Console Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + # TODO: Fix boolean value + def test_connection_status(self): + params = {'connection_status': 'True'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class ConsoleServerPortTestCase(TestCase): + queryset = ConsoleServerPort.objects.all() + filterset = ConsoleServerPortFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + console_ports = ( + ConsolePort(device=devices[3], name='Console Server Port 1'), + ConsolePort(device=devices[3], name='Console Server Port 2'), + ) + ConsolePort.objects.bulk_create(console_ports) + + console_server_ports = ( + ConsoleServerPort(device=devices[0], name='Console Server Port 1', description='First'), + ConsoleServerPort(device=devices[1], name='Console Server Port 2', description='Second'), + ConsoleServerPort(device=devices[2], name='Console Server Port 3', description='Third'), + ) + ConsoleServerPort.objects.bulk_create(console_server_ports) + + # Cables + Cable(termination_a=console_server_ports[0], termination_b=console_ports[0]).save() + Cable(termination_a=console_server_ports[1], termination_b=console_ports[1]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Console Server Port 1', 'Console Server Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + # TODO: Fix boolean value + def test_connection_status(self): + params = {'connection_status': 'True'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class PowerPortTestCase(TestCase): + queryset = PowerPort.objects.all() + filterset = PowerPortFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + power_outlets = ( + PowerOutlet(device=devices[3], name='Power Outlet 1'), + PowerOutlet(device=devices[3], name='Power Outlet 2'), + ) + PowerOutlet.objects.bulk_create(power_outlets) + + power_ports = ( + PowerPort(device=devices[0], name='Power Port 1', maximum_draw=100, allocated_draw=50, description='First'), + PowerPort(device=devices[1], name='Power Port 2', maximum_draw=200, allocated_draw=100, description='Second'), + PowerPort(device=devices[2], name='Power Port 3', maximum_draw=300, allocated_draw=150, description='Third'), + ) + PowerPort.objects.bulk_create(power_ports) + + # Cables + Cable(termination_a=power_ports[0], termination_b=power_outlets[0]).save() + Cable(termination_a=power_ports[1], termination_b=power_outlets[1]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Power Port 1', 'Power Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_maximum_draw(self): + params = {'maximum_draw': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_allocated_draw(self): + params = {'allocated_draw': [50, 100]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + # TODO: Fix boolean value + def test_connection_status(self): + params = {'connection_status': 'True'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class PowerOutletTestCase(TestCase): + queryset = PowerOutlet.objects.all() + filterset = PowerOutletFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + power_ports = ( + PowerPort(device=devices[3], name='Power Outlet 1'), + PowerPort(device=devices[3], name='Power Outlet 2'), + ) + PowerPort.objects.bulk_create(power_ports) + + power_outlets = ( + PowerOutlet(device=devices[0], name='Power Outlet 1', feed_leg=POWERFEED_LEG_A, description='First'), + PowerOutlet(device=devices[1], name='Power Outlet 2', feed_leg=POWERFEED_LEG_B, description='Second'), + PowerOutlet(device=devices[2], name='Power Outlet 3', feed_leg=POWERFEED_LEG_C, description='Third'), + ) + PowerOutlet.objects.bulk_create(power_outlets) + + # Cables + Cable(termination_a=power_outlets[0], termination_b=power_ports[0]).save() + Cable(termination_a=power_outlets[1], termination_b=power_ports[1]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Power Outlet 1', 'Power Outlet 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_feed_leg(self): + # TODO: Support filtering for multiple values + params = {'feed_leg': POWERFEED_LEG_A} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + # TODO: Fix boolean value + def test_connection_status(self): + params = {'connection_status': 'True'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class InterfaceTestCase(TestCase): + queryset = Interface.objects.all() + filterset = InterfaceFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + interfaces = ( + Interface(device=devices[0], name='Interface 1', type=IFACE_TYPE_1GE_SFP, enabled=True, mgmt_only=True, mtu=100, mode=IFACE_MODE_ACCESS, mac_address='00-00-00-00-00-01', description='First'), + Interface(device=devices[1], name='Interface 2', type=IFACE_TYPE_1GE_GBIC, enabled=True, mgmt_only=True, mtu=200, mode=IFACE_MODE_TAGGED, mac_address='00-00-00-00-00-02', description='Second'), + Interface(device=devices[2], name='Interface 3', type=IFACE_TYPE_1GE_FIXED, enabled=False, mgmt_only=False, mtu=300, mode=IFACE_MODE_TAGGED_ALL, mac_address='00-00-00-00-00-03', description='Third'), + Interface(device=devices[3], name='Interface 4', type=IFACE_TYPE_OTHER, enabled=True, mgmt_only=True), + Interface(device=devices[3], name='Interface 5', type=IFACE_TYPE_OTHER, enabled=True, mgmt_only=True), + Interface(device=devices[3], name='Interface 6', type=IFACE_TYPE_OTHER, enabled=False, mgmt_only=False), + ) + Interface.objects.bulk_create(interfaces) + + # Cables + Cable(termination_a=interfaces[0], termination_b=interfaces[3]).save() + Cable(termination_a=interfaces[1], termination_b=interfaces[4]).save() + # Third pair is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_name(self): + params = {'name': ['Interface 1', 'Interface 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + # TODO: Fix boolean value + def test_connection_status(self): + params = {'connection_status': 'True'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_enabled(self): + params = {'enabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'enabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_mtu(self): + params = {'mtu': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_mgmt_only(self): + params = {'mgmt_only': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'mgmt_only': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_mode(self): + params = {'mode': IFACE_MODE_ACCESS} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_kind(self): + params = {'kind': 'physical'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) + params = {'kind': 'virtual'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0) + + def test_mac_address(self): + params = {'mac_address': ['00-00-00-00-00-01', '00-00-00-00-00-02']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + params = {'type': [IFACE_TYPE_1GE_FIXED, IFACE_TYPE_1GE_GBIC]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class FrontPortTestCase(TestCase): + queryset = FrontPort.objects.all() + filterset = FrontPortFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + rear_ports = ( + RearPort(device=devices[0], name='Rear Port 1', type=PORT_TYPE_8P8C, positions=6), + RearPort(device=devices[1], name='Rear Port 2', type=PORT_TYPE_8P8C, positions=6), + RearPort(device=devices[2], name='Rear Port 3', type=PORT_TYPE_8P8C, positions=6), + RearPort(device=devices[3], name='Rear Port 4', type=PORT_TYPE_8P8C, positions=6), + RearPort(device=devices[3], name='Rear Port 5', type=PORT_TYPE_8P8C, positions=6), + RearPort(device=devices[3], name='Rear Port 6', type=PORT_TYPE_8P8C, positions=6), + ) + RearPort.objects.bulk_create(rear_ports) + + front_ports = ( + FrontPort(device=devices[0], name='Front Port 1', type=PORT_TYPE_8P8C, rear_port=rear_ports[0], rear_port_position=1, description='First'), + FrontPort(device=devices[1], name='Front Port 2', type=PORT_TYPE_110_PUNCH, rear_port=rear_ports[1], rear_port_position=2, description='Second'), + FrontPort(device=devices[2], name='Front Port 3', type=PORT_TYPE_BNC, rear_port=rear_ports[2], rear_port_position=3, description='Third'), + FrontPort(device=devices[3], name='Front Port 4', type=PORT_TYPE_FC, rear_port=rear_ports[3], rear_port_position=1), + FrontPort(device=devices[3], name='Front Port 5', type=PORT_TYPE_FC, rear_port=rear_ports[4], rear_port_position=1), + FrontPort(device=devices[3], name='Front Port 6', type=PORT_TYPE_FC, rear_port=rear_ports[5], rear_port_position=1), + ) + FrontPort.objects.bulk_create(front_ports) + + # Cables + Cable(termination_a=front_ports[0], termination_b=front_ports[3]).save() + Cable(termination_a=front_ports[1], termination_b=front_ports[4]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Front Port 1', 'Front Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Test for multiple values + params = {'type': PORT_TYPE_8P8C} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class RearPortTestCase(TestCase): + queryset = RearPort.objects.all() + filterset = RearPortFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + Device(name=None, device_type=device_type, device_role=device_role, site=site), # For cable connections + ) + Device.objects.bulk_create(devices) + + rear_ports = ( + RearPort(device=devices[0], name='Rear Port 1', type=PORT_TYPE_8P8C, positions=1, description='First'), + RearPort(device=devices[1], name='Rear Port 2', type=PORT_TYPE_110_PUNCH, positions=2, description='Second'), + RearPort(device=devices[2], name='Rear Port 3', type=PORT_TYPE_BNC, positions=3, description='Third'), + RearPort(device=devices[3], name='Rear Port 4', type=PORT_TYPE_FC, positions=4), + RearPort(device=devices[3], name='Rear Port 5', type=PORT_TYPE_FC, positions=5), + RearPort(device=devices[3], name='Rear Port 6', type=PORT_TYPE_FC, positions=6), + ) + RearPort.objects.bulk_create(rear_ports) + + # Cables + Cable(termination_a=rear_ports[0], termination_b=rear_ports[3]).save() + Cable(termination_a=rear_ports[1], termination_b=rear_ports[4]).save() + # Third port is not connected + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Rear Port 1', 'Rear Port 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + # TODO: Test for multiple values + params = {'type': PORT_TYPE_8P8C} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_positions(self): + params = {'positions': [1, 2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class DeviceBayTestCase(TestCase): + queryset = DeviceBay.objects.all() + filterset = DeviceBayFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=site), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=site), + ) + Device.objects.bulk_create(devices) + + device_bays = ( + DeviceBay(device=devices[0], name='Device Bay 1', description='First'), + DeviceBay(device=devices[1], name='Device Bay 2', description='Second'), + DeviceBay(device=devices[2], name='Device Bay 3', description='Third'), + ) + DeviceBay.objects.bulk_create(device_bays) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Device Bay 1', 'Device Bay 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['First', 'Second']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class InventoryItemTestCase(TestCase): + queryset = InventoryItem.objects.all() + filterset = InventoryItemFilter + + @classmethod + def setUpTestData(cls): + + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), + ) + Manufacturer.objects.bulk_create(manufacturers) + + device_type = DeviceType.objects.create(manufacturer=manufacturers[0], model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=sites[0]), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=sites[1]), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=sites[2]), + ) + Device.objects.bulk_create(devices) + + inventory_items = ( + InventoryItem(device=devices[0], manufacturer=manufacturers[0], name='Inventory Item 1', part_id='1001', serial='ABC', asset_tag='1001', discovered=True, description='First'), + InventoryItem(device=devices[1], manufacturer=manufacturers[1], name='Inventory Item 2', part_id='1002', serial='DEF', asset_tag='1002', discovered=True, description='Second'), + InventoryItem(device=devices[2], manufacturer=manufacturers[2], name='Inventory Item 3', part_id='1003', serial='GHI', asset_tag='1003', discovered=False, description='Third'), + ) + InventoryItem.objects.bulk_create(inventory_items) + + child_inventory_items = ( + InventoryItem(device=devices[0], name='Inventory Item 1A', parent=inventory_items[0]), + InventoryItem(device=devices[1], name='Inventory Item 2A', parent=inventory_items[1]), + InventoryItem(device=devices[2], name='Inventory Item 3A', parent=inventory_items[2]), + ) + InventoryItem.objects.bulk_create(child_inventory_items) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Inventory Item 1', 'Inventory Item 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_part_id(self): + params = {'part_id': ['1001', '1002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_asset_tag(self): + params = {'asset_tag': ['1001', '1002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_discovered(self): + # TODO: Fix boolean value + params = {'discovered': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'discovered': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_device(self): + # TODO: Allow multiple values + device = Device.objects.first() + params = {'device_id': device.pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': device.name} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_parent_id(self): + parent_items = InventoryItem.objects.filter(parent__isnull=True)[:2] + params = {'parent_id': [parent_items[0].pk, parent_items[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_manufacturer(self): + manufacturers = Manufacturer.objects.all()[:2] + params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_serial(self): + params = {'serial': 'ABC'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'serial': 'abc'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class VirtualChassisTestCase(TestCase): + queryset = VirtualChassis.objects.all() + filterset = VirtualChassisFilter + + @classmethod + def setUpTestData(cls): + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=sites[0], vc_position=1), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=sites[0], vc_position=2), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=sites[1], vc_position=1), + Device(name='Device 4', device_type=device_type, device_role=device_role, site=sites[1], vc_position=2), + Device(name='Device 5', device_type=device_type, device_role=device_role, site=sites[2], vc_position=1), + Device(name='Device 6', device_type=device_type, device_role=device_role, site=sites[2], vc_position=2), + ) + Device.objects.bulk_create(devices) + + virtual_chassis = ( + VirtualChassis(master=devices[0], domain='Domain 1'), + VirtualChassis(master=devices[2], domain='Domain 2'), + VirtualChassis(master=devices[4], domain='Domain 3'), + ) + VirtualChassis.objects.bulk_create(virtual_chassis) + + Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis[0]) + Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=virtual_chassis[1]) + Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[2]) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_domain(self): + params = {'domain': ['Domain 1', 'Domain 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class CableTestCase(TestCase): + queryset = Cable.objects.all() + filterset = CableFilter + + @classmethod + def setUpTestData(cls): + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + Site(name='Site 3', slug='site-3'), + ) + Site.objects.bulk_create(sites) + + racks = ( + Rack(name='Rack 1', site=sites[0]), + Rack(name='Rack 2', site=sites[1]), + Rack(name='Rack 3', site=sites[2]), + ) + Rack.objects.bulk_create(racks) + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model 1', slug='model-1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(name='Device 1', device_type=device_type, device_role=device_role, site=sites[0], rack=racks[0], position=1), + Device(name='Device 2', device_type=device_type, device_role=device_role, site=sites[0], rack=racks[0], position=2), + Device(name='Device 3', device_type=device_type, device_role=device_role, site=sites[1], rack=racks[1], position=1), + Device(name='Device 4', device_type=device_type, device_role=device_role, site=sites[1], rack=racks[1], position=2), + Device(name='Device 5', device_type=device_type, device_role=device_role, site=sites[2], rack=racks[2], position=1), + Device(name='Device 6', device_type=device_type, device_role=device_role, site=sites[2], rack=racks[2], position=2), + ) + Device.objects.bulk_create(devices) + + interfaces = ( + Interface(device=devices[0], name='Interface 1', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[0], name='Interface 2', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[1], name='Interface 3', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[1], name='Interface 4', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[2], name='Interface 5', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[2], name='Interface 6', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[3], name='Interface 7', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[3], name='Interface 8', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[4], name='Interface 9', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[4], name='Interface 10', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[5], name='Interface 11', type=IFACE_TYPE_1GE_FIXED), + Interface(device=devices[5], name='Interface 12', type=IFACE_TYPE_1GE_FIXED), + ) + Interface.objects.bulk_create(interfaces) + + # Cables + Cable(termination_a=interfaces[1], termination_b=interfaces[2], label='Cable 1', type=CABLE_TYPE_CAT3, status=CONNECTION_STATUS_CONNECTED, color='aa1409', length=10, length_unit=LENGTH_UNIT_FOOT).save() + Cable(termination_a=interfaces[3], termination_b=interfaces[4], label='Cable 2', type=CABLE_TYPE_CAT3, status=CONNECTION_STATUS_CONNECTED, color='aa1409', length=20, length_unit=LENGTH_UNIT_FOOT).save() + Cable(termination_a=interfaces[5], termination_b=interfaces[6], label='Cable 3', type=CABLE_TYPE_CAT5E, status=CONNECTION_STATUS_CONNECTED, color='f44336', length=30, length_unit=LENGTH_UNIT_FOOT).save() + Cable(termination_a=interfaces[7], termination_b=interfaces[8], label='Cable 4', type=CABLE_TYPE_CAT5E, status=CONNECTION_STATUS_PLANNED, color='f44336', length=40, length_unit=LENGTH_UNIT_FOOT).save() + Cable(termination_a=interfaces[9], termination_b=interfaces[10], label='Cable 5', type=CABLE_TYPE_CAT6, status=CONNECTION_STATUS_PLANNED, color='e91e63', length=10, length_unit=LENGTH_UNIT_METER).save() + Cable(termination_a=interfaces[11], termination_b=interfaces[0], label='Cable 6', type=CABLE_TYPE_CAT6, status=CONNECTION_STATUS_PLANNED, color='e91e63', length=20, length_unit=LENGTH_UNIT_METER).save() + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_label(self): + params = {'label': ['Cable 1', 'Cable 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_length(self): + params = {'length': [10, 20]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_length_unit(self): + params = {'length_unit': LENGTH_UNIT_FOOT} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_type(self): + params = {'type': [CABLE_TYPE_CAT3, CABLE_TYPE_CAT5E]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_status(self): + params = {'status': [CONNECTION_STATUS_CONNECTED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_color(self): + params = {'color': ['aa1409', 'f44336']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_rack(self): + racks = Rack.objects.all()[:2] + params = {'rack_id': [racks[0].pk, racks[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + params = {'rack': [racks[0].name, racks[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + + def test_site(self): + site = Site.objects.all()[:2] + params = {'site_id': [site[0].pk, site[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + params = {'site': [site[0].slug, site[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + + +class PowerPanelTestCase(TestCase): + queryset = PowerPanel.objects.all() + filterset = PowerPanelFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + rack_groups = ( + RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]), + RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2]), + ) + RackGroup.objects.bulk_create(rack_groups) + + power_panels = ( + PowerPanel(name='Power Panel 1', site=sites[0], rack_group=rack_groups[0]), + PowerPanel(name='Power Panel 2', site=sites[1], rack_group=rack_groups[1]), + PowerPanel(name='Power Panel 3', site=sites[2], rack_group=rack_groups[2]), + ) + PowerPanel.objects.bulk_create(power_panels) + + def test_name(self): + params = {'name': ['Power Panel 1', 'Power Panel 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rack_group(self): + rack_groups = RackGroup.objects.all()[:2] + params = {'rack_group_id': [rack_groups[0].pk, rack_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class PowerFeedTestCase(TestCase): + queryset = PowerFeed.objects.all() + filterset = PowerFeedFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Region 1', slug='region-1'), + Region(name='Region 2', slug='region-2'), + Region(name='Region 3', slug='region-3'), + ) + for region in regions: + region.save() + + sites = ( + Site(name='Site 1', slug='site-1', region=regions[0]), + Site(name='Site 2', slug='site-2', region=regions[1]), + Site(name='Site 3', slug='site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + racks = ( + Rack(name='Rack 1', site=sites[0]), + Rack(name='Rack 2', site=sites[1]), + Rack(name='Rack 3', site=sites[2]), + ) + Rack.objects.bulk_create(racks) + + power_panels = ( + PowerPanel(name='Power Panel 1', site=sites[0]), + PowerPanel(name='Power Panel 2', site=sites[1]), + PowerPanel(name='Power Panel 3', site=sites[2]), + ) + PowerPanel.objects.bulk_create(power_panels) + + power_feeds = ( + PowerFeed(power_panel=power_panels[0], rack=racks[0], name='Power Feed 1', status=POWERFEED_STATUS_ACTIVE, type=POWERFEED_TYPE_PRIMARY, supply=POWERFEED_SUPPLY_AC, phase=POWERFEED_PHASE_3PHASE, voltage=100, amperage=100, max_utilization=10), + PowerFeed(power_panel=power_panels[1], rack=racks[1], name='Power Feed 2', status=POWERFEED_STATUS_FAILED, type=POWERFEED_TYPE_PRIMARY, supply=POWERFEED_SUPPLY_AC, phase=POWERFEED_PHASE_3PHASE, voltage=200, amperage=200, max_utilization=20), + PowerFeed(power_panel=power_panels[2], rack=racks[2], name='Power Feed 3', status=POWERFEED_STATUS_OFFLINE, type=POWERFEED_TYPE_REDUNDANT, supply=POWERFEED_SUPPLY_DC, phase=POWERFEED_PHASE_SINGLE, voltage=300, amperage=300, max_utilization=30), + ) + PowerFeed.objects.bulk_create(power_feeds) + + def test_name(self): + params = {'name': ['Power Feed 1', 'Power Feed 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + # TODO: Test for multiple values + params = {'status': POWERFEED_STATUS_ACTIVE} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_type(self): + params = {'type': POWERFEED_TYPE_PRIMARY} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_supply(self): + params = {'supply': POWERFEED_SUPPLY_AC} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_phase(self): + params = {'phase': POWERFEED_PHASE_3PHASE} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_voltage(self): + params = {'voltage': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_amperage(self): + params = {'amperage': [100, 200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_max_utilization(self): + params = {'max_utilization': [10, 20]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_power_panel_id(self): + power_panels = PowerPanel.objects.all()[:2] + params = {'power_panel_id': [power_panels[0].pk, power_panels[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rack_id(self): + racks = Rack.objects.all()[:2] + params = {'rack_id': [racks[0].pk, racks[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +# TODO: Connection filters diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index 8c805ebdf..cd1306bc4 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -8,6 +8,20 @@ from .constants import * from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, Tag, TopologyMap +__all__ = ( + 'ConfigContextFilter', + 'CreatedUpdatedFilterSet', + 'CustomFieldFilter', + 'CustomFieldFilterSet', + 'ExportTemplateFilter', + 'GraphFilter', + 'LocalConfigContextFilter', + 'ObjectChangeFilter', + 'TagFilter', + 'TopologyMapFilter', +) + + class CustomFieldFilter(django_filters.Filter): """ Filter objects by the presence of a CustomFieldValue. The filter's name is used as the CustomField name. diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index 28238b008..4876595a3 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -263,12 +263,12 @@ class BaseScript: def run(self, data): raise NotImplementedError("The script must define a run() method.") - def as_form(self, data=None, files=None): + def as_form(self, data=None, files=None, initial=None): """ Return a Django form suitable for populating the context data required to run this Script. """ vars = self._get_vars() - form = ScriptForm(vars, data, files, commit_default=getattr(self.Meta, 'commit_default', True)) + form = ScriptForm(vars, data, files, initial=initial, commit_default=getattr(self.Meta, 'commit_default', True)) return form diff --git a/netbox/extras/templatetags/custom_links.py b/netbox/extras/templatetags/custom_links.py index 8c927a0ae..7dae81a1f 100644 --- a/netbox/extras/templatetags/custom_links.py +++ b/netbox/extras/templatetags/custom_links.py @@ -68,8 +68,9 @@ def custom_links(obj): text_rendered = render_jinja2(cl.text, context) if text_rendered: link_target = ' target="_blank"' if cl.new_window else '' + link_rendered = render_jinja2(cl.url, context) links_rendered.append( - GROUP_LINK.format(cl.url, link_target, cl.text) + GROUP_LINK.format(link_rendered, link_target, text_rendered) ) except Exception as e: links_rendered.append( diff --git a/netbox/extras/tests/test_filters.py b/netbox/extras/tests/test_filters.py new file mode 100644 index 000000000..6c6b8145b --- /dev/null +++ b/netbox/extras/tests/test_filters.py @@ -0,0 +1,181 @@ +from django.contrib.contenttypes.models import ContentType +from django.test import TestCase + +from dcim.models import DeviceRole, Platform, Region, Site +from extras.constants import * +from extras.filters import * +from extras.models import ConfigContext, ExportTemplate, Graph +from tenancy.models import Tenant, TenantGroup + + +class GraphTestCase(TestCase): + queryset = Graph.objects.all() + filterset = GraphFilter + + @classmethod + def setUpTestData(cls): + + graphs = ( + Graph(name='Graph 1', type=GRAPH_TYPE_DEVICE, source='http://example.com/1'), + Graph(name='Graph 2', type=GRAPH_TYPE_INTERFACE, source='http://example.com/2'), + Graph(name='Graph 3', type=GRAPH_TYPE_SITE, source='http://example.com/3'), + ) + Graph.objects.bulk_create(graphs) + + def test_name(self): + params = {'name': 'Graph 1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_type(self): + params = {'type': GRAPH_TYPE_DEVICE} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + +class ExportTemplateTestCase(TestCase): + queryset = ExportTemplate.objects.all() + filterset = ExportTemplateFilter + + @classmethod + def setUpTestData(cls): + + content_types = ContentType.objects.filter(model__in=['site', 'rack', 'device']) + + export_templates = ( + ExportTemplate(name='Export Template 1', content_type=content_types[0], template_language=TEMPLATE_LANGUAGE_DJANGO, template_code='TESTING'), + ExportTemplate(name='Export Template 2', content_type=content_types[1], template_language=TEMPLATE_LANGUAGE_JINJA2, template_code='TESTING'), + ExportTemplate(name='Export Template 3', content_type=content_types[2], template_language=TEMPLATE_LANGUAGE_JINJA2, template_code='TESTING'), + ) + ExportTemplate.objects.bulk_create(export_templates) + + def test_name(self): + params = {'name': 'Export Template 1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_content_type(self): + params = {'content_type': ContentType.objects.get(model='site').pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_template_language(self): + params = {'template_language': TEMPLATE_LANGUAGE_JINJA2} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class ConfigContextTestCase(TestCase): + queryset = ConfigContext.objects.all() + filterset = ConfigContextFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + Region(name='Test Region 3', slug='test-region-3'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1'), + Site(name='Test Site 2', slug='test-site-2'), + Site(name='Test Site 3', slug='test-site-3'), + ) + Site.objects.bulk_create(sites) + + device_roles = ( + DeviceRole(name='Device Role 1', slug='device-role-1'), + DeviceRole(name='Device Role 2', slug='device-role-2'), + DeviceRole(name='Device Role 3', slug='device-role-3'), + ) + DeviceRole.objects.bulk_create(device_roles) + + platforms = ( + Platform(name='Platform 1', slug='platform-1'), + Platform(name='Platform 2', slug='platform-2'), + Platform(name='Platform 3', slug='platform-3'), + ) + Platform.objects.bulk_create(platforms) + + tenant_groups = ( + TenantGroup(name='Tenant Group 1', slug='tenant-group-1'), + TenantGroup(name='Tenant Group 2', slug='tenant-group-2'), + TenantGroup(name='Tenant Group 3', slug='tenant-group-3'), + ) + TenantGroup.objects.bulk_create(tenant_groups) + + tenants = ( + Tenant(name='Tenant 1', slug='tenant-1'), + Tenant(name='Tenant 2', slug='tenant-2'), + Tenant(name='Tenant 3', slug='tenant-3'), + ) + Tenant.objects.bulk_create(tenants) + + for i in range(0, 3): + is_active = bool(i % 2) + c = ConfigContext.objects.create( + name='Config Context {}'.format(i + 1), + is_active=is_active, + data='{"foo": 123}' + ) + c.regions.set([regions[i]]) + c.sites.set([sites[i]]) + c.roles.set([device_roles[i]]) + c.platforms.set([platforms[i]]) + c.tenant_groups.set([tenant_groups[i]]) + c.tenants.set([tenants[i]]) + + def test_name(self): + params = {'name': 'Config Context 1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_is_active(self): + params = {'is_active': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'is_active': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_role(self): + device_roles = DeviceRole.objects.all()[:2] + params = {'role_id': [device_roles[0].pk, device_roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'role': [device_roles[0].slug, device_roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_platform(self): + platforms = Platform.objects.all()[:2] + params = {'platform_id': [platforms[0].pk, platforms[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'platform': [platforms[0].slug, platforms[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_tenant_group(self): + tenant_groups = TenantGroup.objects.all()[:2] + params = {'tenant_group_id': [tenant_groups[0].pk, tenant_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_tenant_(self): + tenants = Tenant.objects.all()[:2] + params = {'tenant_id': [tenants[0].pk, tenants[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'tenant': [tenants[0].slug, tenants[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +# TODO: ObjectChangeFilter test diff --git a/netbox/extras/views.py b/netbox/extras/views.py index eb17a65ab..b9ef7f9b4 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -392,7 +392,7 @@ class ScriptView(PermissionRequiredMixin, View): def get(self, request, module, name): script = self._get_script(module, name) - form = script.as_form() + form = script.as_form(initial=request.GET) return render(request, 'extras/script.html', { 'module': module, diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index bf14b80d6..9d1b1d650 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -13,6 +13,19 @@ from .constants import * from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +__all__ = ( + 'AggregateFilter', + 'IPAddressFilter', + 'PrefixFilter', + 'RIRFilter', + 'RoleFilter', + 'ServiceFilter', + 'VLANFilter', + 'VLANGroupFilter', + 'VRFFilter', +) + + class VRFFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): id__in = NumericInFilter( field_name='id', diff --git a/netbox/ipam/tests/test_filters.py b/netbox/ipam/tests/test_filters.py new file mode 100644 index 000000000..5ae912bc6 --- /dev/null +++ b/netbox/ipam/tests/test_filters.py @@ -0,0 +1,645 @@ +from django.test import TestCase + +from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Region, Site +from ipam.constants import * +from ipam.filters import * +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from virtualization.models import Cluster, ClusterType, VirtualMachine + + +class VRFTestCase(TestCase): + queryset = VRF.objects.all() + filterset = VRFFilter + + @classmethod + def setUpTestData(cls): + + vrfs = ( + VRF(name='VRF 1', rd='65000:100', enforce_unique=False), + VRF(name='VRF 2', rd='65000:200', enforce_unique=False), + VRF(name='VRF 3', rd='65000:300', enforce_unique=False), + VRF(name='VRF 4', rd='65000:400', enforce_unique=True), + VRF(name='VRF 5', rd='65000:500', enforce_unique=True), + VRF(name='VRF 6', rd='65000:600', enforce_unique=True), + ) + VRF.objects.bulk_create(vrfs) + + def test_name(self): + params = {'name': ['VRF 1', 'VRF 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rd(self): + params = {'rd': ['65000:100', '65000:200']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_enforce_unique(self): + params = {'enforce_unique': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'enforce_unique': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + +class RIRTestCase(TestCase): + queryset = RIR.objects.all() + filterset = RIRFilter + + @classmethod + def setUpTestData(cls): + + rirs = ( + RIR(name='RIR 1', slug='rir-1', is_private=False), + RIR(name='RIR 2', slug='rir-2', is_private=False), + RIR(name='RIR 3', slug='rir-3', is_private=False), + RIR(name='RIR 4', slug='rir-4', is_private=True), + RIR(name='RIR 5', slug='rir-5', is_private=True), + RIR(name='RIR 6', slug='rir-6', is_private=True), + ) + RIR.objects.bulk_create(rirs) + + def test_name(self): + params = {'name': ['RIR 1', 'RIR 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['rir-1', 'rir-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_is_private(self): + params = {'is_private': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'is_private': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + +class AggregateTestCase(TestCase): + queryset = Aggregate.objects.all() + filterset = AggregateFilter + + @classmethod + def setUpTestData(cls): + + rirs = ( + RIR(name='RIR 1', slug='rir-1'), + RIR(name='RIR 2', slug='rir-2'), + RIR(name='RIR 3', slug='rir-3'), + ) + RIR.objects.bulk_create(rirs) + + aggregates = ( + Aggregate(family=4, prefix='10.1.0.0/16', rir=rirs[0], date_added='2020-01-01'), + Aggregate(family=4, prefix='10.2.0.0/16', rir=rirs[0], date_added='2020-01-02'), + Aggregate(family=4, prefix='10.3.0.0/16', rir=rirs[1], date_added='2020-01-03'), + Aggregate(family=6, prefix='2001:db8:1::/48', rir=rirs[1], date_added='2020-01-04'), + Aggregate(family=6, prefix='2001:db8:2::/48', rir=rirs[2], date_added='2020-01-05'), + Aggregate(family=6, prefix='2001:db8:3::/48', rir=rirs[2], date_added='2020-01-06'), + ) + Aggregate.objects.bulk_create(aggregates) + + def test_family(self): + params = {'family': '4'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_date_added(self): + params = {'date_added': ['2020-01-01', '2020-01-02']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + # TODO: Test for multiple values + def test_prefix(self): + params = {'prefix': '10.1.0.0/16'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_rir(self): + rirs = RIR.objects.all()[:2] + params = {'rir_id': [rirs[0].pk, rirs[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'rir': [rirs[0].slug, rirs[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + +class RoleTestCase(TestCase): + queryset = Role.objects.all() + filterset = RoleFilter + + @classmethod + def setUpTestData(cls): + + roles = ( + Role(name='Role 1', slug='role-1'), + Role(name='Role 2', slug='role-2'), + Role(name='Role 3', slug='role-3'), + ) + Role.objects.bulk_create(roles) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Role 1', 'Role 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['role-1', 'role-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class PrefixTestCase(TestCase): + queryset = Prefix.objects.all() + filterset = PrefixFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + Region(name='Test Region 3', slug='test-region-3'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1', region=regions[0]), + Site(name='Test Site 2', slug='test-site-2', region=regions[1]), + Site(name='Test Site 3', slug='test-site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + vrfs = ( + VRF(name='VRF 1', rd='65000:100'), + VRF(name='VRF 2', rd='65000:200'), + VRF(name='VRF 3', rd='65000:300'), + ) + VRF.objects.bulk_create(vrfs) + + vlans = ( + VLAN(vid=1, name='VLAN 1'), + VLAN(vid=2, name='VLAN 2'), + VLAN(vid=3, name='VLAN 3'), + ) + VLAN.objects.bulk_create(vlans) + + roles = ( + Role(name='Role 1', slug='role-1'), + Role(name='Role 2', slug='role-2'), + Role(name='Role 3', slug='role-3'), + ) + Role.objects.bulk_create(roles) + + prefixes = ( + Prefix(family=4, prefix='10.0.0.0/24', site=None, vrf=None, vlan=None, role=None, is_pool=True), + Prefix(family=4, prefix='10.0.1.0/24', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]), + Prefix(family=4, prefix='10.0.2.0/24', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PREFIX_STATUS_DEPRECATED), + Prefix(family=4, prefix='10.0.3.0/24', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PREFIX_STATUS_RESERVED), + Prefix(family=6, prefix='2001:db8::/64', site=None, vrf=None, vlan=None, role=None, is_pool=True), + Prefix(family=6, prefix='2001:db8:0:1::/64', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]), + Prefix(family=6, prefix='2001:db8:0:2::/64', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PREFIX_STATUS_DEPRECATED), + Prefix(family=6, prefix='2001:db8:0:3::/64', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PREFIX_STATUS_RESERVED), + Prefix(family=4, prefix='10.0.0.0/16'), + Prefix(family=6, prefix='2001:db8::/32'), + ) + Prefix.objects.bulk_create(prefixes) + + def test_family(self): + params = {'family': '6'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + + def test_is_pool(self): + params = {'is_pool': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'is_pool': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_within(self): + params = {'within': '10.0.0.0/16'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_within_include(self): + params = {'within_include': '10.0.0.0/16'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + + def test_contains(self): + params = {'contains': '10.0.1.0/24'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'contains': '2001:db8:0:1::/64'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_mask_length(self): + params = {'mask_length': '24'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_vrf(self): + vrfs = VRF.objects.all()[:2] + params = {'vrf_id': [vrfs[0].pk, vrfs[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'vrf': [vrfs[0].rd, vrfs[1].rd]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_vlan(self): + vlans = VLAN.objects.all()[:2] + params = {'vlan_id': [vlans[0].pk, vlans[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + # TODO: Test for multiple values + params = {'vlan_vid': vlans[0].vid} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_role(self): + roles = Role.objects.all()[:2] + params = {'role_id': [roles[0].pk, roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'role': [roles[0].slug, roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_status(self): + params = {'status': [PREFIX_STATUS_DEPRECATED, PREFIX_STATUS_RESERVED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + +class IPAddressTestCase(TestCase): + queryset = IPAddress.objects.all() + filterset = IPAddressFilter + + @classmethod + def setUpTestData(cls): + + vrfs = ( + VRF(name='VRF 1', rd='65000:100'), + VRF(name='VRF 2', rd='65000:200'), + VRF(name='VRF 3', rd='65000:300'), + ) + VRF.objects.bulk_create(vrfs) + + site = Site.objects.create(name='Site 1', slug='site-1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(device_type=device_type, name='Device 1', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 2', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 3', site=site, device_role=device_role), + ) + Device.objects.bulk_create(devices) + + clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + cluster = Cluster.objects.create(type=clustertype, name='Cluster 1') + + virtual_machines = ( + VirtualMachine(name='Virtual Machine 1', cluster=cluster), + VirtualMachine(name='Virtual Machine 2', cluster=cluster), + VirtualMachine(name='Virtual Machine 3', cluster=cluster), + ) + VirtualMachine.objects.bulk_create(virtual_machines) + + interfaces = ( + Interface(device=devices[0], name='Interface 1'), + Interface(device=devices[1], name='Interface 2'), + Interface(device=devices[2], name='Interface 3'), + Interface(virtual_machine=virtual_machines[0], name='Interface 1'), + Interface(virtual_machine=virtual_machines[1], name='Interface 2'), + Interface(virtual_machine=virtual_machines[2], name='Interface 3'), + ) + Interface.objects.bulk_create(interfaces) + + ipaddresses = ( + IPAddress(family=4, address='10.0.0.1/24', vrf=None, interface=None, status=IPADDRESS_STATUS_ACTIVE, role=None, dns_name='ipaddress-a'), + IPAddress(family=4, address='10.0.0.2/24', vrf=vrfs[0], interface=interfaces[0], status=IPADDRESS_STATUS_ACTIVE, role=None, dns_name='ipaddress-b'), + IPAddress(family=4, address='10.0.0.3/24', vrf=vrfs[1], interface=interfaces[1], status=IPADDRESS_STATUS_RESERVED, role=IPADDRESS_ROLE_VIP, dns_name='ipaddress-c'), + IPAddress(family=4, address='10.0.0.4/24', vrf=vrfs[2], interface=interfaces[2], status=IPADDRESS_STATUS_DEPRECATED, role=IPADDRESS_ROLE_SECONDARY, dns_name='ipaddress-d'), + IPAddress(family=6, address='2001:db8::1/64', vrf=None, interface=None, status=IPADDRESS_STATUS_ACTIVE, role=None, dns_name='ipaddress-a'), + IPAddress(family=6, address='2001:db8::2/64', vrf=vrfs[0], interface=interfaces[3], status=IPADDRESS_STATUS_ACTIVE, role=None, dns_name='ipaddress-b'), + IPAddress(family=6, address='2001:db8::3/64', vrf=vrfs[1], interface=interfaces[4], status=IPADDRESS_STATUS_RESERVED, role=IPADDRESS_ROLE_VIP, dns_name='ipaddress-c'), + IPAddress(family=6, address='2001:db8::4/64', vrf=vrfs[2], interface=interfaces[5], status=IPADDRESS_STATUS_DEPRECATED, role=IPADDRESS_ROLE_SECONDARY, dns_name='ipaddress-d'), + ) + IPAddress.objects.bulk_create(ipaddresses) + + def test_family(self): + params = {'family': '6'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_dns_name(self): + params = {'dns_name': ['ipaddress-a', 'ipaddress-b']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_parent(self): + params = {'parent': '10.0.0.0/24'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'parent': '2001:db8::/64'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def filter_address(self): + # Check IPv4 and IPv6, with and without a mask + params = {'address': '10.0.0.1/24'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'address': '10.0.0.1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'address': '2001:db8::1/64'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'address': '2001:db8::1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_mask_length(self): + params = {'mask_length': '24'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_vrf(self): + vrfs = VRF.objects.all()[:2] + params = {'vrf_id': [vrfs[0].pk, vrfs[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'vrf': [vrfs[0].rd, vrfs[1].rd]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + # TODO: Test for multiple values + def test_device(self): + device = Device.objects.first() + params = {'device_id': device.pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'device': device.name} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_virtual_machine(self): + vms = VirtualMachine.objects.all()[:2] + params = {'virtual_machine_id': [vms[0].pk, vms[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_machine': [vms[0].name, vms[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_interface(self): + interfaces = Interface.objects.all()[:2] + params = {'interface_id': [interfaces[0].pk, interfaces[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'interface': ['Interface 1', 'Interface 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_assigned_to_interface(self): + params = {'assigned_to_interface': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) + params = {'assigned_to_interface': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + params = {'status': [PREFIX_STATUS_DEPRECATED, PREFIX_STATUS_RESERVED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_role(self): + params = {'role': [IPADDRESS_ROLE_SECONDARY, IPADDRESS_ROLE_VIP]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + +class VLANGroupTestCase(TestCase): + queryset = VLANGroup.objects.all() + filterset = VLANGroupFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + Region(name='Test Region 3', slug='test-region-3'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1', region=regions[0]), + Site(name='Test Site 2', slug='test-site-2', region=regions[1]), + Site(name='Test Site 3', slug='test-site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + vlan_groups = ( + VLANGroup(name='VLAN Group 1', slug='vlan-group-1', site=sites[0]), + VLANGroup(name='VLAN Group 2', slug='vlan-group-2', site=sites[1]), + VLANGroup(name='VLAN Group 3', slug='vlan-group-3', site=sites[2]), + VLANGroup(name='VLAN Group 4', slug='vlan-group-4', site=None), + ) + VLANGroup.objects.bulk_create(vlan_groups) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['VLAN Group 1', 'VLAN Group 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['vlan-group-1', 'vlan-group-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VLANTestCase(TestCase): + queryset = VLAN.objects.all() + filterset = VLANFilter + + @classmethod + def setUpTestData(cls): + + regions = ( + Region(name='Test Region 1', slug='test-region-1'), + Region(name='Test Region 2', slug='test-region-2'), + Region(name='Test Region 3', slug='test-region-3'), + ) + # Can't use bulk_create for models with MPTT fields + for r in regions: + r.save() + + sites = ( + Site(name='Test Site 1', slug='test-site-1', region=regions[0]), + Site(name='Test Site 2', slug='test-site-2', region=regions[1]), + Site(name='Test Site 3', slug='test-site-3', region=regions[2]), + ) + Site.objects.bulk_create(sites) + + roles = ( + Role(name='Role 1', slug='role-1'), + Role(name='Role 2', slug='role-2'), + Role(name='Role 3', slug='role-3'), + ) + Role.objects.bulk_create(roles) + + groups = ( + VLANGroup(name='VLAN Group 1', slug='vlan-group-1', site=sites[0]), + VLANGroup(name='VLAN Group 2', slug='vlan-group-2', site=sites[1]), + VLANGroup(name='VLAN Group 3', slug='vlan-group-3', site=None), + ) + VLANGroup.objects.bulk_create(groups) + + vlans = ( + VLAN(vid=101, name='VLAN 101', site=sites[0], group=groups[0], role=roles[0], status=VLAN_STATUS_ACTIVE), + VLAN(vid=102, name='VLAN 102', site=sites[0], group=groups[0], role=roles[0], status=VLAN_STATUS_ACTIVE), + VLAN(vid=201, name='VLAN 201', site=sites[1], group=groups[1], role=roles[1], status=VLAN_STATUS_DEPRECATED), + VLAN(vid=202, name='VLAN 202', site=sites[1], group=groups[1], role=roles[1], status=VLAN_STATUS_DEPRECATED), + VLAN(vid=301, name='VLAN 301', site=sites[2], group=groups[2], role=roles[2], status=VLAN_STATUS_RESERVED), + VLAN(vid=302, name='VLAN 302', site=sites[2], group=groups[2], role=roles[2], status=VLAN_STATUS_RESERVED), + ) + VLAN.objects.bulk_create(vlans) + + def test_name(self): + params = {'name': ['VLAN 101', 'VLAN 102']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_rd(self): + params = {'vid': ['101', '201', '301']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_region(self): + regions = Region.objects.all()[:2] + params = {'region_id': [regions[0].pk, regions[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'region': [regions[0].slug, regions[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_site(self): + sites = Site.objects.all()[:2] + params = {'site_id': [sites[0].pk, sites[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'site': [sites[0].slug, sites[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_group(self): + groups = VLANGroup.objects.all()[:2] + params = {'group_id': [groups[0].pk, groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'group': [groups[0].slug, groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_role(self): + roles = Role.objects.all()[:2] + params = {'role_id': [roles[0].pk, roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'role': [roles[0].slug, roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_status(self): + params = {'status': [VLAN_STATUS_ACTIVE, VLAN_STATUS_DEPRECATED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + +class ServiceTestCase(TestCase): + queryset = Service.objects.all() + filterset = ServiceFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site-1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(device_type=device_type, name='Device 1', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 2', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 3', site=site, device_role=device_role), + ) + Device.objects.bulk_create(devices) + + clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + cluster = Cluster.objects.create(type=clustertype, name='Cluster 1') + + virtual_machines = ( + VirtualMachine(name='Virtual Machine 1', cluster=cluster), + VirtualMachine(name='Virtual Machine 2', cluster=cluster), + VirtualMachine(name='Virtual Machine 3', cluster=cluster), + ) + VirtualMachine.objects.bulk_create(virtual_machines) + + services = ( + Service(device=devices[0], name='Service 1', protocol=IP_PROTOCOL_TCP, port=1001), + Service(device=devices[1], name='Service 2', protocol=IP_PROTOCOL_TCP, port=1002), + Service(device=devices[2], name='Service 3', protocol=IP_PROTOCOL_UDP, port=1003), + Service(virtual_machine=virtual_machines[0], name='Service 4', protocol=IP_PROTOCOL_TCP, port=2001), + Service(virtual_machine=virtual_machines[1], name='Service 5', protocol=IP_PROTOCOL_TCP, port=2002), + Service(virtual_machine=virtual_machines[2], name='Service 6', protocol=IP_PROTOCOL_UDP, port=2003), + ) + Service.objects.bulk_create(services) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:3] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_name(self): + params = {'name': ['Service 1', 'Service 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_protocol(self): + params = {'protocol': IP_PROTOCOL_TCP} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_port(self): + params = {'port': ['1001', '1002', '1003']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_virtual_machine(self): + vms = VirtualMachine.objects.all()[:2] + params = {'virtual_machine_id': [vms[0].pk, vms[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_machine': [vms[0].name, vms[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 2cc1a0ea8..26df90c93 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -333,7 +333,10 @@ class AggregateView(PermissionRequiredMixin, View): ).annotate_depth( limit=0 ) - child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) + + # Add available prefixes to the table if requested + if request.GET.get('show_available', 'true') == 'true': + child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -356,6 +359,7 @@ class AggregateView(PermissionRequiredMixin, View): 'aggregate': aggregate, 'prefix_table': prefix_table, 'permissions': permissions, + 'show_available': request.GET.get('show_available', 'true') == 'true', }) @@ -511,8 +515,8 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'site', 'vlan', 'role', ).annotate_depth(limit=0) - # Annotate available prefixes - if child_prefixes: + # Add available prefixes to the table if requested + if child_prefixes and request.GET.get('show_available', 'true') == 'true': child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -539,6 +543,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'prefixes', + 'show_available': request.GET.get('show_available', 'true') == 'true', }) @@ -553,7 +558,10 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): ipaddresses = prefix.get_child_ips().prefetch_related( 'vrf', 'interface__device', 'primary_ip4_for', 'primary_ip6_for' ) - ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) + + # Add available IP addresses to the table if requested + if request.GET.get('show_available', 'true') == 'true': + ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) ip_table = tables.IPAddressTable(ipaddresses) if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): @@ -579,6 +587,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'ip-addresses', + 'show_available': request.GET.get('show_available', 'true') == 'true', }) diff --git a/netbox/secrets/filters.py b/netbox/secrets/filters.py index bdc643e71..2998b9c18 100644 --- a/netbox/secrets/filters.py +++ b/netbox/secrets/filters.py @@ -7,6 +7,12 @@ from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilte from .models import Secret, SecretRole +__all__ = ( + 'SecretFilter', + 'SecretRoleFilter', +) + + class SecretRoleFilter(NameSlugSearchFilterSet): class Meta: diff --git a/netbox/secrets/tests/test_filters.py b/netbox/secrets/tests/test_filters.py new file mode 100644 index 000000000..c378147ff --- /dev/null +++ b/netbox/secrets/tests/test_filters.py @@ -0,0 +1,92 @@ +from django.test import TestCase + +from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site +from secrets.filters import * +from secrets.models import Secret, SecretRole + + +class SecretRoleTestCase(TestCase): + queryset = SecretRole.objects.all() + filterset = SecretRoleFilter + + @classmethod + def setUpTestData(cls): + + roles = ( + SecretRole(name='Secret Role 1', slug='secret-role-1'), + SecretRole(name='Secret Role 2', slug='secret-role-2'), + SecretRole(name='Secret Role 3', slug='secret-role-3'), + ) + SecretRole.objects.bulk_create(roles) + + def test_id(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id': [str(id) for id in id_list]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Secret Role 1', 'Secret Role 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_slug(self): + params = {'slug': ['secret-role-1', 'secret-role-2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class SecretTestCase(TestCase): + queryset = Secret.objects.all() + filterset = SecretFilter + + @classmethod + def setUpTestData(cls): + + site = Site.objects.create(name='Site 1', slug='site-1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + + devices = ( + Device(device_type=device_type, name='Device 1', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 2', site=site, device_role=device_role), + Device(device_type=device_type, name='Device 3', site=site, device_role=device_role), + ) + Device.objects.bulk_create(devices) + + roles = ( + SecretRole(name='Secret Role 1', slug='secret-role-1'), + SecretRole(name='Secret Role 2', slug='secret-role-2'), + SecretRole(name='Secret Role 3', slug='secret-role-3'), + ) + SecretRole.objects.bulk_create(roles) + + secrets = ( + Secret(device=devices[0], role=roles[0], name='Secret 1', plaintext='SECRET DATA'), + Secret(device=devices[1], role=roles[1], name='Secret 2', plaintext='SECRET DATA'), + Secret(device=devices[2], role=roles[2], name='Secret 3', plaintext='SECRET DATA'), + ) + # Must call save() to encrypt Secrets + for s in secrets: + s.save() + + def test_name(self): + params = {'name': ['Secret 1', 'Secret 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_id__in(self): + id_list = self.queryset.values_list('id', flat=True)[:2] + params = {'id__in': ','.join([str(id) for id in id_list])} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_role(self): + roles = SecretRole.objects.all()[:2] + params = {'role_id': [roles[0].pk, roles[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'role': [roles[0].slug, roles[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index daa7b5107..d2dfe8888 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -40,6 +40,7 @@