diff --git a/.gitignore b/.gitignore
index 485b46d59..95e4ff702 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
/netbox/static
/venv/
/*.sh
+local_requirements.txt
!upgrade.sh
fabfile.py
gunicorn.py
diff --git a/docs/additional-features/custom-links.md b/docs/additional-features/custom-links.md
index 7c96eba8b..56d67a7be 100644
--- a/docs/additional-features/custom-links.md
+++ b/docs/additional-features/custom-links.md
@@ -24,7 +24,7 @@ Only links which render with non-empty text are included on the page. You can em
For example, if you only want to display a link for active devices, you could set the link text to
```
-{% if obj.status == 1 %}View NMS{% endif %}
+{% if obj.status == 'active' %}View NMS{% endif %}
```
The link will not appear when viewing a device with any status other than "active."
diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md
index 5ca86217a..f9b02db8d 100644
--- a/docs/release-notes/version-2.8.md
+++ b/docs/release-notes/version-2.8.md
@@ -1,5 +1,19 @@
# NetBox v2.8
+## v2.8.6 (FUTURE)
+
+### Enhancements
+
+* [#4698](https://github.com/netbox-community/netbox/issues/4698) - Improve display of template code for object in admin UI
+
+### Bug Fixes
+
+* [#4702](https://github.com/netbox-community/netbox/issues/4702) - Catch IntegrityError exception when adding a non-unique secret
+* [#4707](https://github.com/netbox-community/netbox/issues/4707) - Fix `prefix_count` population on VLAN API serializer
+* [#4725](https://github.com/netbox-community/netbox/issues/4725) - Fix "brief" rendering of various REST API endpoints
+
+---
+
## v2.8.5 (2020-05-26)
**Note:** The minimum required version of PostgreSQL is now 9.6.
diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py
index b5f8758e7..71db7234d 100644
--- a/netbox/circuits/tests/test_api.py
+++ b/netbox/circuits/tests/test_api.py
@@ -1,443 +1,188 @@
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
-from rest_framework import status
from circuits.choices import *
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
from dcim.models import Site
from extras.models import Graph
-from utilities.testing import APITestCase
+from utilities.testing import APITestCase, APIViewTestCases
class AppTest(APITestCase):
def test_root(self):
-
url = reverse('circuits-api:api-root')
response = self.client.get('{}?format=api'.format(url), **self.header)
self.assertEqual(response.status_code, 200)
-class ProviderTest(APITestCase):
+class ProviderTest(APIViewTestCases.APIViewTestCase):
+ model = Provider
+ brief_fields = ['circuit_count', 'id', 'name', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Provider 4',
+ 'slug': 'provider-4',
+ },
+ {
+ 'name': 'Provider 5',
+ 'slug': 'provider-5',
+ },
+ {
+ 'name': 'Provider 6',
+ 'slug': 'provider-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.provider1 = Provider.objects.create(name='Test Provider 1', slug='test-provider-1')
- self.provider2 = Provider.objects.create(name='Test Provider 2', slug='test-provider-2')
- self.provider3 = Provider.objects.create(name='Test Provider 3', slug='test-provider-3')
-
- def test_get_provider(self):
-
- url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.provider1.name)
+ providers = (
+ Provider(name='Provider 1', slug='provider-1'),
+ Provider(name='Provider 2', slug='provider-2'),
+ Provider(name='Provider 3', slug='provider-3'),
+ )
+ Provider.objects.bulk_create(providers)
def test_get_provider_graphs(self):
+ """
+ Test retrieval of Graphs assigned to Providers.
+ """
+ provider = self.model.objects.first()
+ ct = ContentType.objects.get(app_label='circuits', model='provider')
+ graphs = (
+ Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=1'),
+ Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=2'),
+ Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=3'),
+ )
+ Graph.objects.bulk_create(graphs)
- provider_ct = ContentType.objects.get(app_label='circuits', model='provider')
- self.graph1 = Graph.objects.create(
- type=provider_ct,
- name='Test Graph 1',
- source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=1'
- )
- self.graph2 = Graph.objects.create(
- type=provider_ct,
- name='Test Graph 2',
- source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=2'
- )
- self.graph3 = Graph.objects.create(
- type=provider_ct,
- name='Test Graph 3',
- source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=3'
- )
-
- url = reverse('circuits-api:provider-graphs', kwargs={'pk': self.provider1.pk})
+ url = reverse('circuits-api:provider-graphs', kwargs={'pk': provider.pk})
response = self.client.get(url, **self.header)
self.assertEqual(len(response.data), 3)
- self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?provider=test-provider-1&foo=1')
+ self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?provider=provider-1&foo=1')
- def test_list_providers(self):
- url = reverse('circuits-api:provider-list')
- response = self.client.get(url, **self.header)
+class CircuitTypeTest(APIViewTestCases.APIViewTestCase):
+ model = CircuitType
+ brief_fields = ['circuit_count', 'id', 'name', 'slug', 'url']
+ create_data = (
+ {
+ 'name': 'Circuit Type 4',
+ 'slug': 'circuit-type-4',
+ },
+ {
+ 'name': 'Circuit Type 5',
+ 'slug': 'circuit-type-5',
+ },
+ {
+ 'name': 'Circuit Type 6',
+ 'slug': 'circuit-type-6',
+ },
+ )
- self.assertEqual(response.data['count'], 3)
+ @classmethod
+ def setUpTestData(cls):
- def test_list_providers_brief(self):
-
- url = reverse('circuits-api:provider-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['circuit_count', 'id', 'name', 'slug', 'url']
+ circuit_types = (
+ 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'),
)
+ CircuitType.objects.bulk_create(circuit_types)
- def test_create_provider(self):
- data = {
- 'name': 'Test Provider 4',
- 'slug': 'test-provider-4',
- }
+class CircuitTest(APIViewTestCases.APIViewTestCase):
+ model = Circuit
+ brief_fields = ['cid', 'id', 'url']
- url = reverse('circuits-api:provider-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Provider.objects.count(), 4)
- provider4 = Provider.objects.get(pk=response.data['id'])
- self.assertEqual(provider4.name, data['name'])
- self.assertEqual(provider4.slug, data['slug'])
+ providers = (
+ Provider(name='Provider 1', slug='provider-1'),
+ Provider(name='Provider 2', slug='provider-2'),
+ )
+ Provider.objects.bulk_create(providers)
- def test_create_provider_bulk(self):
+ circuit_types = (
+ CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
+ CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
+ )
+ CircuitType.objects.bulk_create(circuit_types)
- data = [
+ circuits = (
+ Circuit(cid='Circuit 1', provider=providers[0], type=circuit_types[0]),
+ Circuit(cid='Circuit 2', provider=providers[0], type=circuit_types[0]),
+ Circuit(cid='Circuit 3', provider=providers[0], type=circuit_types[0]),
+ )
+ Circuit.objects.bulk_create(circuits)
+
+ cls.create_data = [
{
- 'name': 'Test Provider 4',
- 'slug': 'test-provider-4',
+ 'cid': 'Circuit 4',
+ 'provider': providers[1].pk,
+ 'type': circuit_types[1].pk,
},
{
- 'name': 'Test Provider 5',
- 'slug': 'test-provider-5',
+ 'cid': 'Circuit 5',
+ 'provider': providers[1].pk,
+ 'type': circuit_types[1].pk,
},
{
- 'name': 'Test Provider 6',
- 'slug': 'test-provider-6',
+ 'cid': 'Circuit 6',
+ 'provider': providers[1].pk,
+ 'type': circuit_types[1].pk,
},
]
- url = reverse('circuits-api:provider-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Provider.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class CircuitTerminationTest(APIViewTestCases.APIViewTestCase):
+ model = CircuitTermination
+ brief_fields = ['circuit', 'id', 'term_side', 'url']
- def test_update_provider(self):
+ @classmethod
+ def setUpTestData(cls):
+ SIDE_A = CircuitTerminationSideChoices.SIDE_A
+ SIDE_Z = CircuitTerminationSideChoices.SIDE_Z
- data = {
- 'name': 'Test Provider X',
- 'slug': 'test-provider-x',
- }
-
- url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Provider.objects.count(), 3)
- provider1 = Provider.objects.get(pk=response.data['id'])
- self.assertEqual(provider1.name, data['name'])
- self.assertEqual(provider1.slug, data['slug'])
-
- def test_delete_provider(self):
-
- url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Provider.objects.count(), 2)
-
-
-class CircuitTypeTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.circuittype1 = CircuitType.objects.create(name='Test Circuit Type 1', slug='test-circuit-type-1')
- self.circuittype2 = CircuitType.objects.create(name='Test Circuit Type 2', slug='test-circuit-type-2')
- self.circuittype3 = CircuitType.objects.create(name='Test Circuit Type 3', slug='test-circuit-type-3')
-
- def test_get_circuittype(self):
-
- url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.circuittype1.name)
-
- def test_list_circuittypes(self):
-
- url = reverse('circuits-api:circuittype-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_circuittypes_brief(self):
-
- url = reverse('circuits-api:circuittype-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['circuit_count', 'id', 'name', 'slug', 'url']
+ sites = (
+ Site(name='Site 1', slug='site-1'),
+ Site(name='Site 2', slug='site-2'),
)
+ Site.objects.bulk_create(sites)
- def test_create_circuittype(self):
+ provider = Provider.objects.create(name='Provider 1', slug='provider-1')
+ circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
- data = {
- 'name': 'Test Circuit Type 4',
- 'slug': 'test-circuit-type-4',
- }
-
- url = reverse('circuits-api:circuittype-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(CircuitType.objects.count(), 4)
- circuittype4 = CircuitType.objects.get(pk=response.data['id'])
- self.assertEqual(circuittype4.name, data['name'])
- self.assertEqual(circuittype4.slug, data['slug'])
-
- def test_update_circuittype(self):
-
- data = {
- 'name': 'Test Circuit Type X',
- 'slug': 'test-circuit-type-x',
- }
-
- url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(CircuitType.objects.count(), 3)
- circuittype1 = CircuitType.objects.get(pk=response.data['id'])
- self.assertEqual(circuittype1.name, data['name'])
- self.assertEqual(circuittype1.slug, data['slug'])
-
- def test_delete_circuittype(self):
-
- url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(CircuitType.objects.count(), 2)
-
-
-class CircuitTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.provider1 = Provider.objects.create(name='Test Provider 1', slug='test-provider-1')
- self.provider2 = Provider.objects.create(name='Test Provider 2', slug='test-provider-2')
- self.circuittype1 = CircuitType.objects.create(name='Test Circuit Type 1', slug='test-circuit-type-1')
- self.circuittype2 = CircuitType.objects.create(name='Test Circuit Type 2', slug='test-circuit-type-2')
- self.circuit1 = Circuit.objects.create(cid='TEST0001', provider=self.provider1, type=self.circuittype1)
- self.circuit2 = Circuit.objects.create(cid='TEST0002', provider=self.provider1, type=self.circuittype1)
- self.circuit3 = Circuit.objects.create(cid='TEST0003', provider=self.provider1, type=self.circuittype1)
-
- def test_get_circuit(self):
-
- url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['cid'], self.circuit1.cid)
-
- def test_list_circuits(self):
-
- url = reverse('circuits-api:circuit-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_circuits_brief(self):
-
- url = reverse('circuits-api:circuit-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cid', 'id', 'url']
+ circuits = (
+ Circuit(cid='Circuit 1', provider=provider, type=circuit_type),
+ Circuit(cid='Circuit 2', provider=provider, type=circuit_type),
+ Circuit(cid='Circuit 3', provider=provider, type=circuit_type),
)
+ Circuit.objects.bulk_create(circuits)
- def test_create_circuit(self):
+ circuit_terminations = (
+ CircuitTermination(circuit=circuits[0], site=sites[0], port_speed=100000, term_side=SIDE_A),
+ CircuitTermination(circuit=circuits[0], site=sites[1], port_speed=100000, term_side=SIDE_Z),
+ CircuitTermination(circuit=circuits[1], site=sites[0], port_speed=100000, term_side=SIDE_A),
+ CircuitTermination(circuit=circuits[1], site=sites[1], port_speed=100000, term_side=SIDE_Z),
+ )
+ CircuitTermination.objects.bulk_create(circuit_terminations)
- data = {
- 'cid': 'TEST0004',
- 'provider': self.provider1.pk,
- 'type': self.circuittype1.pk,
- 'status': CircuitStatusChoices.STATUS_ACTIVE,
- }
-
- url = reverse('circuits-api:circuit-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Circuit.objects.count(), 4)
- circuit4 = Circuit.objects.get(pk=response.data['id'])
- self.assertEqual(circuit4.cid, data['cid'])
- self.assertEqual(circuit4.provider_id, data['provider'])
- self.assertEqual(circuit4.type_id, data['type'])
-
- def test_create_circuit_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'cid': 'TEST0004',
- 'provider': self.provider1.pk,
- 'type': self.circuittype1.pk,
- 'status': CircuitStatusChoices.STATUS_ACTIVE,
+ 'circuit': circuits[2].pk,
+ 'term_side': SIDE_A,
+ 'site': sites[1].pk,
+ 'port_speed': 200000,
},
{
- 'cid': 'TEST0005',
- 'provider': self.provider1.pk,
- 'type': self.circuittype1.pk,
- 'status': CircuitStatusChoices.STATUS_ACTIVE,
- },
- {
- 'cid': 'TEST0006',
- 'provider': self.provider1.pk,
- 'type': self.circuittype1.pk,
- 'status': CircuitStatusChoices.STATUS_ACTIVE,
+ 'circuit': circuits[2].pk,
+ 'term_side': SIDE_Z,
+ 'site': sites[1].pk,
+ 'port_speed': 200000,
},
]
-
- url = reverse('circuits-api:circuit-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Circuit.objects.count(), 6)
- self.assertEqual(response.data[0]['cid'], data[0]['cid'])
- self.assertEqual(response.data[1]['cid'], data[1]['cid'])
- self.assertEqual(response.data[2]['cid'], data[2]['cid'])
-
- def test_update_circuit(self):
-
- data = {
- 'cid': 'TEST000X',
- 'provider': self.provider2.pk,
- 'type': self.circuittype2.pk,
- }
-
- url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Circuit.objects.count(), 3)
- circuit1 = Circuit.objects.get(pk=response.data['id'])
- self.assertEqual(circuit1.cid, data['cid'])
- self.assertEqual(circuit1.provider_id, data['provider'])
- self.assertEqual(circuit1.type_id, data['type'])
-
- def test_delete_circuit(self):
-
- url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Circuit.objects.count(), 2)
-
-
-class CircuitTerminationTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2')
- provider = Provider.objects.create(name='Test Provider', slug='test-provider')
- circuittype = CircuitType.objects.create(name='Test Circuit Type', slug='test-circuit-type')
- self.circuit1 = Circuit.objects.create(cid='TEST0001', provider=provider, type=circuittype)
- self.circuit2 = Circuit.objects.create(cid='TEST0002', provider=provider, type=circuittype)
- self.circuit3 = Circuit.objects.create(cid='TEST0003', provider=provider, type=circuittype)
- self.circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit1,
- term_side=CircuitTerminationSideChoices.SIDE_A,
- site=self.site1,
- port_speed=1000000
- )
- self.circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit1,
- term_side=CircuitTerminationSideChoices.SIDE_Z,
- site=self.site2,
- port_speed=1000000
- )
- self.circuittermination3 = CircuitTermination.objects.create(
- circuit=self.circuit2,
- term_side=CircuitTerminationSideChoices.SIDE_A,
- site=self.site1,
- port_speed=1000000
- )
- self.circuittermination4 = CircuitTermination.objects.create(
- circuit=self.circuit2,
- term_side=CircuitTerminationSideChoices.SIDE_Z,
- site=self.site2,
- port_speed=1000000
- )
-
- def test_get_circuittermination(self):
-
- url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': self.circuittermination1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['id'], self.circuittermination1.pk)
-
- def test_list_circuitterminations(self):
-
- url = reverse('circuits-api:circuittermination-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 4)
-
- def test_create_circuittermination(self):
-
- data = {
- 'circuit': self.circuit3.pk,
- 'term_side': CircuitTerminationSideChoices.SIDE_A,
- 'site': self.site1.pk,
- 'port_speed': 1000000,
- }
-
- url = reverse('circuits-api:circuittermination-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(CircuitTermination.objects.count(), 5)
- circuittermination4 = CircuitTermination.objects.get(pk=response.data['id'])
- self.assertEqual(circuittermination4.circuit_id, data['circuit'])
- self.assertEqual(circuittermination4.term_side, data['term_side'])
- self.assertEqual(circuittermination4.site_id, data['site'])
- self.assertEqual(circuittermination4.port_speed, data['port_speed'])
-
- def test_update_circuittermination(self):
-
- circuittermination5 = CircuitTermination.objects.create(
- circuit=self.circuit3,
- term_side=CircuitTerminationSideChoices.SIDE_A,
- site=self.site1,
- port_speed=1000000
- )
-
- data = {
- 'circuit': self.circuit3.pk,
- 'term_side': CircuitTerminationSideChoices.SIDE_Z,
- 'site': self.site2.pk,
- 'port_speed': 1000000,
- }
-
- url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': circuittermination5.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(CircuitTermination.objects.count(), 5)
- circuittermination1 = CircuitTermination.objects.get(pk=response.data['id'])
- self.assertEqual(circuittermination1.term_side, data['term_side'])
- self.assertEqual(circuittermination1.site_id, data['site'])
- self.assertEqual(circuittermination1.port_speed, data['port_speed'])
-
- def test_delete_circuittermination(self):
-
- url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': self.circuittermination1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(CircuitTermination.objects.count(), 3)
diff --git a/netbox/dcim/api/nested_serializers.py b/netbox/dcim/api/nested_serializers.py
index bb2d61faa..83fcd7a2a 100644
--- a/netbox/dcim/api/nested_serializers.py
+++ b/netbox/dcim/api/nested_serializers.py
@@ -1,32 +1,35 @@
from rest_framework import serializers
from dcim.constants import CONNECTION_STATUS_CHOICES
-from dcim.models import (
- Cable, ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceType, DeviceRole, FrontPort, FrontPortTemplate,
- Interface, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerPanel, PowerPort, PowerPortTemplate, Rack,
- RackGroup, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis,
-)
+from dcim import models
from utilities.api import ChoiceField, WritableNestedSerializer
__all__ = [
'NestedCableSerializer',
'NestedConsolePortSerializer',
+ 'NestedConsolePortTemplateSerializer',
'NestedConsoleServerPortSerializer',
+ 'NestedConsoleServerPortTemplateSerializer',
'NestedDeviceBaySerializer',
+ 'NestedDeviceBayTemplateSerializer',
'NestedDeviceRoleSerializer',
'NestedDeviceSerializer',
'NestedDeviceTypeSerializer',
'NestedFrontPortSerializer',
'NestedFrontPortTemplateSerializer',
'NestedInterfaceSerializer',
+ 'NestedInterfaceTemplateSerializer',
+ 'NestedInventoryItemSerializer',
'NestedManufacturerSerializer',
'NestedPlatformSerializer',
'NestedPowerFeedSerializer',
'NestedPowerOutletSerializer',
+ 'NestedPowerOutletTemplateSerializer',
'NestedPowerPanelSerializer',
'NestedPowerPortSerializer',
'NestedPowerPortTemplateSerializer',
'NestedRackGroupSerializer',
+ 'NestedRackReservationSerializer',
'NestedRackRoleSerializer',
'NestedRackSerializer',
'NestedRearPortSerializer',
@@ -46,7 +49,7 @@ class NestedRegionSerializer(WritableNestedSerializer):
site_count = serializers.IntegerField(read_only=True)
class Meta:
- model = Region
+ model = models.Region
fields = ['id', 'url', 'name', 'slug', 'site_count']
@@ -54,7 +57,7 @@ class NestedSiteSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail')
class Meta:
- model = Site
+ model = models.Site
fields = ['id', 'url', 'name', 'slug']
@@ -67,7 +70,7 @@ class NestedRackGroupSerializer(WritableNestedSerializer):
rack_count = serializers.IntegerField(read_only=True)
class Meta:
- model = RackGroup
+ model = models.RackGroup
fields = ['id', 'url', 'name', 'slug', 'rack_count']
@@ -76,7 +79,7 @@ class NestedRackRoleSerializer(WritableNestedSerializer):
rack_count = serializers.IntegerField(read_only=True)
class Meta:
- model = RackRole
+ model = models.RackRole
fields = ['id', 'url', 'name', 'slug', 'rack_count']
@@ -85,10 +88,22 @@ class NestedRackSerializer(WritableNestedSerializer):
device_count = serializers.IntegerField(read_only=True)
class Meta:
- model = Rack
+ model = models.Rack
fields = ['id', 'url', 'name', 'display_name', 'device_count']
+class NestedRackReservationSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackreservation-detail')
+ user = serializers.SerializerMethodField(read_only=True)
+
+ class Meta:
+ model = models.RackReservation
+ fields = ['id', 'url', 'user', 'units']
+
+ def get_user(self, obj):
+ return obj.user.username
+
+
#
# Device types
#
@@ -98,7 +113,7 @@ class NestedManufacturerSerializer(WritableNestedSerializer):
devicetype_count = serializers.IntegerField(read_only=True)
class Meta:
- model = Manufacturer
+ model = models.Manufacturer
fields = ['id', 'url', 'name', 'slug', 'devicetype_count']
@@ -108,15 +123,47 @@ class NestedDeviceTypeSerializer(WritableNestedSerializer):
device_count = serializers.IntegerField(read_only=True)
class Meta:
- model = DeviceType
+ model = models.DeviceType
fields = ['id', 'url', 'manufacturer', 'model', 'slug', 'display_name', 'device_count']
+class NestedConsolePortTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleporttemplate-detail')
+
+ class Meta:
+ model = models.ConsolePortTemplate
+ fields = ['id', 'url', 'name']
+
+
+class NestedConsoleServerPortTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverporttemplate-detail')
+
+ class Meta:
+ model = models.ConsoleServerPortTemplate
+ fields = ['id', 'url', 'name']
+
+
class NestedPowerPortTemplateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerporttemplate-detail')
class Meta:
- model = PowerPortTemplate
+ model = models.PowerPortTemplate
+ fields = ['id', 'url', 'name']
+
+
+class NestedPowerOutletTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlettemplate-detail')
+
+ class Meta:
+ model = models.PowerOutletTemplate
+ fields = ['id', 'url', 'name']
+
+
+class NestedInterfaceTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfacetemplate-detail')
+
+ class Meta:
+ model = models.InterfaceTemplate
fields = ['id', 'url', 'name']
@@ -124,7 +171,7 @@ class NestedRearPortTemplateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearporttemplate-detail')
class Meta:
- model = RearPortTemplate
+ model = models.RearPortTemplate
fields = ['id', 'url', 'name']
@@ -132,7 +179,15 @@ class NestedFrontPortTemplateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontporttemplate-detail')
class Meta:
- model = FrontPortTemplate
+ model = models.FrontPortTemplate
+ fields = ['id', 'url', 'name']
+
+
+class NestedDeviceBayTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebaytemplate-detail')
+
+ class Meta:
+ model = models.DeviceBayTemplate
fields = ['id', 'url', 'name']
@@ -146,7 +201,7 @@ class NestedDeviceRoleSerializer(WritableNestedSerializer):
virtualmachine_count = serializers.IntegerField(read_only=True)
class Meta:
- model = DeviceRole
+ model = models.DeviceRole
fields = ['id', 'url', 'name', 'slug', 'device_count', 'virtualmachine_count']
@@ -156,7 +211,7 @@ class NestedPlatformSerializer(WritableNestedSerializer):
virtualmachine_count = serializers.IntegerField(read_only=True)
class Meta:
- model = Platform
+ model = models.Platform
fields = ['id', 'url', 'name', 'slug', 'device_count', 'virtualmachine_count']
@@ -164,7 +219,7 @@ class NestedDeviceSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
class Meta:
- model = Device
+ model = models.Device
fields = ['id', 'url', 'name', 'display_name']
@@ -174,7 +229,7 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer):
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
class Meta:
- model = ConsoleServerPort
+ model = models.ConsoleServerPort
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status']
@@ -184,7 +239,7 @@ class NestedConsolePortSerializer(WritableNestedSerializer):
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
class Meta:
- model = ConsolePort
+ model = models.ConsolePort
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status']
@@ -194,7 +249,7 @@ class NestedPowerOutletSerializer(WritableNestedSerializer):
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
class Meta:
- model = PowerOutlet
+ model = models.PowerOutlet
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status']
@@ -204,7 +259,7 @@ class NestedPowerPortSerializer(WritableNestedSerializer):
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
class Meta:
- model = PowerPort
+ model = models.PowerPort
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status']
@@ -214,7 +269,7 @@ class NestedInterfaceSerializer(WritableNestedSerializer):
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
class Meta:
- model = Interface
+ model = models.Interface
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status']
@@ -223,7 +278,7 @@ class NestedRearPortSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail')
class Meta:
- model = RearPort
+ model = models.RearPort
fields = ['id', 'url', 'device', 'name', 'cable']
@@ -232,7 +287,7 @@ class NestedFrontPortSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail')
class Meta:
- model = FrontPort
+ model = models.FrontPort
fields = ['id', 'url', 'device', 'name', 'cable']
@@ -241,7 +296,16 @@ class NestedDeviceBaySerializer(WritableNestedSerializer):
device = NestedDeviceSerializer(read_only=True)
class Meta:
- model = DeviceBay
+ model = models.DeviceBay
+ fields = ['id', 'url', 'device', 'name']
+
+
+class NestedInventoryItemSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail')
+ device = NestedDeviceSerializer(read_only=True)
+
+ class Meta:
+ model = models.InventoryItem
fields = ['id', 'url', 'device', 'name']
@@ -253,7 +317,7 @@ class NestedCableSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
class Meta:
- model = Cable
+ model = models.Cable
fields = ['id', 'url', 'label']
@@ -267,7 +331,7 @@ class NestedVirtualChassisSerializer(WritableNestedSerializer):
member_count = serializers.IntegerField(read_only=True)
class Meta:
- model = VirtualChassis
+ model = models.VirtualChassis
fields = ['id', 'url', 'master', 'member_count']
@@ -280,7 +344,7 @@ class NestedPowerPanelSerializer(WritableNestedSerializer):
powerfeed_count = serializers.IntegerField(read_only=True)
class Meta:
- model = PowerPanel
+ model = models.PowerPanel
fields = ['id', 'url', 'name', 'powerfeed_count']
@@ -288,5 +352,5 @@ class NestedPowerFeedSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail')
class Meta:
- model = PowerFeed
+ model = models.PowerFeed
fields = ['id', 'url', 'name']
diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py
index 4d18509a9..73220d1f0 100644
--- a/netbox/dcim/models/__init__.py
+++ b/netbox/dcim/models/__init__.py
@@ -2140,9 +2140,9 @@ class Cable(ChangeLoggedModel):
"""
instance = super().from_db(db, field_names, values)
- instance._orig_termination_a_type = instance.termination_a_type
+ instance._orig_termination_a_type_id = instance.termination_a_type_id
instance._orig_termination_a_id = instance.termination_a_id
- instance._orig_termination_b_type = instance.termination_b_type
+ instance._orig_termination_b_type_id = instance.termination_b_type_id
instance._orig_termination_b_id = instance.termination_b_id
return instance
@@ -2179,14 +2179,14 @@ class Cable(ChangeLoggedModel):
if self.pk:
err_msg = 'Cable termination points may not be modified. Delete and recreate the cable instead.'
if (
- self.termination_a_type != self._orig_termination_a_type or
+ self.termination_a_type_id != self._orig_termination_a_type_id or
self.termination_a_id != self._orig_termination_a_id
):
raise ValidationError({
'termination_a': err_msg
})
if (
- self.termination_b_type != self._orig_termination_b_type or
+ self.termination_b_type_id != self._orig_termination_b_type_id or
self.termination_b_id != self._orig_termination_b_id
):
raise ValidationError({
diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py
index d45d972f8..6c6b75c7f 100644
--- a/netbox/dcim/tests/test_api.py
+++ b/netbox/dcim/tests/test_api.py
@@ -1,6 +1,6 @@
+from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
-from netaddr import IPNetwork
from rest_framework import status
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
@@ -12,9 +12,9 @@ from dcim.models import (
InventoryItem, Platform, PowerFeed, PowerPort, PowerPortTemplate, PowerOutlet, PowerOutletTemplate, PowerPanel,
Rack, RackGroup, RackReservation, RackRole, RearPort, Region, Site, VirtualChassis,
)
-from ipam.models import IPAddress, VLAN
+from ipam.models import VLAN
from extras.models import Graph
-from utilities.testing import APITestCase
+from utilities.testing import APITestCase, APIViewTestCases
from virtualization.models import Cluster, ClusterType
@@ -28,2007 +28,796 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class RegionTest(APITestCase):
+class RegionTest(APIViewTestCases.APIViewTestCase):
+ model = Region
+ brief_fields = ['id', 'name', 'site_count', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Region 4',
+ 'slug': 'region-4',
+ },
+ {
+ 'name': 'Region 5',
+ 'slug': 'region-5',
+ },
+ {
+ 'name': 'Region 6',
+ 'slug': 'region-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
+ Region.objects.create(name='Region 1', slug='region-1')
+ Region.objects.create(name='Region 2', slug='region-2')
+ Region.objects.create(name='Region 3', slug='region-3')
- self.region1 = Region.objects.create(name='Test Region 1', slug='test-region-1')
- self.region2 = Region.objects.create(name='Test Region 2', slug='test-region-2')
- self.region3 = Region.objects.create(name='Test Region 3', slug='test-region-3')
- def test_get_region(self):
+class SiteTest(APIViewTestCases.APIViewTestCase):
+ model = Site
+ brief_fields = ['id', 'name', 'slug', 'url']
- url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk})
- response = self.client.get(url, **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertEqual(response.data['name'], self.region1.name)
-
- def test_list_regions(self):
-
- url = reverse('dcim-api:region-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_regions_brief(self):
-
- url = reverse('dcim-api:region-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'site_count', 'slug', 'url']
+ regions = (
+ Region.objects.create(name='Test Region 1', slug='test-region-1'),
+ Region.objects.create(name='Test Region 2', slug='test-region-2'),
)
- def test_create_region(self):
+ sites = (
+ Site(region=regions[0], name='Site 1', slug='site-1'),
+ Site(region=regions[0], name='Site 2', slug='site-2'),
+ Site(region=regions[0], name='Site 3', slug='site-3'),
+ )
+ Site.objects.bulk_create(sites)
- data = {
- 'name': 'Test Region 4',
- 'slug': 'test-region-4',
- }
-
- url = reverse('dcim-api:region-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Region.objects.count(), 4)
- region4 = Region.objects.get(pk=response.data['id'])
- self.assertEqual(region4.name, data['name'])
- self.assertEqual(region4.slug, data['slug'])
-
- def test_create_region_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Region 4',
- 'slug': 'test-region-4',
+ 'name': 'Site 4',
+ 'slug': 'site-4',
+ 'region': regions[1].pk,
+ 'status': SiteStatusChoices.STATUS_ACTIVE,
},
{
- 'name': 'Test Region 5',
- 'slug': 'test-region-5',
+ 'name': 'Site 5',
+ 'slug': 'site-5',
+ 'region': regions[1].pk,
+ 'status': SiteStatusChoices.STATUS_ACTIVE,
},
{
- 'name': 'Test Region 6',
- 'slug': 'test-region-6',
+ 'name': 'Site 6',
+ 'slug': 'site-6',
+ 'region': regions[1].pk,
+ 'status': SiteStatusChoices.STATUS_ACTIVE,
},
]
- url = reverse('dcim-api:region-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Region.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_region(self):
-
- data = {
- 'name': 'Test Region X',
- 'slug': 'test-region-x',
- }
-
- url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Region.objects.count(), 3)
- region1 = Region.objects.get(pk=response.data['id'])
- self.assertEqual(region1.name, data['name'])
- self.assertEqual(region1.slug, data['slug'])
-
- def test_delete_region(self):
-
- url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Region.objects.count(), 2)
-
-
-class SiteTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.region1 = Region.objects.create(name='Test Region 1', slug='test-region-1')
- self.region2 = Region.objects.create(name='Test Region 2', slug='test-region-2')
- self.site1 = Site.objects.create(region=self.region1, name='Test Site 1', slug='test-site-1')
- self.site2 = Site.objects.create(region=self.region1, name='Test Site 2', slug='test-site-2')
- self.site3 = Site.objects.create(region=self.region1, name='Test Site 3', slug='test-site-3')
-
- def test_get_site(self):
-
- url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.site1.name)
-
def test_get_site_graphs(self):
+ """
+ Test retrieval of Graphs assigned to Sites.
+ """
+ ct = ContentType.objects.get_for_model(Site)
+ graphs = (
+ Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=1'),
+ Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=2'),
+ Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=3'),
+ )
+ Graph.objects.bulk_create(graphs)
- site_ct = ContentType.objects.get_for_model(Site)
- self.graph1 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 1',
- source='http://example.com/graphs.py?site={{ obj.slug }}&foo=1'
- )
- self.graph2 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 2',
- source='http://example.com/graphs.py?site={{ obj.slug }}&foo=2'
- )
- self.graph3 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 3',
- source='http://example.com/graphs.py?site={{ obj.slug }}&foo=3'
- )
-
- url = reverse('dcim-api:site-graphs', kwargs={'pk': self.site1.pk})
+ url = reverse('dcim-api:site-graphs', kwargs={'pk': Site.objects.first().pk})
response = self.client.get(url, **self.header)
self.assertEqual(len(response.data), 3)
- self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?site=test-site-1&foo=1')
+ self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?site=site-1&foo=1')
- def test_list_sites(self):
- url = reverse('dcim-api:site-list')
- response = self.client.get(url, **self.header)
+class RackGroupTest(APIViewTestCases.APIViewTestCase):
+ model = RackGroup
+ brief_fields = ['id', 'name', 'rack_count', 'slug', 'url']
- self.assertEqual(response.data['count'], 3)
+ @classmethod
+ def setUpTestData(cls):
- def test_list_sites_brief(self):
+ sites = (
+ Site(name='Site 1', slug='site-1'),
+ Site(name='Site 2', slug='site-2'),
+ )
+ Site.objects.bulk_create(sites)
- url = reverse('dcim-api:site-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'slug', 'url']
+ parent_rack_groups = (
+ RackGroup.objects.create(site=sites[0], name='Parent Rack Group 1', slug='parent-rack-group-1'),
+ RackGroup.objects.create(site=sites[1], name='Parent Rack Group 2', slug='parent-rack-group-2'),
)
- def test_create_site(self):
+ RackGroup.objects.create(site=sites[0], name='Rack Group 1', slug='rack-group-1', parent=parent_rack_groups[0])
+ RackGroup.objects.create(site=sites[0], name='Rack Group 2', slug='rack-group-2', parent=parent_rack_groups[0])
+ RackGroup.objects.create(site=sites[0], name='Rack Group 3', slug='rack-group-3', parent=parent_rack_groups[0])
- data = {
- 'name': 'Test Site 4',
- 'slug': 'test-site-4',
- 'region': self.region1.pk,
- 'status': SiteStatusChoices.STATUS_ACTIVE,
- }
-
- url = reverse('dcim-api:site-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Site.objects.count(), 4)
- site4 = Site.objects.get(pk=response.data['id'])
- self.assertEqual(site4.name, data['name'])
- self.assertEqual(site4.slug, data['slug'])
- self.assertEqual(site4.region_id, data['region'])
-
- def test_create_site_bulk(self):
-
- data = [
- {
- 'name': 'Test Site 4',
- 'slug': 'test-site-4',
- 'region': self.region1.pk,
- 'status': SiteStatusChoices.STATUS_ACTIVE,
- },
- {
- 'name': 'Test Site 5',
- 'slug': 'test-site-5',
- 'region': self.region1.pk,
- 'status': SiteStatusChoices.STATUS_ACTIVE,
- },
- {
- 'name': 'Test Site 6',
- 'slug': 'test-site-6',
- 'region': self.region1.pk,
- 'status': SiteStatusChoices.STATUS_ACTIVE,
- },
- ]
-
- url = reverse('dcim-api:site-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Site.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_site(self):
-
- data = {
- 'name': 'Test Site X',
- 'slug': 'test-site-x',
- 'region': self.region2.pk,
- }
-
- url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Site.objects.count(), 3)
- site1 = Site.objects.get(pk=response.data['id'])
- self.assertEqual(site1.name, data['name'])
- self.assertEqual(site1.slug, data['slug'])
- self.assertEqual(site1.region_id, data['region'])
-
- def test_delete_site(self):
-
- url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Site.objects.count(), 2)
-
-
-class RackGroupTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2')
- self.parent_rackgroup1 = RackGroup.objects.create(site=self.site1, name='Parent Rack Group 1', slug='parent-rack-group-1')
- self.parent_rackgroup2 = RackGroup.objects.create(site=self.site2, name='Parent Rack Group 2', slug='parent-rack-group-2')
- self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Rack Group 1', slug='rack-group-1', parent=self.parent_rackgroup1)
- self.rackgroup2 = RackGroup.objects.create(site=self.site1, name='Rack Group 2', slug='rack-group-2', parent=self.parent_rackgroup1)
- self.rackgroup3 = RackGroup.objects.create(site=self.site1, name='Rack Group 3', slug='rack-group-3', parent=self.parent_rackgroup1)
-
- def test_get_rackgroup(self):
-
- url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.rackgroup1.name)
-
- def test_list_rackgroups(self):
-
- url = reverse('dcim-api:rackgroup-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 5)
-
- def test_list_rackgroups_brief(self):
-
- url = reverse('dcim-api:rackgroup-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'rack_count', 'slug', 'url']
- )
-
- def test_create_rackgroup(self):
-
- data = {
- 'name': 'Rack Group 4',
- 'slug': 'rack-group-4',
- 'site': self.site1.pk,
- 'parent': self.parent_rackgroup1.pk,
- }
-
- url = reverse('dcim-api:rackgroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackGroup.objects.count(), 6)
- rackgroup4 = RackGroup.objects.get(pk=response.data['id'])
- self.assertEqual(rackgroup4.name, data['name'])
- self.assertEqual(rackgroup4.slug, data['slug'])
- self.assertEqual(rackgroup4.site_id, data['site'])
- self.assertEqual(rackgroup4.parent_id, data['parent'])
-
- def test_create_rackgroup_bulk(self):
-
- data = [
+ cls.create_data = [
{
'name': 'Test Rack Group 4',
'slug': 'test-rack-group-4',
- 'site': self.site1.pk,
- 'parent': self.parent_rackgroup1.pk,
+ 'site': sites[1].pk,
+ 'parent': parent_rack_groups[1].pk,
},
{
'name': 'Test Rack Group 5',
'slug': 'test-rack-group-5',
- 'site': self.site1.pk,
- 'parent': self.parent_rackgroup1.pk,
+ 'site': sites[1].pk,
+ 'parent': parent_rack_groups[1].pk,
},
{
'name': 'Test Rack Group 6',
'slug': 'test-rack-group-6',
- 'site': self.site1.pk,
- 'parent': self.parent_rackgroup1.pk,
+ 'site': sites[1].pk,
+ 'parent': parent_rack_groups[1].pk,
},
]
- url = reverse('dcim-api:rackgroup-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackGroup.objects.count(), 8)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class RackRoleTest(APIViewTestCases.APIViewTestCase):
+ model = RackRole
+ brief_fields = ['id', 'name', 'rack_count', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Rack Role 4',
+ 'slug': 'rack-role-4',
+ 'color': 'ffff00',
+ },
+ {
+ 'name': 'Rack Role 5',
+ 'slug': 'rack-role-5',
+ 'color': 'ffff00',
+ },
+ {
+ 'name': 'Rack Role 6',
+ 'slug': 'rack-role-6',
+ 'color': 'ffff00',
+ },
+ ]
- def test_update_rackgroup(self):
+ @classmethod
+ def setUpTestData(cls):
- data = {
- 'name': 'Test Rack Group X',
- 'slug': 'test-rack-group-x',
- 'site': self.site2.pk,
- 'parent': self.parent_rackgroup2.pk,
- }
-
- url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(RackGroup.objects.count(), 5)
- rackgroup1 = RackGroup.objects.get(pk=response.data['id'])
- self.assertEqual(rackgroup1.name, data['name'])
- self.assertEqual(rackgroup1.slug, data['slug'])
- self.assertEqual(rackgroup1.site_id, data['site'])
- self.assertEqual(rackgroup1.parent_id, data['parent'])
-
- def test_delete_rackgroup(self):
-
- url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(RackGroup.objects.count(), 4)
+ 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)
-class RackRoleTest(APITestCase):
+class RackTest(APIViewTestCases.APIViewTestCase):
+ model = Rack
+ brief_fields = ['device_count', 'display_name', 'id', 'name', 'url']
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
+ sites = (
+ Site(name='Site 1', slug='site-1'),
+ Site(name='Site 2', slug='site-2'),
+ )
+ Site.objects.bulk_create(sites)
- self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000')
- self.rackrole2 = RackRole.objects.create(name='Test Rack Role 2', slug='test-rack-role-2', color='00ff00')
- self.rackrole3 = RackRole.objects.create(name='Test Rack Role 3', slug='test-rack-role-3', color='0000ff')
-
- def test_get_rackrole(self):
-
- url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.rackrole1.name)
-
- def test_list_rackroles(self):
-
- url = reverse('dcim-api:rackrole-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_rackroles_brief(self):
-
- url = reverse('dcim-api:rackrole-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'rack_count', 'slug', 'url']
+ rack_groups = (
+ RackGroup.objects.create(site=sites[0], name='Rack Group 1', slug='rack-group-1'),
+ RackGroup.objects.create(site=sites[1], name='Rack Group 2', slug='rack-group-2'),
)
- def test_create_rackrole(self):
+ 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.objects.bulk_create(rack_roles)
- data = {
- 'name': 'Test Rack Role 4',
- 'slug': 'test-rack-role-4',
- 'color': 'ffff00',
- }
+ racks = (
+ Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 1'),
+ Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 2'),
+ Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 3'),
+ )
+ Rack.objects.bulk_create(racks)
- url = reverse('dcim-api:rackrole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackRole.objects.count(), 4)
- rackrole1 = RackRole.objects.get(pk=response.data['id'])
- self.assertEqual(rackrole1.name, data['name'])
- self.assertEqual(rackrole1.slug, data['slug'])
- self.assertEqual(rackrole1.color, data['color'])
-
- def test_create_rackrole_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Rack Role 4',
- 'slug': 'test-rack-role-4',
- 'color': 'ffff00',
+ 'name': 'Test Rack 4',
+ 'site': sites[1].pk,
+ 'group': rack_groups[1].pk,
+ 'role': rack_roles[1].pk,
},
{
- 'name': 'Test Rack Role 5',
- 'slug': 'test-rack-role-5',
- 'color': 'ffff00',
+ 'name': 'Test Rack 5',
+ 'site': sites[1].pk,
+ 'group': rack_groups[1].pk,
+ 'role': rack_roles[1].pk,
},
{
- 'name': 'Test Rack Role 6',
- 'slug': 'test-rack-role-6',
- 'color': 'ffff00',
+ 'name': 'Test Rack 6',
+ 'site': sites[1].pk,
+ 'group': rack_groups[1].pk,
+ 'role': rack_roles[1].pk,
},
]
- url = reverse('dcim-api:rackrole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackRole.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_rackrole(self):
-
- data = {
- 'name': 'Test Rack Role X',
- 'slug': 'test-rack-role-x',
- 'color': 'ffff00',
- }
-
- url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(RackRole.objects.count(), 3)
- rackrole1 = RackRole.objects.get(pk=response.data['id'])
- self.assertEqual(rackrole1.name, data['name'])
- self.assertEqual(rackrole1.slug, data['slug'])
- self.assertEqual(rackrole1.color, data['color'])
-
- def test_delete_rackrole(self):
-
- url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(RackRole.objects.count(), 2)
-
-
-class RackTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2')
- self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1')
- self.rackgroup2 = RackGroup.objects.create(site=self.site2, name='Test Rack Group 2', slug='test-rack-group-2')
- self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000')
- self.rackrole2 = RackRole.objects.create(name='Test Rack Role 2', slug='test-rack-role-2', color='00ff00')
- self.rack1 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 1', u_height=42,
- )
- self.rack2 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 2', u_height=42,
- )
- self.rack3 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 3', u_height=42,
- )
-
- def test_get_rack(self):
-
- url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.rack1.name)
-
+ # TODO: Document this test
def test_get_elevation_rack_units(self):
+ rack = Rack.objects.first()
- url = '{}?q=3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}))
+ url = '{}?q=3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
response = self.client.get(url, **self.header)
self.assertEqual(response.data['count'], 13)
- url = '{}?q=U3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}))
+ url = '{}?q=U3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
response = self.client.get(url, **self.header)
self.assertEqual(response.data['count'], 11)
- url = '{}?q=10'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}))
+ url = '{}?q=10'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
response = self.client.get(url, **self.header)
self.assertEqual(response.data['count'], 1)
- url = '{}?q=U20'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}))
+ url = '{}?q=U20'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
response = self.client.get(url, **self.header)
self.assertEqual(response.data['count'], 1)
def test_get_rack_elevation(self):
-
- url = reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})
+ """
+ GET a single rack elevation.
+ """
+ rack = Rack.objects.first()
+ url = reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})
response = self.client.get(url, **self.header)
self.assertEqual(response.data['count'], 42)
def test_get_rack_elevation_svg(self):
-
- url = '{}?render=svg'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}))
+ """
+ GET a single rack elevation in SVG format.
+ """
+ rack = Rack.objects.first()
+ url = '{}?render=svg'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
response = self.client.get(url, **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.get('Content-Type'), 'image/svg+xml')
- def test_list_racks(self):
- url = reverse('dcim-api:rack-list')
- response = self.client.get(url, **self.header)
+class RackReservationTest(APIViewTestCases.APIViewTestCase):
+ model = RackReservation
+ brief_fields = ['id', 'units', 'url', 'user']
- self.assertEqual(response.data['count'], 3)
+ @classmethod
+ def setUpTestData(cls):
- def test_list_racks_brief(self):
+ user = User.objects.create(username='user1', is_active=True)
- url = reverse('dcim-api:rack-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
+ site = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['device_count', 'display_name', 'id', 'name', 'url']
+ cls.racks = (
+ Rack(site=site, name='Rack 1'),
+ Rack(site=site, name='Rack 2'),
)
+ Rack.objects.bulk_create(cls.racks)
- def test_create_rack(self):
-
- data = {
- 'name': 'Test Rack 4',
- 'facility_id': '1234',
- 'site': self.site1.pk,
- 'group': self.rackgroup1.pk,
- 'role': self.rackrole1.pk,
- }
-
- url = reverse('dcim-api:rack-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Rack.objects.count(), 4)
- rack4 = Rack.objects.get(pk=response.data['id'])
- self.assertEqual(rack4.name, data['name'])
- self.assertEqual(rack4.site_id, data['site'])
- self.assertEqual(rack4.group_id, data['group'])
- self.assertEqual(rack4.role_id, data['role'])
-
- def test_create_rack_bulk(self):
-
- data = [
- {
- 'name': 'Test Rack 4',
- 'site': self.site1.pk,
- 'group': self.rackgroup1.pk,
- 'role': self.rackrole1.pk,
- },
- {
- 'name': 'Test Rack 5',
- 'site': self.site1.pk,
- 'group': self.rackgroup1.pk,
- 'role': self.rackrole1.pk,
- },
- {
- 'name': 'Test Rack 6',
- 'site': self.site1.pk,
- 'group': self.rackgroup1.pk,
- 'role': self.rackrole1.pk,
- },
- ]
-
- url = reverse('dcim-api:rack-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Rack.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_rack(self):
-
- data = {
- 'name': 'Test Rack X',
- 'site': self.site2.pk,
- 'group': self.rackgroup2.pk,
- 'role': self.rackrole2.pk,
- }
-
- url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Rack.objects.count(), 3)
- rack1 = Rack.objects.get(pk=response.data['id'])
- self.assertEqual(rack1.name, data['name'])
- self.assertEqual(rack1.site_id, data['site'])
- self.assertEqual(rack1.group_id, data['group'])
- self.assertEqual(rack1.role_id, data['role'])
-
- def test_delete_rack(self):
-
- url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Rack.objects.count(), 2)
-
-
-class RackReservationTest(APITestCase):
+ rack_reservations = (
+ RackReservation(rack=cls.racks[0], units=[1, 2, 3], user=user, description='Reservation #1'),
+ RackReservation(rack=cls.racks[0], units=[4, 5, 6], user=user, description='Reservation #2'),
+ RackReservation(rack=cls.racks[0], units=[7, 8, 9], user=user, description='Reservation #3'),
+ )
+ RackReservation.objects.bulk_create(rack_reservations)
def setUp(self):
-
super().setUp()
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.rack1 = Rack.objects.create(site=self.site1, name='Test Rack 1')
- self.rackreservation1 = RackReservation.objects.create(
- rack=self.rack1, units=[1, 2, 3], user=self.user, description='Reservation #1',
- )
- self.rackreservation2 = RackReservation.objects.create(
- rack=self.rack1, units=[4, 5, 6], user=self.user, description='Reservation #2',
- )
- self.rackreservation3 = RackReservation.objects.create(
- rack=self.rack1, units=[7, 8, 9], user=self.user, description='Reservation #3',
- )
-
- def test_get_rackreservation(self):
-
- url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['id'], self.rackreservation1.pk)
-
- def test_list_rackreservations(self):
-
- url = reverse('dcim-api:rackreservation-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_rackreservation(self):
-
- data = {
- 'rack': self.rack1.pk,
- 'units': [10, 11, 12],
- 'user': self.user.pk,
- 'description': 'Fourth reservation',
- }
-
- url = reverse('dcim-api:rackreservation-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackReservation.objects.count(), 4)
- rackreservation4 = RackReservation.objects.get(pk=response.data['id'])
- self.assertEqual(rackreservation4.rack_id, data['rack'])
- self.assertEqual(rackreservation4.units, data['units'])
- self.assertEqual(rackreservation4.user_id, data['user'])
- self.assertEqual(rackreservation4.description, data['description'])
-
- def test_create_rackreservation_bulk(self):
-
- data = [
+ # We have to set creation data under setUp() because we need access to the test user.
+ self.create_data = [
{
- 'rack': self.rack1.pk,
+ 'rack': self.racks[1].pk,
'units': [10, 11, 12],
'user': self.user.pk,
'description': 'Reservation #4',
},
{
- 'rack': self.rack1.pk,
+ 'rack': self.racks[1].pk,
'units': [13, 14, 15],
'user': self.user.pk,
'description': 'Reservation #5',
},
{
- 'rack': self.rack1.pk,
+ 'rack': self.racks[1].pk,
'units': [16, 17, 18],
'user': self.user.pk,
'description': 'Reservation #6',
},
]
- url = reverse('dcim-api:rackreservation-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RackReservation.objects.count(), 6)
- self.assertEqual(response.data[0]['description'], data[0]['description'])
- self.assertEqual(response.data[1]['description'], data[1]['description'])
- self.assertEqual(response.data[2]['description'], data[2]['description'])
+class ManufacturerTest(APIViewTestCases.APIViewTestCase):
+ model = Manufacturer
+ brief_fields = ['devicetype_count', 'id', 'name', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Manufacturer 4',
+ 'slug': 'manufacturer-4',
+ },
+ {
+ 'name': 'Manufacturer 5',
+ 'slug': 'manufacturer-5',
+ },
+ {
+ 'name': 'Manufacturer 6',
+ 'slug': 'manufacturer-6',
+ },
+ ]
- def test_update_rackreservation(self):
+ @classmethod
+ def setUpTestData(cls):
- data = {
- 'rack': self.rack1.pk,
- 'units': [10, 11, 12],
- 'user': self.user.pk,
- 'description': 'Modified reservation',
- }
-
- url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(RackReservation.objects.count(), 3)
- rackreservation1 = RackReservation.objects.get(pk=response.data['id'])
- self.assertEqual(rackreservation1.units, data['units'])
- self.assertEqual(rackreservation1.description, data['description'])
-
- def test_delete_rackreservation(self):
-
- url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(RackReservation.objects.count(), 2)
-
-
-class ManufacturerTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer1 = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.manufacturer2 = Manufacturer.objects.create(name='Test Manufacturer 2', slug='test-manufacturer-2')
- self.manufacturer3 = Manufacturer.objects.create(name='Test Manufacturer 3', slug='test-manufacturer-3')
-
- def test_get_manufacturer(self):
-
- url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.manufacturer1.name)
-
- def test_list_manufacturers(self):
-
- url = reverse('dcim-api:manufacturer-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_manufacturers_brief(self):
-
- url = reverse('dcim-api:manufacturer-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['devicetype_count', 'id', 'name', 'slug', 'url']
+ 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_create_manufacturer(self):
- data = {
- 'name': 'Test Manufacturer 4',
- 'slug': 'test-manufacturer-4',
- }
+class DeviceTypeTest(APIViewTestCases.APIViewTestCase):
+ model = DeviceType
+ brief_fields = ['device_count', 'display_name', 'id', 'manufacturer', 'model', 'slug', 'url']
- url = reverse('dcim-api:manufacturer-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Manufacturer.objects.count(), 4)
- manufacturer4 = Manufacturer.objects.get(pk=response.data['id'])
- self.assertEqual(manufacturer4.name, data['name'])
- self.assertEqual(manufacturer4.slug, data['slug'])
+ manufacturers = (
+ Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
+ Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
+ )
+ Manufacturer.objects.bulk_create(manufacturers)
- def test_create_manufacturer_bulk(self):
+ device_types = (
+ DeviceType(manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1'),
+ DeviceType(manufacturer=manufacturers[0], model='Device Type 2', slug='device-type-2'),
+ DeviceType(manufacturer=manufacturers[0], model='Device Type 3', slug='device-type-3'),
+ )
+ DeviceType.objects.bulk_create(device_types)
- data = [
+ cls.create_data = [
{
- 'name': 'Test Manufacturer 4',
- 'slug': 'test-manufacturer-4',
+ 'manufacturer': manufacturers[1].pk,
+ 'model': 'Device Type 4',
+ 'slug': 'device-type-4',
},
{
- 'name': 'Test Manufacturer 5',
- 'slug': 'test-manufacturer-5',
+ 'manufacturer': manufacturers[1].pk,
+ 'model': 'Device Type 5',
+ 'slug': 'device-type-5',
},
{
- 'name': 'Test Manufacturer 6',
- 'slug': 'test-manufacturer-6',
+ 'manufacturer': manufacturers[1].pk,
+ 'model': 'Device Type 6',
+ 'slug': 'device-type-6',
},
]
- url = reverse('dcim-api:manufacturer-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Manufacturer.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = ConsolePortTemplate
+ brief_fields = ['id', 'name', 'url']
- def test_update_manufacturer(self):
-
- data = {
- 'name': 'Test Manufacturer X',
- 'slug': 'test-manufacturer-x',
- }
-
- url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Manufacturer.objects.count(), 3)
- manufacturer1 = Manufacturer.objects.get(pk=response.data['id'])
- self.assertEqual(manufacturer1.name, data['name'])
- self.assertEqual(manufacturer1.slug, data['slug'])
-
- def test_delete_manufacturer(self):
-
- url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Manufacturer.objects.count(), 2)
-
-
-class DeviceTypeTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer1 = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.manufacturer2 = Manufacturer.objects.create(name='Test Manufacturer 2', slug='test-manufacturer-2')
- self.devicetype1 = DeviceType.objects.create(
- manufacturer=self.manufacturer1, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.devicetype2 = DeviceType.objects.create(
- manufacturer=self.manufacturer1, model='Test Device Type 2', slug='test-device-type-2'
- )
- self.devicetype3 = DeviceType.objects.create(
- manufacturer=self.manufacturer1, model='Test Device Type 3', slug='test-device-type-3'
- )
-
- def test_get_devicetype(self):
-
- url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['model'], self.devicetype1.model)
-
- def test_list_devicetypes(self):
-
- url = reverse('dcim-api:devicetype-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_devicetypes_brief(self):
-
- url = reverse('dcim-api:devicetype-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['device_count', 'display_name', 'id', 'manufacturer', 'model', 'slug', 'url']
- )
-
- def test_create_devicetype(self):
-
- data = {
- 'manufacturer': self.manufacturer1.pk,
- 'model': 'Test Device Type 4',
- 'slug': 'test-device-type-4',
- }
-
- url = reverse('dcim-api:devicetype-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceType.objects.count(), 4)
- devicetype4 = DeviceType.objects.get(pk=response.data['id'])
- self.assertEqual(devicetype4.manufacturer_id, data['manufacturer'])
- self.assertEqual(devicetype4.model, data['model'])
- self.assertEqual(devicetype4.slug, data['slug'])
-
- def test_create_devicetype_bulk(self):
-
- data = [
- {
- 'manufacturer': self.manufacturer1.pk,
- 'model': 'Test Device Type 4',
- 'slug': 'test-device-type-4',
- },
- {
- 'manufacturer': self.manufacturer1.pk,
- 'model': 'Test Device Type 5',
- 'slug': 'test-device-type-5',
- },
- {
- 'manufacturer': self.manufacturer1.pk,
- 'model': 'Test Device Type 6',
- 'slug': 'test-device-type-6',
- },
- ]
-
- url = reverse('dcim-api:devicetype-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceType.objects.count(), 6)
- self.assertEqual(response.data[0]['model'], data[0]['model'])
- self.assertEqual(response.data[1]['model'], data[1]['model'])
- self.assertEqual(response.data[2]['model'], data[2]['model'])
-
- def test_update_devicetype(self):
-
- data = {
- 'manufacturer': self.manufacturer2.pk,
- 'model': 'Test Device Type X',
- 'slug': 'test-device-type-x',
- }
-
- url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(DeviceType.objects.count(), 3)
- devicetype1 = DeviceType.objects.get(pk=response.data['id'])
- self.assertEqual(devicetype1.manufacturer_id, data['manufacturer'])
- self.assertEqual(devicetype1.model, data['model'])
- self.assertEqual(devicetype1.slug, data['slug'])
-
- def test_delete_devicetype(self):
-
- url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(DeviceType.objects.count(), 2)
-
-
-class ConsolePortTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.consoleporttemplate1 = ConsolePortTemplate.objects.create(
- device_type=self.devicetype, name='Test CP Template 1'
- )
- self.consoleporttemplate2 = ConsolePortTemplate.objects.create(
- device_type=self.devicetype, name='Test CP Template 2'
- )
- self.consoleporttemplate3 = ConsolePortTemplate.objects.create(
- device_type=self.devicetype, name='Test CP Template 3'
- )
-
- def test_get_consoleporttemplate(self):
-
- url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.consoleporttemplate1.name)
-
- def test_list_consoleporttemplates(self):
-
- url = reverse('dcim-api:consoleporttemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_consoleporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CP Template 4',
- }
-
- url = reverse('dcim-api:consoleporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsolePortTemplate.objects.count(), 4)
- consoleporttemplate4 = ConsolePortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(consoleporttemplate4.device_type_id, data['device_type'])
- self.assertEqual(consoleporttemplate4.name, data['name'])
-
- def test_create_consoleporttemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CP Template 4',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CP Template 5',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CP Template 6',
- },
- ]
-
- url = reverse('dcim-api:consoleporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsolePortTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_consoleporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CP Template X',
- }
-
- url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ConsolePortTemplate.objects.count(), 3)
- consoleporttemplate1 = ConsolePortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(consoleporttemplate1.name, data['name'])
-
- def test_delete_consoleporttemplate(self):
-
- url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ConsolePortTemplate.objects.count(), 2)
-
-
-class ConsoleServerPortTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.consoleserverporttemplate1 = ConsoleServerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test CSP Template 1'
- )
- self.consoleserverporttemplate2 = ConsoleServerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test CSP Template 2'
- )
- self.consoleserverporttemplate3 = ConsoleServerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test CSP Template 3'
- )
-
- def test_get_consoleserverporttemplate(self):
-
- url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.consoleserverporttemplate1.name)
-
- def test_list_consoleserverporttemplates(self):
-
- url = reverse('dcim-api:consoleserverporttemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_consoleserverporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CSP Template 4',
- }
-
- url = reverse('dcim-api:consoleserverporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsoleServerPortTemplate.objects.count(), 4)
- consoleserverporttemplate4 = ConsoleServerPortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(consoleserverporttemplate4.device_type_id, data['device_type'])
- self.assertEqual(consoleserverporttemplate4.name, data['name'])
-
- def test_create_consoleserverporttemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CSP Template 4',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CSP Template 5',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CSP Template 6',
- },
- ]
-
- url = reverse('dcim-api:consoleserverporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsoleServerPortTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_consoleserverporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test CSP Template X',
- }
-
- url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ConsoleServerPortTemplate.objects.count(), 3)
- consoleserverporttemplate1 = ConsoleServerPortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(consoleserverporttemplate1.name, data['name'])
-
- def test_delete_consoleserverporttemplate(self):
-
- url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ConsoleServerPortTemplate.objects.count(), 2)
-
-
-class PowerPortTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.powerporttemplate1 = PowerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test PP Template 1'
- )
- self.powerporttemplate2 = PowerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test PP Template 2'
- )
- self.powerporttemplate3 = PowerPortTemplate.objects.create(
- device_type=self.devicetype, name='Test PP Template 3'
- )
-
- def test_get_powerporttemplate(self):
-
- url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.powerporttemplate1.name)
-
- def test_list_powerporttemplates(self):
-
- url = reverse('dcim-api:powerporttemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_powerporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PP Template 4',
- }
-
- url = reverse('dcim-api:powerporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPortTemplate.objects.count(), 4)
- powerporttemplate4 = PowerPortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(powerporttemplate4.device_type_id, data['device_type'])
- self.assertEqual(powerporttemplate4.name, data['name'])
-
- def test_create_powerporttemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PP Template 4',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PP Template 5',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PP Template 6',
- },
- ]
-
- url = reverse('dcim-api:powerporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPortTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_powerporttemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PP Template X',
- }
-
- url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerPortTemplate.objects.count(), 3)
- powerporttemplate1 = PowerPortTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(powerporttemplate1.name, data['name'])
-
- def test_delete_powerporttemplate(self):
-
- url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerPortTemplate.objects.count(), 2)
-
-
-class PowerOutletTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.poweroutlettemplate1 = PowerOutletTemplate.objects.create(
- device_type=self.devicetype, name='Test PO Template 1'
- )
- self.poweroutlettemplate2 = PowerOutletTemplate.objects.create(
- device_type=self.devicetype, name='Test PO Template 2'
- )
- self.poweroutlettemplate3 = PowerOutletTemplate.objects.create(
- device_type=self.devicetype, name='Test PO Template 3'
- )
-
- def test_get_poweroutlettemplate(self):
-
- url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.poweroutlettemplate1.name)
-
- def test_list_poweroutlettemplates(self):
-
- url = reverse('dcim-api:poweroutlettemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_poweroutlettemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PO Template 4',
- }
-
- url = reverse('dcim-api:poweroutlettemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerOutletTemplate.objects.count(), 4)
- poweroutlettemplate4 = PowerOutletTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(poweroutlettemplate4.device_type_id, data['device_type'])
- self.assertEqual(poweroutlettemplate4.name, data['name'])
-
- def test_create_poweroutlettemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PO Template 4',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PO Template 5',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PO Template 6',
- },
- ]
-
- url = reverse('dcim-api:poweroutlettemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerOutletTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_poweroutlettemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test PO Template X',
- }
-
- url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerOutletTemplate.objects.count(), 3)
- poweroutlettemplate1 = PowerOutletTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(poweroutlettemplate1.name, data['name'])
-
- def test_delete_poweroutlettemplate(self):
-
- url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerOutletTemplate.objects.count(), 2)
-
-
-class InterfaceTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.interfacetemplate1 = InterfaceTemplate.objects.create(
- device_type=self.devicetype, name='Test Interface Template 1', type='1000base-t'
- )
- self.interfacetemplate2 = InterfaceTemplate.objects.create(
- device_type=self.devicetype, name='Test Interface Template 2', type='1000base-t'
- )
- self.interfacetemplate3 = InterfaceTemplate.objects.create(
- device_type=self.devicetype, name='Test Interface Template 3', type='1000base-t'
- )
-
- def test_get_interfacetemplate(self):
-
- url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.interfacetemplate1.name)
-
- def test_list_interfacetemplates(self):
-
- url = reverse('dcim-api:interfacetemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_interfacetemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Interface Template 4',
- 'type': '1000base-t',
- }
-
- url = reverse('dcim-api:interfacetemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(InterfaceTemplate.objects.count(), 4)
- interfacetemplate4 = InterfaceTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(interfacetemplate4.device_type_id, data['device_type'])
- self.assertEqual(interfacetemplate4.name, data['name'])
-
- def test_create_interfacetemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Interface Template 4',
- 'type': '1000base-t',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Interface Template 5',
- 'type': '1000base-t',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Interface Template 6',
- 'type': '1000base-t',
- },
- ]
-
- url = reverse('dcim-api:interfacetemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(InterfaceTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_interfacetemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Interface Template X',
- 'type': '1000base-x-gbic',
- }
-
- url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(InterfaceTemplate.objects.count(), 3)
- interfacetemplate1 = InterfaceTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(interfacetemplate1.name, data['name'])
-
- def test_delete_interfacetemplate(self):
-
- url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(InterfaceTemplate.objects.count(), 2)
-
-
-class DeviceBayTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.devicebaytemplate1 = DeviceBayTemplate.objects.create(
- device_type=self.devicetype, name='Test Device Bay Template 1'
- )
- self.devicebaytemplate2 = DeviceBayTemplate.objects.create(
- device_type=self.devicetype, name='Test Device Bay Template 2'
- )
- self.devicebaytemplate3 = DeviceBayTemplate.objects.create(
- device_type=self.devicetype, name='Test Device Bay Template 3'
- )
-
- def test_get_devicebaytemplate(self):
-
- url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.devicebaytemplate1.name)
-
- def test_list_devicebaytemplates(self):
-
- url = reverse('dcim-api:devicebaytemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_devicebaytemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Device Bay Template 4',
- }
-
- url = reverse('dcim-api:devicebaytemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceBayTemplate.objects.count(), 4)
- devicebaytemplate4 = DeviceBayTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(devicebaytemplate4.device_type_id, data['device_type'])
- self.assertEqual(devicebaytemplate4.name, data['name'])
-
- def test_create_devicebaytemplate_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Device Bay Template 4',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Device Bay Template 5',
- },
- {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Device Bay Template 6',
- },
- ]
-
- url = reverse('dcim-api:devicebaytemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceBayTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_devicebaytemplate(self):
-
- data = {
- 'device_type': self.devicetype.pk,
- 'name': 'Test Device Bay Template X',
- }
-
- url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(DeviceBayTemplate.objects.count(), 3)
- devicebaytemplate1 = DeviceBayTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(devicebaytemplate1.name, data['name'])
-
- def test_delete_devicebaytemplate(self):
-
- url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(DeviceBayTemplate.objects.count(), 2)
-
-
-class DeviceRoleTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.devicerole1 = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.devicerole2 = DeviceRole.objects.create(
- name='Test Device Role 2', slug='test-device-role-2', color='00ff00'
- )
- self.devicerole3 = DeviceRole.objects.create(
- name='Test Device Role 3', slug='test-device-role-3', color='0000ff'
- )
-
- def test_get_devicerole(self):
-
- url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.devicerole1.name)
-
- def test_list_deviceroles(self):
-
- url = reverse('dcim-api:devicerole-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_deviceroles_brief(self):
-
- url = reverse('dcim-api:devicerole-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
- )
-
- def test_create_devicerole(self):
-
- data = {
- 'name': 'Test Device Role 4',
- 'slug': 'test-device-role-4',
- 'color': 'ffff00',
- }
-
- url = reverse('dcim-api:devicerole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceRole.objects.count(), 4)
- devicerole4 = DeviceRole.objects.get(pk=response.data['id'])
- self.assertEqual(devicerole4.name, data['name'])
- self.assertEqual(devicerole4.slug, data['slug'])
- self.assertEqual(devicerole4.color, data['color'])
-
- def test_create_devicerole_bulk(self):
-
- data = [
- {
- 'name': 'Test Device Role 4',
- 'slug': 'test-device-role-4',
- 'color': 'ffff00',
- },
- {
- 'name': 'Test Device Role 5',
- 'slug': 'test-device-role-5',
- 'color': 'ffff00',
- },
- {
- 'name': 'Test Device Role 6',
- 'slug': 'test-device-role-6',
- 'color': 'ffff00',
- },
- ]
-
- url = reverse('dcim-api:devicerole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceRole.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_devicerole(self):
-
- data = {
- 'name': 'Test Device Role X',
- 'slug': 'test-device-role-x',
- 'color': '00ffff',
- }
-
- url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(DeviceRole.objects.count(), 3)
- devicerole1 = DeviceRole.objects.get(pk=response.data['id'])
- self.assertEqual(devicerole1.name, data['name'])
- self.assertEqual(devicerole1.slug, data['slug'])
- self.assertEqual(devicerole1.color, data['color'])
-
- def test_delete_devicerole(self):
-
- url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(DeviceRole.objects.count(), 2)
-
-
-class PlatformTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.platform1 = Platform.objects.create(name='Test Platform 1', slug='test-platform-1')
- self.platform2 = Platform.objects.create(name='Test Platform 2', slug='test-platform-2')
- self.platform3 = Platform.objects.create(name='Test Platform 3', slug='test-platform-3')
-
- def test_get_platform(self):
-
- url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.platform1.name)
-
- def test_list_platforms(self):
-
- url = reverse('dcim-api:platform-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_platforms_brief(self):
-
- url = reverse('dcim-api:platform-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
- )
-
- def test_create_platform(self):
-
- data = {
- 'name': 'Test Platform 4',
- 'slug': 'test-platform-4',
- }
-
- url = reverse('dcim-api:platform-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Platform.objects.count(), 4)
- platform4 = Platform.objects.get(pk=response.data['id'])
- self.assertEqual(platform4.name, data['name'])
- self.assertEqual(platform4.slug, data['slug'])
-
- def test_create_platform_bulk(self):
-
- data = [
- {
- 'name': 'Test Platform 4',
- 'slug': 'test-platform-4',
- },
- {
- 'name': 'Test Platform 5',
- 'slug': 'test-platform-5',
- },
- {
- 'name': 'Test Platform 6',
- 'slug': 'test-platform-6',
- },
- ]
-
- url = reverse('dcim-api:platform-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Platform.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_platform(self):
-
- data = {
- 'name': 'Test Platform X',
- 'slug': 'test-platform-x',
- }
-
- url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Platform.objects.count(), 3)
- platform1 = Platform.objects.get(pk=response.data['id'])
- self.assertEqual(platform1.name, data['name'])
- self.assertEqual(platform1.slug, data['slug'])
-
- def test_delete_platform(self):
-
- url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Platform.objects.count(), 2)
-
-
-class DeviceTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2')
- self.rack1 = Rack.objects.create(name='Test Rack 1', site=self.site1, u_height=48)
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype1 = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
- )
- self.devicetype2 = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 2', slug='test-device-type-2'
- )
- self.devicerole1 = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.devicerole2 = DeviceRole.objects.create(
- name='Test Device Role 2', slug='test-device-role-2', color='00ff00'
- )
- cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1')
- self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type)
- self.device1 = Device.objects.create(
- device_type=self.devicetype1,
- device_role=self.devicerole1,
- name='Test Device 1',
- site=self.site1,
- cluster=self.cluster1
- )
- self.device2 = Device.objects.create(
- device_type=self.devicetype1,
- device_role=self.devicerole1,
- name='Test Device 2',
- site=self.site1,
- cluster=self.cluster1
- )
- self.device3 = Device.objects.create(
- device_type=self.devicetype1,
- device_role=self.devicerole1,
- name='Test Device 3',
- site=self.site1,
- cluster=self.cluster1
- )
- self.device_with_context_data = Device.objects.create(
- device_type=self.devicetype1,
- device_role=self.devicerole1,
- name='Device with context data',
- site=self.site1,
- local_context_data={
- 'A': 1,
- 'B': 2
- }
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
)
- def test_get_device(self):
+ console_port_templates = (
+ ConsolePortTemplate(device_type=devicetype, name='Console Port Template 1'),
+ ConsolePortTemplate(device_type=devicetype, name='Console Port Template 2'),
+ ConsolePortTemplate(device_type=devicetype, name='Console Port Template 3'),
+ )
+ ConsolePortTemplate.objects.bulk_create(console_port_templates)
- url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk})
- response = self.client.get(url, **self.header)
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Port Template 4',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Port Template 5',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Port Template 6',
+ },
+ ]
- self.assertEqual(response.data['name'], self.device1.name)
- self.assertEqual(response.data['device_role']['id'], self.devicerole1.pk)
- self.assertEqual(response.data['cluster']['id'], self.cluster1.pk)
+
+class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = ConsoleServerPortTemplate
+ brief_fields = ['id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
+ )
+
+ console_server_port_templates = (
+ ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 1'),
+ ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 2'),
+ ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 3'),
+ )
+ ConsoleServerPortTemplate.objects.bulk_create(console_server_port_templates)
+
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Server Port Template 4',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Server Port Template 5',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Console Server Port Template 6',
+ },
+ ]
+
+
+class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = PowerPortTemplate
+ brief_fields = ['id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
+ )
+
+ power_port_templates = (
+ PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'),
+ PowerPortTemplate(device_type=devicetype, name='Power Port Template 2'),
+ PowerPortTemplate(device_type=devicetype, name='Power Port Template 3'),
+ )
+ PowerPortTemplate.objects.bulk_create(power_port_templates)
+
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Port Template 4',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Port Template 5',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Port Template 6',
+ },
+ ]
+
+
+class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = PowerOutletTemplate
+ brief_fields = ['id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
+ )
+
+ power_outlet_templates = (
+ PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'),
+ PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'),
+ PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'),
+ )
+ PowerOutletTemplate.objects.bulk_create(power_outlet_templates)
+
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Outlet Template 4',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Outlet Template 5',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Power Outlet Template 6',
+ },
+ ]
+
+
+class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = InterfaceTemplate
+ brief_fields = ['id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
+ )
+
+ interface_templates = (
+ InterfaceTemplate(device_type=devicetype, name='Interface Template 1', type='1000base-t'),
+ InterfaceTemplate(device_type=devicetype, name='Interface Template 2', type='1000base-t'),
+ InterfaceTemplate(device_type=devicetype, name='Interface Template 3', type='1000base-t'),
+ )
+ InterfaceTemplate.objects.bulk_create(interface_templates)
+
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Interface Template 4',
+ 'type': '1000base-t',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Interface Template 5',
+ 'type': '1000base-t',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Interface Template 6',
+ 'type': '1000base-t',
+ },
+ ]
+
+
+class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = DeviceBayTemplate
+ brief_fields = ['id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(
+ manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
+ )
+
+ device_bay_templates = (
+ DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 1'),
+ DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 2'),
+ DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 3'),
+ )
+ DeviceBayTemplate.objects.bulk_create(device_bay_templates)
+
+ cls.create_data = [
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Device Bay Template 4',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Device Bay Template 5',
+ },
+ {
+ 'device_type': devicetype.pk,
+ 'name': 'Device Bay Template 6',
+ },
+ ]
+
+
+class DeviceRoleTest(APIViewTestCases.APIViewTestCase):
+ model = DeviceRole
+ brief_fields = ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
+ create_data = [
+ {
+ 'name': 'Device Role 4',
+ 'slug': 'device-role-4',
+ 'color': 'ffff00',
+ },
+ {
+ 'name': 'Device Role 5',
+ 'slug': 'device-role-5',
+ 'color': 'ffff00',
+ },
+ {
+ 'name': 'Device Role 6',
+ 'slug': 'device-role-6',
+ 'color': 'ffff00',
+ },
+ ]
+
+ @classmethod
+ def setUpTestData(cls):
+
+ device_roles = (
+ DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'),
+ DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'),
+ DeviceRole(name='Device Role 3', slug='device-role-3', color='0000ff'),
+ )
+ DeviceRole.objects.bulk_create(device_roles)
+
+
+class PlatformTest(APIViewTestCases.APIViewTestCase):
+ model = Platform
+ brief_fields = ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
+ create_data = [
+ {
+ 'name': 'Platform 4',
+ 'slug': 'platform-4',
+ },
+ {
+ 'name': 'Platform 5',
+ 'slug': 'platform-5',
+ },
+ {
+ 'name': 'Platform 6',
+ 'slug': 'platform-6',
+ },
+ ]
+
+ @classmethod
+ def setUpTestData(cls):
+
+ 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)
+
+
+class DeviceTest(APIViewTestCases.APIViewTestCase):
+ model = Device
+ brief_fields = ['display_name', 'id', 'name', 'url']
+
+ @classmethod
+ def setUpTestData(cls):
+
+ sites = (
+ Site(name='Site 1', slug='site-1'),
+ Site(name='Site 2', slug='site-2'),
+ )
+ Site.objects.bulk_create(sites)
+
+ racks = (
+ Rack(name='Rack 1', site=sites[0]),
+ Rack(name='Rack 2', site=sites[1]),
+ )
+ Rack.objects.bulk_create(racks)
+
+ manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
+
+ device_types = (
+ DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
+ DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
+ )
+ DeviceType.objects.bulk_create(device_types)
+
+ device_roles = (
+ DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'),
+ DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'),
+ )
+ DeviceRole.objects.bulk_create(device_roles)
+
+ 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.objects.bulk_create(clusters)
+
+ devices = (
+ Device(
+ device_type=device_types[0],
+ device_role=device_roles[0],
+ name='Device 1',
+ site=sites[0],
+ rack=racks[0],
+ cluster=clusters[0],
+ local_context_data={'A': 1}
+ ),
+ Device(
+ device_type=device_types[0],
+ device_role=device_roles[0],
+ name='Device 2',
+ site=sites[0],
+ rack=racks[0],
+ cluster=clusters[0],
+ local_context_data={'B': 2}
+ ),
+ Device(
+ device_type=device_types[0],
+ device_role=device_roles[0],
+ name='Device 3',
+ site=sites[0],
+ rack=racks[0],
+ cluster=clusters[0],
+ local_context_data={'C': 3}
+ ),
+ )
+ Device.objects.bulk_create(devices)
+
+ cls.create_data = [
+ {
+ 'device_type': device_types[1].pk,
+ 'device_role': device_roles[1].pk,
+ 'name': 'Test Device 4',
+ 'site': sites[1].pk,
+ 'rack': racks[1].pk,
+ 'cluster': clusters[1].pk,
+ },
+ {
+ 'device_type': device_types[1].pk,
+ 'device_role': device_roles[1].pk,
+ 'name': 'Test Device 5',
+ 'site': sites[1].pk,
+ 'rack': racks[1].pk,
+ 'cluster': clusters[1].pk,
+ },
+ {
+ 'device_type': device_types[1].pk,
+ 'device_role': device_roles[1].pk,
+ 'name': 'Test Device 6',
+ 'site': sites[1].pk,
+ 'rack': racks[1].pk,
+ 'cluster': clusters[1].pk,
+ },
+ ]
def test_get_device_graphs(self):
+ """
+ Test retrieval of Graphs assigned to Devices.
+ """
+ ct = ContentType.objects.get_for_model(Device)
+ graphs = (
+ Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?device={{ obj.name }}&foo=1'),
+ Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?device={{ obj.name }}&foo=2'),
+ Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?device={{ obj.name }}&foo=3'),
+ )
+ Graph.objects.bulk_create(graphs)
- device_ct = ContentType.objects.get_for_model(Device)
- self.graph1 = Graph.objects.create(
- type=device_ct,
- name='Test Graph 1',
- source='http://example.com/graphs.py?device={{ obj.name }}&foo=1'
- )
- self.graph2 = Graph.objects.create(
- type=device_ct,
- name='Test Graph 2',
- source='http://example.com/graphs.py?device={{ obj.name }}&foo=2'
- )
- self.graph3 = Graph.objects.create(
- type=device_ct,
- name='Test Graph 3',
- source='http://example.com/graphs.py?device={{ obj.name }}&foo=3'
- )
-
- url = reverse('dcim-api:device-graphs', kwargs={'pk': self.device1.pk})
+ url = reverse('dcim-api:device-graphs', kwargs={'pk': Device.objects.first().pk})
response = self.client.get(url, **self.header)
self.assertEqual(len(response.data), 3)
- self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?device=Test Device 1&foo=1')
-
- def test_list_devices(self):
-
- url = reverse('dcim-api:device-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 4)
-
- def test_list_devices_brief(self):
-
- url = reverse('dcim-api:device-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['display_name', 'id', 'name', 'url']
- )
-
- def test_create_device(self):
-
- data = {
- 'device_type': self.devicetype1.pk,
- 'device_role': self.devicerole1.pk,
- 'name': 'Test Device 4',
- 'site': self.site1.pk,
- 'rack': self.rack1.pk,
- 'face': DeviceFaceChoices.FACE_FRONT,
- 'position': 1,
- 'cluster': self.cluster1.pk,
- }
-
- url = reverse('dcim-api:device-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Device.objects.count(), 5)
- device4 = Device.objects.get(pk=response.data['id'])
- self.assertEqual(device4.device_type_id, data['device_type'])
- self.assertEqual(device4.device_role_id, data['device_role'])
- self.assertEqual(device4.name, data['name'])
- self.assertEqual(device4.site.pk, data['site'])
- self.assertEqual(device4.cluster.pk, data['cluster'])
-
- def test_create_device_bulk(self):
-
- data = [
- {
- 'device_type': self.devicetype1.pk,
- 'device_role': self.devicerole1.pk,
- 'name': 'Test Device 4',
- 'site': self.site1.pk,
- },
- {
- 'device_type': self.devicetype1.pk,
- 'device_role': self.devicerole1.pk,
- 'name': 'Test Device 5',
- 'site': self.site1.pk,
- },
- {
- 'device_type': self.devicetype1.pk,
- 'device_role': self.devicerole1.pk,
- 'name': 'Test Device 6',
- 'site': self.site1.pk,
- },
- ]
-
- url = reverse('dcim-api:device-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Device.objects.count(), 7)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_device(self):
-
- interface = Interface.objects.create(name='Test Interface 1', device=self.device1)
- ip4_address = IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), interface=interface)
- ip6_address = IPAddress.objects.create(address=IPNetwork('2001:db8::1/64'), interface=interface)
-
- data = {
- 'device_type': self.devicetype2.pk,
- 'device_role': self.devicerole2.pk,
- 'name': 'Test Device X',
- 'site': self.site2.pk,
- 'primary_ip4': ip4_address.pk,
- 'primary_ip6': ip6_address.pk,
- }
-
- url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Device.objects.count(), 4)
- device1 = Device.objects.get(pk=response.data['id'])
- self.assertEqual(device1.device_type_id, data['device_type'])
- self.assertEqual(device1.device_role_id, data['device_role'])
- self.assertEqual(device1.name, data['name'])
- self.assertEqual(device1.site.pk, data['site'])
- self.assertEqual(device1.primary_ip4.pk, data['primary_ip4'])
- self.assertEqual(device1.primary_ip6.pk, data['primary_ip6'])
-
- def test_delete_device(self):
-
- url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Device.objects.count(), 3)
+ self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?device=Device 1&foo=1')
def test_config_context_included_by_default_in_list_view(self):
-
+ """
+ Check that config context data is included by default in the devices list.
+ """
url = reverse('dcim-api:device-list') + '?slug=device-with-context-data'
response = self.client.get(url, **self.header)
self.assertEqual(response.data['results'][0].get('config_context', {}).get('A'), 1)
def test_config_context_excluded(self):
-
+ """
+ Check that config context data can be excluded by passing ?exclude=config_context.
+ """
url = reverse('dcim-api:device-list') + '?exclude=config_context'
response = self.client.get(url, **self.header)
self.assertFalse('config_context' in response.data['results'][0])
def test_unique_name_per_site_constraint(self):
-
+ """
+ Check that creating a device with a duplicate name within a site fails.
+ """
+ device = Device.objects.first()
data = {
- 'device_type': self.devicetype1.pk,
- 'device_role': self.devicerole1.pk,
- 'name': 'Test Device 1',
- 'site': self.site1.pk,
+ 'device_type': device.device_type.pk,
+ 'device_role': device.device_role.pk,
+ 'site': device.site.pk,
+ 'name': device.name,
}
url = reverse('dcim-api:device-list')
@@ -2037,1401 +826,578 @@ class DeviceTest(APITestCase):
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
-class ConsolePortTest(APITestCase):
+class ConsolePortTest(APIViewTestCases.APIViewTestCase):
+ model = ConsolePort
+ brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ console_ports = (
+ ConsolePort(device=device, name='Console Port 1'),
+ ConsolePort(device=device, name='Console Port 2'),
+ ConsolePort(device=device, name='Console Port 3'),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.consoleport1 = ConsolePort.objects.create(device=self.device, name='Test Console Port 1')
- self.consoleport2 = ConsolePort.objects.create(device=self.device, name='Test Console Port 2')
- self.consoleport3 = ConsolePort.objects.create(device=self.device, name='Test Console Port 3')
+ ConsolePort.objects.bulk_create(console_ports)
- def test_get_consoleport(self):
-
- url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.consoleport1.name)
-
- def test_list_consoleports(self):
-
- url = reverse('dcim-api:consoleport-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_consoleports_brief(self):
-
- url = reverse('dcim-api:consoleport-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- )
-
- def test_create_consoleport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Console Port 4',
- }
-
- url = reverse('dcim-api:consoleport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsolePort.objects.count(), 4)
- consoleport4 = ConsolePort.objects.get(pk=response.data['id'])
- self.assertEqual(consoleport4.device_id, data['device'])
- self.assertEqual(consoleport4.name, data['name'])
-
- def test_create_consoleport_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
- 'name': 'Test Console Port 4',
+ 'device': device.pk,
+ 'name': 'Console Port 4',
},
{
- 'device': self.device.pk,
- 'name': 'Test Console Port 5',
+ 'device': device.pk,
+ 'name': 'Console Port 5',
},
{
- 'device': self.device.pk,
- 'name': 'Test Console Port 6',
+ 'device': device.pk,
+ 'name': 'Console Port 6',
},
]
- url = reverse('dcim-api:consoleport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsolePort.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_consoleport(self):
-
- consoleserverport = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 1')
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Console Port X',
- }
-
- url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ConsolePort.objects.count(), 3)
- consoleport1 = ConsolePort.objects.get(pk=response.data['id'])
- self.assertEqual(consoleport1.name, data['name'])
-
- def test_delete_consoleport(self):
-
- url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ConsolePort.objects.count(), 2)
-
def test_trace_consoleport(self):
-
+ """
+ Test tracing a ConsolePort cable.
+ """
+ consoleport = ConsolePort.objects.first()
peer_device = Device.objects.create(
site=Site.objects.first(),
device_type=DeviceType.objects.first(),
device_role=DeviceRole.objects.first(),
name='Peer Device'
)
- console_server_port = ConsoleServerPort.objects.create(
+ consoleserverport = ConsoleServerPort.objects.create(
device=peer_device,
name='Console Server Port 1'
)
- cable = Cable(termination_a=self.consoleport1, termination_b=console_server_port, label='Cable 1')
+ cable = Cable(termination_a=consoleport, termination_b=consoleserverport, label='Cable 1')
cable.save()
- url = reverse('dcim-api:consoleport-trace', kwargs={'pk': self.consoleport1.pk})
+ url = reverse('dcim-api:consoleport-trace', kwargs={'pk': consoleport.pk})
response = self.client.get(url, **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
segment1 = response.data[0]
- self.assertEqual(segment1[0]['name'], self.consoleport1.name)
+ self.assertEqual(segment1[0]['name'], consoleport.name)
self.assertEqual(segment1[1]['label'], cable.label)
- self.assertEqual(segment1[2]['name'], console_server_port.name)
+ self.assertEqual(segment1[2]['name'], consoleserverport.name)
-class ConsoleServerPortTest(APITestCase):
+class ConsoleServerPortTest(APIViewTestCases.APIViewTestCase):
+ model = ConsoleServerPort
+ brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ console_server_ports = (
+ ConsoleServerPort(device=device, name='Console Server Port 1'),
+ ConsoleServerPort(device=device, name='Console Server Port 2'),
+ ConsoleServerPort(device=device, name='Console Server Port 3'),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.consoleserverport1 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 1')
- self.consoleserverport2 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 2')
- self.consoleserverport3 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 3')
+ ConsoleServerPort.objects.bulk_create(console_server_ports)
- def test_get_consoleserverport(self):
-
- url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.consoleserverport1.name)
-
- def test_list_consoleserverports(self):
-
- url = reverse('dcim-api:consoleserverport-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_consoleserverports_brief(self):
-
- url = reverse('dcim-api:consoleserverport-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- )
-
- def test_create_consoleserverport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test CS Port 4',
- }
-
- url = reverse('dcim-api:consoleserverport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsoleServerPort.objects.count(), 4)
- consoleserverport4 = ConsoleServerPort.objects.get(pk=response.data['id'])
- self.assertEqual(consoleserverport4.device_id, data['device'])
- self.assertEqual(consoleserverport4.name, data['name'])
-
- def test_create_consoleserverport_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
- 'name': 'Test CS Port 4',
+ 'device': device.pk,
+ 'name': 'Console Server Port 4',
},
{
- 'device': self.device.pk,
- 'name': 'Test CS Port 5',
+ 'device': device.pk,
+ 'name': 'Console Server Port 5',
},
{
- 'device': self.device.pk,
- 'name': 'Test CS Port 6',
+ 'device': device.pk,
+ 'name': 'Console Server Port 6',
},
]
- url = reverse('dcim-api:consoleserverport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConsoleServerPort.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_consoleserverport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test CS Port X',
- }
-
- url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ConsoleServerPort.objects.count(), 3)
- consoleserverport1 = ConsoleServerPort.objects.get(pk=response.data['id'])
- self.assertEqual(consoleserverport1.name, data['name'])
-
- def test_delete_consoleserverport(self):
-
- url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ConsoleServerPort.objects.count(), 2)
-
def test_trace_consoleserverport(self):
-
+ """
+ Test tracing a ConsoleServerPort cable.
+ """
+ consoleserverport = ConsoleServerPort.objects.first()
peer_device = Device.objects.create(
site=Site.objects.first(),
device_type=DeviceType.objects.first(),
device_role=DeviceRole.objects.first(),
name='Peer Device'
)
- console_port = ConsolePort.objects.create(
+ consoleport = ConsolePort.objects.create(
device=peer_device,
name='Console Port 1'
)
- cable = Cable(termination_a=self.consoleserverport1, termination_b=console_port, label='Cable 1')
+ cable = Cable(termination_a=consoleserverport, termination_b=consoleport, label='Cable 1')
cable.save()
- url = reverse('dcim-api:consoleserverport-trace', kwargs={'pk': self.consoleserverport1.pk})
+ url = reverse('dcim-api:consoleserverport-trace', kwargs={'pk': consoleserverport.pk})
response = self.client.get(url, **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
segment1 = response.data[0]
- self.assertEqual(segment1[0]['name'], self.consoleserverport1.name)
+ self.assertEqual(segment1[0]['name'], consoleserverport.name)
self.assertEqual(segment1[1]['label'], cable.label)
- self.assertEqual(segment1[2]['name'], console_port.name)
+ self.assertEqual(segment1[2]['name'], consoleport.name)
-class PowerPortTest(APITestCase):
+class PowerPortTest(APIViewTestCases.APIViewTestCase):
+ model = PowerPort
+ brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ power_ports = (
+ PowerPort(device=device, name='Power Port 1'),
+ PowerPort(device=device, name='Power Port 2'),
+ PowerPort(device=device, name='Power Port 3'),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.powerport1 = PowerPort.objects.create(device=self.device, name='Test Power Port 1')
- self.powerport2 = PowerPort.objects.create(device=self.device, name='Test Power Port 2')
- self.powerport3 = PowerPort.objects.create(device=self.device, name='Test Power Port 3')
+ PowerPort.objects.bulk_create(power_ports)
- def test_get_powerport(self):
-
- url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.powerport1.name)
-
- def test_list_powerports(self):
-
- url = reverse('dcim-api:powerport-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_powerports_brief(self):
-
- url = reverse('dcim-api:powerport-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- )
-
- def test_create_powerport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Power Port 4',
- }
-
- url = reverse('dcim-api:powerport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPort.objects.count(), 4)
- powerport4 = PowerPort.objects.get(pk=response.data['id'])
- self.assertEqual(powerport4.device_id, data['device'])
- self.assertEqual(powerport4.name, data['name'])
-
- def test_create_powerport_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
- 'name': 'Test Power Port 4',
+ 'device': device.pk,
+ 'name': 'Power Port 4',
},
{
- 'device': self.device.pk,
- 'name': 'Test Power Port 5',
+ 'device': device.pk,
+ 'name': 'Power Port 5',
},
{
- 'device': self.device.pk,
- 'name': 'Test Power Port 6',
+ 'device': device.pk,
+ 'name': 'Power Port 6',
},
]
- url = reverse('dcim-api:powerport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPort.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_powerport(self):
-
- poweroutlet = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 1')
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Power Port X',
- }
-
- url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerPort.objects.count(), 3)
- powerport1 = PowerPort.objects.get(pk=response.data['id'])
- self.assertEqual(powerport1.name, data['name'])
-
- def test_delete_powerport(self):
-
- url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerPort.objects.count(), 2)
-
def test_trace_powerport(self):
-
+ """
+ Test tracing a PowerPort cable.
+ """
+ powerport = PowerPort.objects.first()
peer_device = Device.objects.create(
site=Site.objects.first(),
device_type=DeviceType.objects.first(),
device_role=DeviceRole.objects.first(),
name='Peer Device'
)
- power_outlet = PowerOutlet.objects.create(
+ poweroutlet = PowerOutlet.objects.create(
device=peer_device,
name='Power Outlet 1'
)
- cable = Cable(termination_a=self.powerport1, termination_b=power_outlet, label='Cable 1')
+ cable = Cable(termination_a=powerport, termination_b=poweroutlet, label='Cable 1')
cable.save()
- url = reverse('dcim-api:powerport-trace', kwargs={'pk': self.powerport1.pk})
+ url = reverse('dcim-api:powerport-trace', kwargs={'pk': powerport.pk})
response = self.client.get(url, **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
segment1 = response.data[0]
- self.assertEqual(segment1[0]['name'], self.powerport1.name)
+ self.assertEqual(segment1[0]['name'], powerport.name)
self.assertEqual(segment1[1]['label'], cable.label)
- self.assertEqual(segment1[2]['name'], power_outlet.name)
+ self.assertEqual(segment1[2]['name'], poweroutlet.name)
-class PowerOutletTest(APITestCase):
+class PowerOutletTest(APIViewTestCases.APIViewTestCase):
+ model = PowerOutlet
+ brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ power_outlets = (
+ PowerOutlet(device=device, name='Power Outlet 1'),
+ PowerOutlet(device=device, name='Power Outlet 2'),
+ PowerOutlet(device=device, name='Power Outlet 3'),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.poweroutlet1 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 1')
- self.poweroutlet2 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 2')
- self.poweroutlet3 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 3')
+ PowerOutlet.objects.bulk_create(power_outlets)
- def test_get_poweroutlet(self):
-
- url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.poweroutlet1.name)
-
- def test_list_poweroutlets(self):
-
- url = reverse('dcim-api:poweroutlet-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_poweroutlets_brief(self):
-
- url = reverse('dcim-api:poweroutlet-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- )
-
- def test_create_poweroutlet(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Power Outlet 4',
- }
-
- url = reverse('dcim-api:poweroutlet-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerOutlet.objects.count(), 4)
- poweroutlet4 = PowerOutlet.objects.get(pk=response.data['id'])
- self.assertEqual(poweroutlet4.device_id, data['device'])
- self.assertEqual(poweroutlet4.name, data['name'])
-
- def test_create_poweroutlet_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
- 'name': 'Test Power Outlet 4',
+ 'device': device.pk,
+ 'name': 'Power Outlet 4',
},
{
- 'device': self.device.pk,
- 'name': 'Test Power Outlet 5',
+ 'device': device.pk,
+ 'name': 'Power Outlet 5',
},
{
- 'device': self.device.pk,
- 'name': 'Test Power Outlet 6',
+ 'device': device.pk,
+ 'name': 'Power Outlet 6',
},
]
- url = reverse('dcim-api:poweroutlet-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerOutlet.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_poweroutlet(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Power Outlet X',
- }
-
- url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerOutlet.objects.count(), 3)
- poweroutlet1 = PowerOutlet.objects.get(pk=response.data['id'])
- self.assertEqual(poweroutlet1.name, data['name'])
-
- def test_delete_poweroutlet(self):
-
- url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerOutlet.objects.count(), 2)
-
def test_trace_poweroutlet(self):
-
+ """
+ Test tracing a PowerOutlet cable.
+ """
+ poweroutlet = PowerOutlet.objects.first()
peer_device = Device.objects.create(
site=Site.objects.first(),
device_type=DeviceType.objects.first(),
device_role=DeviceRole.objects.first(),
name='Peer Device'
)
- power_port = PowerPort.objects.create(
+ powerport = PowerPort.objects.create(
device=peer_device,
name='Power Port 1'
)
- cable = Cable(termination_a=self.poweroutlet1, termination_b=power_port, label='Cable 1')
+ cable = Cable(termination_a=poweroutlet, termination_b=powerport, label='Cable 1')
cable.save()
- url = reverse('dcim-api:poweroutlet-trace', kwargs={'pk': self.poweroutlet1.pk})
+ url = reverse('dcim-api:poweroutlet-trace', kwargs={'pk': poweroutlet.pk})
response = self.client.get(url, **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
segment1 = response.data[0]
- self.assertEqual(segment1[0]['name'], self.poweroutlet1.name)
+ self.assertEqual(segment1[0]['name'], poweroutlet.name)
self.assertEqual(segment1[1]['label'], cable.label)
- self.assertEqual(segment1[2]['name'], power_port.name)
+ self.assertEqual(segment1[2]['name'], powerport.name)
-class InterfaceTest(APITestCase):
+class InterfaceTest(APIViewTestCases.APIViewTestCase):
+ model = Interface
+ brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ interfaces = (
+ Interface(device=device, name='Interface 1', type='1000base-t'),
+ Interface(device=device, name='Interface 2', type='1000base-t'),
+ Interface(device=device, name='Interface 3', type='1000base-t'),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
+ Interface.objects.bulk_create(interfaces)
+
+ vlans = (
+ VLAN(name='VLAN 1', vid=1),
+ VLAN(name='VLAN 2', vid=2),
+ VLAN(name='VLAN 3', vid=3),
)
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.interface1 = Interface.objects.create(device=self.device, name='Test Interface 1', type='1000base-t')
- self.interface2 = Interface.objects.create(device=self.device, name='Test Interface 2', type='1000base-t')
- self.interface3 = Interface.objects.create(device=self.device, name='Test Interface 3', type='1000base-t')
+ VLAN.objects.bulk_create(vlans)
- self.vlan1 = VLAN.objects.create(name="Test VLAN 1", vid=1)
- self.vlan2 = VLAN.objects.create(name="Test VLAN 2", vid=2)
- self.vlan3 = VLAN.objects.create(name="Test VLAN 3", vid=3)
-
- def test_get_interface(self):
-
- url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(response.data['name'], self.interface1.name)
+ cls.create_data = [
+ {
+ 'device': device.pk,
+ 'name': 'Interface 4',
+ 'type': '1000base-t',
+ 'mode': InterfaceModeChoices.MODE_TAGGED,
+ 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
+ 'untagged_vlan': vlans[2].pk,
+ },
+ {
+ 'device': device.pk,
+ 'name': 'Interface 5',
+ 'type': '1000base-t',
+ 'mode': InterfaceModeChoices.MODE_TAGGED,
+ 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
+ 'untagged_vlan': vlans[2].pk,
+ },
+ {
+ 'device': device.pk,
+ 'name': 'Interface 6',
+ 'type': '1000base-t',
+ 'mode': InterfaceModeChoices.MODE_TAGGED,
+ 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
+ 'untagged_vlan': vlans[2].pk,
+ },
+ ]
def test_get_interface_graphs(self):
+ """
+ Test retrieval of Graphs assigned to Devices.
+ """
+ ct = ContentType.objects.get_for_model(Interface)
+ graphs = (
+ Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1'),
+ Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2'),
+ Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3'),
+ )
+ Graph.objects.bulk_create(graphs)
- interface_ct = ContentType.objects.get_for_model(Interface)
- self.graph1 = Graph.objects.create(
- type=interface_ct,
- name='Test Graph 1',
- source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1'
- )
- self.graph2 = Graph.objects.create(
- type=interface_ct,
- name='Test Graph 2',
- source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2'
- )
- self.graph3 = Graph.objects.create(
- type=interface_ct,
- name='Test Graph 3',
- source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3'
- )
-
- url = reverse('dcim-api:interface-graphs', kwargs={'pk': self.interface1.pk})
+ url = reverse('dcim-api:interface-graphs', kwargs={'pk': Interface.objects.first().pk})
response = self.client.get(url, **self.header)
self.assertEqual(len(response.data), 3)
- self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Test Interface 1&foo=1')
-
- def test_list_interfaces(self):
-
- url = reverse('dcim-api:interface-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_interfaces_brief(self):
-
- url = reverse('dcim-api:interface-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'connection_status', 'device', 'id', 'name', 'url']
- )
-
- def test_create_interface(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Interface 4',
- 'type': '1000base-t',
- }
-
- url = reverse('dcim-api:interface-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Interface.objects.count(), 4)
- interface4 = Interface.objects.get(pk=response.data['id'])
- self.assertEqual(interface4.device_id, data['device'])
- self.assertEqual(interface4.name, data['name'])
-
- def test_create_interface_with_802_1q(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Interface 4',
- 'type': '1000base-t',
- 'mode': InterfaceModeChoices.MODE_TAGGED,
- 'untagged_vlan': self.vlan3.id,
- 'tagged_vlans': [self.vlan1.id, self.vlan2.id],
- }
-
- url = reverse('dcim-api:interface-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Interface.objects.count(), 4)
- self.assertEqual(response.data['device']['id'], data['device'])
- self.assertEqual(response.data['name'], data['name'])
- self.assertEqual(response.data['untagged_vlan']['id'], data['untagged_vlan'])
- self.assertEqual([v['id'] for v in response.data['tagged_vlans']], data['tagged_vlans'])
-
- def test_create_interface_bulk(self):
-
- data = [
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 4',
- 'type': '1000base-t',
- },
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 5',
- 'type': '1000base-t',
- },
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 6',
- 'type': '1000base-t',
- },
- ]
-
- url = reverse('dcim-api:interface-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Interface.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_create_interface_802_1q_bulk(self):
-
- data = [
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 4',
- 'type': '1000base-t',
- 'mode': InterfaceModeChoices.MODE_TAGGED,
- 'untagged_vlan': self.vlan2.id,
- 'tagged_vlans': [self.vlan1.id],
- },
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 5',
- 'type': '1000base-t',
- 'mode': InterfaceModeChoices.MODE_TAGGED,
- 'untagged_vlan': self.vlan2.id,
- 'tagged_vlans': [self.vlan1.id],
- },
- {
- 'device': self.device.pk,
- 'name': 'Test Interface 6',
- 'type': '1000base-t',
- 'mode': InterfaceModeChoices.MODE_TAGGED,
- 'untagged_vlan': self.vlan2.id,
- 'tagged_vlans': [self.vlan1.id],
- },
- ]
-
- url = reverse('dcim-api:interface-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Interface.objects.count(), 6)
- for i in range(0, 3):
- self.assertEqual(response.data[i]['name'], data[i]['name'])
- self.assertEqual([v['id'] for v in response.data[i]['tagged_vlans']], data[i]['tagged_vlans'])
- self.assertEqual(response.data[i]['untagged_vlan']['id'], data[i]['untagged_vlan'])
-
- def test_update_interface(self):
-
- lag_interface = Interface.objects.create(
- device=self.device, name='Test LAG Interface', type=InterfaceTypeChoices.TYPE_LAG
- )
-
- data = {
- 'device': self.device.pk,
- 'name': 'Test Interface X',
- 'type': '1000base-x-gbic',
- 'lag': lag_interface.pk,
- }
-
- url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Interface.objects.count(), 4)
- interface1 = Interface.objects.get(pk=response.data['id'])
- self.assertEqual(interface1.name, data['name'])
- self.assertEqual(interface1.lag_id, data['lag'])
-
- def test_delete_interface(self):
-
- url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Interface.objects.count(), 2)
+ self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Interface 1&foo=1')
-class FrontPortTest(APITestCase):
+class FrontPortTest(APIViewTestCases.APIViewTestCase):
+ model = FrontPort
+ brief_fields = ['cable', 'device', 'id', 'name', 'url']
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ rear_ports = (
+ RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 4', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 5', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 6', type=PortTypeChoices.TYPE_8P8C),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
+ RearPort.objects.bulk_create(rear_ports)
+
+ front_ports = (
+ FrontPort(device=device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]),
+ FrontPort(device=device, name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]),
+ FrontPort(device=device, name='Front Port 3', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[2]),
)
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- rear_ports = RearPort.objects.bulk_create((
- RearPort(device=self.device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C),
- RearPort(device=self.device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C),
- RearPort(device=self.device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C),
- RearPort(device=self.device, name='Rear Port 4', type=PortTypeChoices.TYPE_8P8C),
- RearPort(device=self.device, name='Rear Port 5', type=PortTypeChoices.TYPE_8P8C),
- RearPort(device=self.device, name='Rear Port 6', type=PortTypeChoices.TYPE_8P8C),
- ))
- self.frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0])
- self.frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1])
- self.frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 3', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[2])
+ FrontPort.objects.bulk_create(front_ports)
- def test_get_frontport(self):
-
- url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.frontport1.name)
-
- def test_list_frontports(self):
-
- url = reverse('dcim-api:frontport-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_frontports_brief(self):
-
- url = reverse('dcim-api:frontport-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'device', 'id', 'name', 'url']
- )
-
- def test_create_frontport(self):
-
- rear_port = RearPort.objects.get(name='Rear Port 4')
- data = {
- 'device': self.device.pk,
- 'name': 'Front Port 4',
- 'type': PortTypeChoices.TYPE_8P8C,
- 'rear_port': rear_port.pk,
- 'rear_port_position': 1,
- }
-
- url = reverse('dcim-api:frontport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(FrontPort.objects.count(), 4)
- frontport4 = FrontPort.objects.get(pk=response.data['id'])
- self.assertEqual(frontport4.device_id, data['device'])
- self.assertEqual(frontport4.name, data['name'])
-
- def test_create_frontport_bulk(self):
-
- rear_ports = RearPort.objects.filter(frontports__isnull=True)
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Front Port 4',
'type': PortTypeChoices.TYPE_8P8C,
- 'rear_port': rear_ports[0].pk,
+ 'rear_port': rear_ports[3].pk,
'rear_port_position': 1,
},
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Front Port 5',
'type': PortTypeChoices.TYPE_8P8C,
- 'rear_port': rear_ports[1].pk,
+ 'rear_port': rear_ports[4].pk,
'rear_port_position': 1,
},
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Front Port 6',
'type': PortTypeChoices.TYPE_8P8C,
- 'rear_port': rear_ports[2].pk,
+ 'rear_port': rear_ports[5].pk,
'rear_port_position': 1,
},
]
- url = reverse('dcim-api:frontport-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(FrontPort.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class RearPortTest(APIViewTestCases.APIViewTestCase):
+ model = RearPort
+ brief_fields = ['cable', 'device', 'id', 'name', 'url']
- def test_update_frontport(self):
-
- rear_port = RearPort.objects.get(name='Rear Port 4')
- data = {
- 'device': self.device.pk,
- 'name': 'Front Port X',
- 'type': PortTypeChoices.TYPE_110_PUNCH,
- 'rear_port': rear_port.pk,
- 'rear_port_position': 1,
- }
-
- url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(FrontPort.objects.count(), 3)
- frontport1 = FrontPort.objects.get(pk=response.data['id'])
- self.assertEqual(frontport1.name, data['name'])
- self.assertEqual(frontport1.type, data['type'])
- self.assertEqual(frontport1.rear_port, rear_port)
-
- def test_delete_frontport(self):
-
- url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(FrontPort.objects.count(), 2)
-
-
-class RearPortTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
+
+ rear_ports = (
+ RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C),
+ RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.rearport1 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 1')
- self.rearport3 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 2')
- self.rearport1 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 3')
+ RearPort.objects.bulk_create(rear_ports)
- def test_get_rearport(self):
-
- url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.rearport1.name)
-
- def test_list_rearports(self):
-
- url = reverse('dcim-api:rearport-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_rearports_brief(self):
-
- url = reverse('dcim-api:rearport-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cable', 'device', 'id', 'name', 'url']
- )
-
- def test_create_rearport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Front Port 4',
- 'type': PortTypeChoices.TYPE_8P8C,
- }
-
- url = reverse('dcim-api:rearport-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RearPort.objects.count(), 4)
- rearport4 = RearPort.objects.get(pk=response.data['id'])
- self.assertEqual(rearport4.device_id, data['device'])
- self.assertEqual(rearport4.name, data['name'])
-
- def test_create_rearport_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Rear Port 4',
'type': PortTypeChoices.TYPE_8P8C,
},
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Rear Port 5',
'type': PortTypeChoices.TYPE_8P8C,
},
{
- 'device': self.device.pk,
+ 'device': device.pk,
'name': 'Rear Port 6',
'type': PortTypeChoices.TYPE_8P8C,
},
]
- url = reverse('dcim-api:rearport-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RearPort.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class DeviceBayTest(APIViewTestCases.APIViewTestCase):
+ model = DeviceBay
+ brief_fields = ['device', 'id', 'name', 'url']
- def test_update_rearport(self):
-
- data = {
- 'device': self.device.pk,
- 'name': 'Front Port X',
- 'type': PortTypeChoices.TYPE_110_PUNCH
- }
-
- url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(RearPort.objects.count(), 3)
- rearport1 = RearPort.objects.get(pk=response.data['id'])
- self.assertEqual(rearport1.name, data['name'])
- self.assertEqual(rearport1.type, data['type'])
-
- def test_delete_rearport(self):
-
- url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(RearPort.objects.count(), 2)
-
-
-class DeviceBayTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+ @classmethod
+ def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- self.devicetype1 = DeviceType.objects.create(
- manufacturer=manufacturer, model='Parent Device Type', slug='parent-device-type',
- subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+
+ device_types = (
+ DeviceType(
+ manufacturer=manufacturer,
+ model='Device Type 1',
+ slug='device-type-1',
+ subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
+ ),
+ DeviceType(
+ manufacturer=manufacturer,
+ model='Device Type 2',
+ slug='device-type-2',
+ subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
+ ),
)
- self.devicetype2 = DeviceType.objects.create(
- manufacturer=manufacturer, model='Child Device Type', slug='child-device-type',
- subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
+ DeviceType.objects.bulk_create(device_types)
+
+ devices = (
+ Device(device_type=device_types[0], device_role=devicerole, name='Device 1', site=site),
+ Device(device_type=device_types[1], device_role=devicerole, name='Device 2', site=site),
+ Device(device_type=device_types[1], device_role=devicerole, name='Device 3', site=site),
+ Device(device_type=device_types[1], device_role=devicerole, name='Device 4', site=site),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
+ Device.objects.bulk_create(devices)
+
+ device_bays = (
+ DeviceBay(device=devices[0], name='Device Bay 1'),
+ DeviceBay(device=devices[0], name='Device Bay 2'),
+ DeviceBay(device=devices[0], name='Device Bay 3'),
)
- self.parent_device = Device.objects.create(
- device_type=self.devicetype1, device_role=devicerole, name='Parent Device 1', site=site
- )
- self.child_device = Device.objects.create(
- device_type=self.devicetype2, device_role=devicerole, name='Child Device 1', site=site
- )
- self.devicebay1 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 1')
- self.devicebay2 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 2')
- self.devicebay3 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 3')
+ DeviceBay.objects.bulk_create(device_bays)
- def test_get_devicebay(self):
-
- url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.devicebay1.name)
-
- def test_list_devicebays(self):
-
- url = reverse('dcim-api:devicebay-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_devicebays_brief(self):
-
- url = reverse('dcim-api:devicebay-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['device', 'id', 'name', 'url']
- )
-
- def test_create_devicebay(self):
-
- data = {
- 'device': self.parent_device.pk,
- 'name': 'Test Device Bay 4',
- 'installed_device': self.child_device.pk,
- }
-
- url = reverse('dcim-api:devicebay-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceBay.objects.count(), 4)
- devicebay4 = DeviceBay.objects.get(pk=response.data['id'])
- self.assertEqual(devicebay4.device_id, data['device'])
- self.assertEqual(devicebay4.name, data['name'])
- self.assertEqual(devicebay4.installed_device_id, data['installed_device'])
-
- def test_create_devicebay_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.parent_device.pk,
- 'name': 'Test Device Bay 4',
+ 'device': devices[0].pk,
+ 'name': 'Device Bay 4',
+ 'installed_device': devices[1].pk,
},
{
- 'device': self.parent_device.pk,
- 'name': 'Test Device Bay 5',
+ 'device': devices[0].pk,
+ 'name': 'Device Bay 5',
+ 'installed_device': devices[2].pk,
},
{
- 'device': self.parent_device.pk,
- 'name': 'Test Device Bay 6',
+ 'device': devices[0].pk,
+ 'name': 'Device Bay 6',
+ 'installed_device': devices[3].pk,
},
]
- url = reverse('dcim-api:devicebay-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(DeviceBay.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class InventoryItemTest(APIViewTestCases.APIViewTestCase):
+ model = InventoryItem
+ brief_fields = ['device', 'id', 'name', 'url']
- def test_update_devicebay(self):
+ @classmethod
+ def setUpTestData(cls):
+ manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
+ device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
- data = {
- 'device': self.parent_device.pk,
- 'name': 'Test Device Bay X',
- 'installed_device': self.child_device.pk,
- }
-
- url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(DeviceBay.objects.count(), 3)
- devicebay1 = DeviceBay.objects.get(pk=response.data['id'])
- self.assertEqual(devicebay1.name, data['name'])
- self.assertEqual(devicebay1.installed_device_id, data['installed_device'])
-
- def test_delete_devicebay(self):
-
- url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(DeviceBay.objects.count(), 2)
-
-
-class InventoryItemTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ inventory_items = (
+ InventoryItem(device=device, name='Inventory Item 1', manufacturer=manufacturer),
+ InventoryItem(device=device, name='Inventory Item 2', manufacturer=manufacturer),
+ InventoryItem(device=device, name='Inventory Item 3', manufacturer=manufacturer),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.inventoryitem1 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 1')
- self.inventoryitem2 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 2')
- self.inventoryitem3 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 3')
+ InventoryItem.objects.bulk_create(inventory_items)
- def test_get_inventoryitem(self):
-
- url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.inventoryitem1.name)
-
- def test_list_inventoryitems(self):
-
- url = reverse('dcim-api:inventoryitem-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_inventoryitem(self):
-
- data = {
- 'device': self.device.pk,
- 'parent': self.inventoryitem1.pk,
- 'name': 'Test Inventory Item 4',
- 'manufacturer': self.manufacturer.pk,
- }
-
- url = reverse('dcim-api:inventoryitem-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(InventoryItem.objects.count(), 4)
- inventoryitem4 = InventoryItem.objects.get(pk=response.data['id'])
- self.assertEqual(inventoryitem4.device_id, data['device'])
- self.assertEqual(inventoryitem4.parent_id, data['parent'])
- self.assertEqual(inventoryitem4.name, data['name'])
- self.assertEqual(inventoryitem4.manufacturer_id, data['manufacturer'])
-
- def test_create_inventoryitem_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device.pk,
- 'parent': self.inventoryitem1.pk,
- 'name': 'Test Inventory Item 4',
- 'manufacturer': self.manufacturer.pk,
+ 'device': device.pk,
+ 'name': 'Inventory Item 4',
+ 'manufacturer': manufacturer.pk,
},
{
- 'device': self.device.pk,
- 'parent': self.inventoryitem1.pk,
- 'name': 'Test Inventory Item 5',
- 'manufacturer': self.manufacturer.pk,
+ 'device': device.pk,
+ 'name': 'Inventory Item 5',
+ 'manufacturer': manufacturer.pk,
},
{
- 'device': self.device.pk,
- 'parent': self.inventoryitem1.pk,
- 'name': 'Test Inventory Item 6',
- 'manufacturer': self.manufacturer.pk,
+ 'device': device.pk,
+ 'name': 'Inventory Item 6',
+ 'manufacturer': manufacturer.pk,
},
]
- url = reverse('dcim-api:inventoryitem-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(InventoryItem.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class CableTest(APIViewTestCases.APIViewTestCase):
+ model = Cable
+ brief_fields = ['id', 'label', 'url']
- def test_update_inventoryitem(self):
+ # TODO: Allow updating cable terminations
+ test_update_object = None
- data = {
- 'device': self.device.pk,
- 'parent': self.inventoryitem1.pk,
- 'name': 'Test Inventory Item X',
- 'manufacturer': self.manufacturer.pk,
- }
+ @classmethod
+ def setUpTestData(cls):
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1', color='ff0000')
- url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(InventoryItem.objects.count(), 3)
- inventoryitem1 = InventoryItem.objects.get(pk=response.data['id'])
- self.assertEqual(inventoryitem1.device_id, data['device'])
- self.assertEqual(inventoryitem1.parent_id, data['parent'])
- self.assertEqual(inventoryitem1.name, data['name'])
- self.assertEqual(inventoryitem1.manufacturer_id, data['manufacturer'])
-
- def test_delete_inventoryitem(self):
-
- url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(InventoryItem.objects.count(), 2)
-
-
-class CableTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(
- manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1'
+ devices = (
+ Device(device_type=devicetype, device_role=devicerole, name='Device 1', site=site),
+ Device(device_type=devicetype, device_role=devicerole, name='Device 2', site=site),
)
- devicerole = DeviceRole.objects.create(
- name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
- )
- self.device1 = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
- )
- self.device2 = Device.objects.create(
- device_type=devicetype, device_role=devicerole, name='Test Device 2', site=site
- )
- for device in [self.device1, self.device2]:
+ Device.objects.bulk_create(devices)
+
+ interfaces = []
+ for device in devices:
for i in range(0, 10):
- Interface(device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED, name='eth{}'.format(i)).save()
+ interfaces.append(Interface(device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED, name=f'eth{i}'))
+ Interface.objects.bulk_create(interfaces)
- self.cable1 = Cable(
- termination_a=self.device1.interfaces.get(name='eth0'),
- termination_b=self.device2.interfaces.get(name='eth0'),
- label='Test Cable 1'
+ cables = (
+ Cable(termination_a=interfaces[0], termination_b=interfaces[10], label='Cable 1'),
+ Cable(termination_a=interfaces[1], termination_b=interfaces[11], label='Cable 2'),
+ Cable(termination_a=interfaces[2], termination_b=interfaces[12], label='Cable 3'),
)
- self.cable1.save()
- self.cable2 = Cable(
- termination_a=self.device1.interfaces.get(name='eth1'),
- termination_b=self.device2.interfaces.get(name='eth1'),
- label='Test Cable 2'
- )
- self.cable2.save()
- self.cable3 = Cable(
- termination_a=self.device1.interfaces.get(name='eth2'),
- termination_b=self.device2.interfaces.get(name='eth2'),
- label='Test Cable 3'
- )
- self.cable3.save()
+ for cable in cables:
+ cable.save()
- def test_get_cable(self):
-
- url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['id'], self.cable1.pk)
-
- def test_list_cables(self):
-
- url = reverse('dcim-api:cable-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_cable(self):
-
- interface_a = self.device1.interfaces.get(name='eth3')
- interface_b = self.device2.interfaces.get(name='eth3')
- data = {
- 'termination_a_type': 'dcim.interface',
- 'termination_a_id': interface_a.pk,
- 'termination_b_type': 'dcim.interface',
- 'termination_b_id': interface_b.pk,
- 'status': CableStatusChoices.STATUS_PLANNED,
- 'label': 'Test Cable 4',
- }
-
- url = reverse('dcim-api:cable-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Cable.objects.count(), 4)
- cable4 = Cable.objects.get(pk=response.data['id'])
- self.assertEqual(cable4.termination_a, interface_a)
- self.assertEqual(cable4.termination_b, interface_b)
- self.assertEqual(cable4.status, data['status'])
- self.assertEqual(cable4.label, data['label'])
-
- def test_create_cable_bulk(self):
-
- data = [
+ cls.create_data = [
{
'termination_a_type': 'dcim.interface',
- 'termination_a_id': self.device1.interfaces.get(name='eth3').pk,
+ 'termination_a_id': interfaces[4].pk,
'termination_b_type': 'dcim.interface',
- 'termination_b_id': self.device2.interfaces.get(name='eth3').pk,
- 'label': 'Test Cable 4',
+ 'termination_b_id': interfaces[14].pk,
+ 'label': 'Cable 4',
},
{
'termination_a_type': 'dcim.interface',
- 'termination_a_id': self.device1.interfaces.get(name='eth4').pk,
+ 'termination_a_id': interfaces[5].pk,
'termination_b_type': 'dcim.interface',
- 'termination_b_id': self.device2.interfaces.get(name='eth4').pk,
- 'label': 'Test Cable 5',
+ 'termination_b_id': interfaces[15].pk,
+ 'label': 'Cable 5',
},
{
'termination_a_type': 'dcim.interface',
- 'termination_a_id': self.device1.interfaces.get(name='eth5').pk,
+ 'termination_a_id': interfaces[6].pk,
'termination_b_type': 'dcim.interface',
- 'termination_b_id': self.device2.interfaces.get(name='eth5').pk,
- 'label': 'Test Cable 6',
+ 'termination_b_id': interfaces[16].pk,
+ 'label': 'Cable 6',
},
]
- url = reverse('dcim-api:cable-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Cable.objects.count(), 6)
- self.assertEqual(response.data[0]['label'], data[0]['label'])
- self.assertEqual(response.data[1]['label'], data[1]['label'])
- self.assertEqual(response.data[2]['label'], data[2]['label'])
-
- def test_update_cable(self):
-
- data = {
- 'label': 'Test Cable X',
- 'status': CableStatusChoices.STATUS_CONNECTED,
- }
-
- url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk})
- response = self.client.patch(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Cable.objects.count(), 3)
- cable1 = Cable.objects.get(pk=response.data['id'])
- self.assertEqual(cable1.status, data['status'])
- self.assertEqual(cable1.label, data['label'])
-
- def test_delete_cable(self):
-
- url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Cable.objects.count(), 2)
-
class ConnectionTest(APITestCase):
@@ -3839,426 +1805,159 @@ class ConnectedDeviceTest(APITestCase):
self.assertEqual(response.data['name'], self.device1.name)
-class VirtualChassisTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
+class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
+ model = VirtualChassis
+ brief_fields = ['id', 'master', 'member_count', 'url']
+ @classmethod
+ def setUpTestData(cls):
site = Site.objects.create(name='Test Site', slug='test-site')
- manufacturer = Manufacturer.objects.create(name='Test Manufacturer', slug='test-manufacturer')
- device_type = DeviceType.objects.create(
- manufacturer=manufacturer, model='Test Device Type', slug='test-device-type'
- )
- device_role = DeviceRole.objects.create(
- name='Test Device Role', slug='test-device-role', color='ff0000'
- )
+ manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type', slug='device-type')
+ devicerole = DeviceRole.objects.create(name='Device Role', slug='device-role', color='ff0000')
- # Create 9 member Devices with 12 interfaces each
- self.device1 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch1', site=site
+ devices = (
+ Device(name='Device 1', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 2', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 3', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 4', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 5', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 6', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 7', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 8', device_type=devicetype, device_role=devicerole, site=site),
+ Device(name='Device 9', device_type=devicetype, device_role=devicerole, site=site),
)
- self.device2 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch2', site=site
- )
- self.device3 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch3', site=site
- )
- self.device4 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch4', site=site
- )
- self.device5 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch5', site=site
- )
- self.device6 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch6', site=site
- )
- self.device7 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch7', site=site
- )
- self.device8 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch8', site=site
- )
- self.device9 = Device.objects.create(
- device_type=device_type, device_role=device_role, name='StackSwitch9', site=site
- )
- for i in range(0, 13):
- Interface.objects.create(device=self.device1, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device2, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device3, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device4, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device5, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device6, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device7, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device8, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
- for i in range(0, 13):
- Interface.objects.create(device=self.device9, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED)
+ Device.objects.bulk_create(devices)
+
+ # Create 12 interfaces per device
+ interfaces = []
+ for i, device in enumerate(devices):
+ for j in range(0, 13):
+ interfaces.append(
+ # Interface name starts with parent device's position in VC; e.g. 1/1, 1/2, 1/3...
+ Interface(device=device, name=f'{i%3+1}/{j}', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
+ )
+ Interface.objects.bulk_create(interfaces)
# Create two VirtualChassis with three members each
- self.vc1 = VirtualChassis.objects.create(master=self.device1, domain='test-domain-1')
- Device.objects.filter(pk=self.device2.pk).update(virtual_chassis=self.vc1, vc_position=2)
- Device.objects.filter(pk=self.device3.pk).update(virtual_chassis=self.vc1, vc_position=3)
- self.vc2 = VirtualChassis.objects.create(master=self.device4, domain='test-domain-2')
- Device.objects.filter(pk=self.device5.pk).update(virtual_chassis=self.vc2, vc_position=2)
- Device.objects.filter(pk=self.device6.pk).update(virtual_chassis=self.vc2, vc_position=3)
-
- def test_get_virtualchassis(self):
-
- url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['domain'], self.vc1.domain)
-
- def test_list_virtualchassis(self):
-
- url = reverse('dcim-api:virtualchassis-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 2)
-
- def test_list_virtualchassis_brief(self):
-
- url = reverse('dcim-api:virtualchassis-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'master', 'member_count', 'url']
+ virtual_chassis = (
+ VirtualChassis(master=devices[0], domain='domain-1'),
+ VirtualChassis(master=devices[3], domain='domain-2'),
)
+ VirtualChassis.objects.bulk_create(virtual_chassis)
+ Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis[0], vc_position=2)
+ Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=virtual_chassis[0], vc_position=3)
+ Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=virtual_chassis[1], vc_position=2)
+ Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[1], vc_position=3)
- def test_create_virtualchassis(self):
-
- data = {
- 'master': self.device7.pk,
- 'domain': 'test-domain-3',
+ cls.update_data = {
+ 'master': devices[1].pk,
+ 'domain': 'domain-x',
}
- url = reverse('dcim-api:virtualchassis-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VirtualChassis.objects.count(), 3)
- vc3 = VirtualChassis.objects.get(pk=response.data['id'])
- self.assertEqual(vc3.master.pk, data['master'])
- self.assertEqual(vc3.domain, data['domain'])
-
- # Verify that the master device was automatically assigned to the VC
- self.assertTrue(Device.objects.filter(pk=vc3.master.pk, virtual_chassis=vc3.pk).exists())
-
- def test_create_virtualchassis_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'master': self.device7.pk,
- 'domain': 'test-domain-3',
+ 'master': devices[6].pk,
+ 'domain': 'domain-3',
},
{
- 'master': self.device8.pk,
- 'domain': 'test-domain-4',
+ 'master': devices[7].pk,
+ 'domain': 'domain-4',
},
{
- 'master': self.device9.pk,
- 'domain': 'test-domain-5',
+ 'master': devices[8].pk,
+ 'domain': 'domain-5',
},
]
- url = reverse('dcim-api:virtualchassis-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VirtualChassis.objects.count(), 5)
- for i in range(0, 3):
- self.assertEqual(response.data[i]['master']['id'], data[i]['master'])
- self.assertEqual(response.data[i]['domain'], data[i]['domain'])
- def test_update_virtualchassis(self):
+class PowerPanelTest(APIViewTestCases.APIViewTestCase):
+ model = PowerPanel
+ brief_fields = ['id', 'name', 'powerfeed_count', 'url']
- data = {
- 'master': self.device2.pk,
- 'domain': 'test-domain-x',
- }
+ @classmethod
+ def setUpTestData(cls):
+ site = Site.objects.create(name='Site 1', slug='site-1')
- url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(VirtualChassis.objects.count(), 2)
- vc1 = VirtualChassis.objects.get(pk=response.data['id'])
- self.assertEqual(vc1.master.pk, data['master'])
- self.assertEqual(vc1.domain, data['domain'])
-
- def test_delete_virtualchassis(self):
-
- url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(VirtualChassis.objects.count(), 1)
-
- # Verify that all VC members have had their VC-related fields nullified
- for d in [self.device1, self.device2, self.device3]:
- self.assertTrue(
- Device.objects.filter(pk=d.pk, virtual_chassis=None, vc_position=None, vc_priority=None)
- )
-
-
-class PowerPanelTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1')
- self.rackgroup2 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 2', slug='test-rack-group-2')
- self.rackgroup3 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 3', slug='test-rack-group-3')
- self.powerpanel1 = PowerPanel.objects.create(
- site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 1'
- )
- self.powerpanel2 = PowerPanel.objects.create(
- site=self.site1, rack_group=self.rackgroup2, name='Test Power Panel 2'
- )
- self.powerpanel3 = PowerPanel.objects.create(
- site=self.site1, rack_group=self.rackgroup3, name='Test Power Panel 3'
+ rack_groups = (
+ RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=site),
+ RackGroup.objects.create(name='Rack Group 2', slug='rack-group-2', site=site),
+ RackGroup.objects.create(name='Rack Group 3', slug='rack-group-3', site=site),
)
- def test_get_powerpanel(self):
-
- url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.powerpanel1.name)
-
- def test_list_powerpanels(self):
-
- url = reverse('dcim-api:powerpanel-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_powerpanels_brief(self):
-
- url = reverse('dcim-api:powerpanel-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'powerfeed_count', 'url']
+ power_panels = (
+ PowerPanel(site=site, rack_group=rack_groups[0], name='Power Panel 1'),
+ PowerPanel(site=site, rack_group=rack_groups[1], name='Power Panel 2'),
+ PowerPanel(site=site, rack_group=rack_groups[2], name='Power Panel 3'),
)
+ PowerPanel.objects.bulk_create(power_panels)
- def test_create_powerpanel(self):
-
- data = {
- 'name': 'Test Power Panel 4',
- 'site': self.site1.pk,
- 'rack_group': self.rackgroup1.pk,
- }
-
- url = reverse('dcim-api:powerpanel-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPanel.objects.count(), 4)
- powerpanel4 = PowerPanel.objects.get(pk=response.data['id'])
- self.assertEqual(powerpanel4.name, data['name'])
- self.assertEqual(powerpanel4.site_id, data['site'])
- self.assertEqual(powerpanel4.rack_group_id, data['rack_group'])
-
- def test_create_powerpanel_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Power Panel 4',
- 'site': self.site1.pk,
- 'rack_group': self.rackgroup1.pk,
+ 'name': 'Power Panel 4',
+ 'site': site.pk,
+ 'rack_group': rack_groups[0].pk,
},
{
- 'name': 'Test Power Panel 5',
- 'site': self.site1.pk,
- 'rack_group': self.rackgroup2.pk,
+ 'name': 'Power Panel 5',
+ 'site': site.pk,
+ 'rack_group': rack_groups[1].pk,
},
{
- 'name': 'Test Power Panel 6',
- 'site': self.site1.pk,
- 'rack_group': self.rackgroup3.pk,
+ 'name': 'Power Panel 6',
+ 'site': site.pk,
+ 'rack_group': rack_groups[2].pk,
},
]
- url = reverse('dcim-api:powerpanel-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerPanel.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class PowerFeedTest(APIViewTestCases.APIViewTestCase):
+ model = PowerFeed
+ brief_fields = ['id', 'name', 'url']
- def test_update_powerpanel(self):
+ @classmethod
+ def setUpTestData(cls):
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ rackgroup = RackGroup.objects.create(site=site, name='Rack Group 1', slug='rack-group-1')
+ rackrole = RackRole.objects.create(name='Rack Role 1', slug='rack-role-1', color='ff0000')
- data = {
- 'name': 'Test Power Panel X',
- 'rack_group': self.rackgroup2.pk,
- }
-
- url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk})
- response = self.client.patch(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerPanel.objects.count(), 3)
- powerpanel1 = PowerPanel.objects.get(pk=response.data['id'])
- self.assertEqual(powerpanel1.name, data['name'])
- self.assertEqual(powerpanel1.rack_group_id, data['rack_group'])
-
- def test_delete_powerpanel(self):
-
- url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerPanel.objects.count(), 2)
-
-
-class PowerFeedTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1')
- self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000')
- self.rack1 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 1', u_height=42,
+ racks = (
+ Rack(site=site, group=rackgroup, role=rackrole, name='Rack 1'),
+ Rack(site=site, group=rackgroup, role=rackrole, name='Rack 2'),
+ Rack(site=site, group=rackgroup, role=rackrole, name='Rack 3'),
+ Rack(site=site, group=rackgroup, role=rackrole, name='Rack 4'),
)
- self.rack2 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 2', u_height=42,
+ Rack.objects.bulk_create(racks)
+
+ power_panels = (
+ PowerPanel(site=site, rack_group=rackgroup, name='Power Panel 1'),
+ PowerPanel(site=site, rack_group=rackgroup, name='Power Panel 2'),
)
- self.rack3 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 3', u_height=42,
- )
- self.rack4 = Rack.objects.create(
- site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 4', u_height=42,
- )
- self.powerpanel1 = PowerPanel.objects.create(
- site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 1'
- )
- self.powerpanel2 = PowerPanel.objects.create(
- site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 2'
- )
- self.powerfeed1 = PowerFeed.objects.create(
- power_panel=self.powerpanel1, rack=self.rack1, name='Test Power Feed 1A', type=PowerFeedTypeChoices.TYPE_PRIMARY
- )
- self.powerfeed2 = PowerFeed.objects.create(
- power_panel=self.powerpanel2, rack=self.rack1, name='Test Power Feed 1B', type=PowerFeedTypeChoices.TYPE_REDUNDANT
- )
- self.powerfeed3 = PowerFeed.objects.create(
- power_panel=self.powerpanel1, rack=self.rack2, name='Test Power Feed 2A', type=PowerFeedTypeChoices.TYPE_PRIMARY
- )
- self.powerfeed4 = PowerFeed.objects.create(
- power_panel=self.powerpanel2, rack=self.rack2, name='Test Power Feed 2B', type=PowerFeedTypeChoices.TYPE_REDUNDANT
- )
- self.powerfeed5 = PowerFeed.objects.create(
- power_panel=self.powerpanel1, rack=self.rack3, name='Test Power Feed 3A', type=PowerFeedTypeChoices.TYPE_PRIMARY
- )
- self.powerfeed6 = PowerFeed.objects.create(
- power_panel=self.powerpanel2, rack=self.rack3, name='Test Power Feed 3B', type=PowerFeedTypeChoices.TYPE_REDUNDANT
+ PowerPanel.objects.bulk_create(power_panels)
+
+ PRIMARY = PowerFeedTypeChoices.TYPE_PRIMARY
+ REDUNDANT = PowerFeedTypeChoices.TYPE_REDUNDANT
+ power_feeds = (
+ PowerFeed(power_panel=power_panels[0], rack=racks[0], name='Power Feed 1A', type=PRIMARY),
+ PowerFeed(power_panel=power_panels[1], rack=racks[0], name='Power Feed 1B', type=REDUNDANT),
+ PowerFeed(power_panel=power_panels[0], rack=racks[1], name='Power Feed 2A', type=PRIMARY),
+ PowerFeed(power_panel=power_panels[1], rack=racks[1], name='Power Feed 2B', type=REDUNDANT),
+ PowerFeed(power_panel=power_panels[0], rack=racks[2], name='Power Feed 3A', type=PRIMARY),
+ PowerFeed(power_panel=power_panels[1], rack=racks[2], name='Power Feed 3B', type=REDUNDANT),
)
+ PowerFeed.objects.bulk_create(power_feeds)
- def test_get_powerfeed(self):
-
- url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.powerfeed1.name)
-
- def test_list_powerfeeds(self):
-
- url = reverse('dcim-api:powerfeed-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 6)
-
- def test_list_powerfeeds_brief(self):
-
- url = reverse('dcim-api:powerfeed-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'url']
- )
-
- def test_create_powerfeed(self):
-
- data = {
- 'name': 'Test Power Feed 4A',
- 'power_panel': self.powerpanel1.pk,
- 'rack': self.rack4.pk,
- 'type': PowerFeedTypeChoices.TYPE_PRIMARY,
- }
-
- url = reverse('dcim-api:powerfeed-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerFeed.objects.count(), 7)
- powerfeed4 = PowerFeed.objects.get(pk=response.data['id'])
- self.assertEqual(powerfeed4.name, data['name'])
- self.assertEqual(powerfeed4.power_panel_id, data['power_panel'])
- self.assertEqual(powerfeed4.rack_id, data['rack'])
-
- def test_create_powerfeed_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Power Feed 4A',
- 'power_panel': self.powerpanel1.pk,
- 'rack': self.rack4.pk,
- 'type': PowerFeedTypeChoices.TYPE_PRIMARY,
+ 'name': 'Power Feed 4A',
+ 'power_panel': power_panels[0].pk,
+ 'rack': racks[3].pk,
+ 'type': PRIMARY,
},
{
- 'name': 'Test Power Feed 4B',
- 'power_panel': self.powerpanel1.pk,
- 'rack': self.rack4.pk,
- 'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
+ 'name': 'Power Feed 4B',
+ 'power_panel': power_panels[1].pk,
+ 'rack': racks[3].pk,
+ 'type': REDUNDANT,
},
]
-
- url = reverse('dcim-api:powerfeed-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(PowerFeed.objects.count(), 8)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
-
- def test_update_powerfeed(self):
-
- data = {
- 'name': 'Test Power Feed X',
- 'rack': self.rack4.pk,
- 'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
- }
-
- url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk})
- response = self.client.patch(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(PowerFeed.objects.count(), 6)
- powerfeed1 = PowerFeed.objects.get(pk=response.data['id'])
- self.assertEqual(powerfeed1.name, data['name'])
- self.assertEqual(powerfeed1.rack_id, data['rack'])
- self.assertEqual(powerfeed1.type, data['type'])
-
- def test_delete_powerfeed(self):
-
- url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(PowerFeed.objects.count(), 5)
diff --git a/netbox/extras/admin.py b/netbox/extras/admin.py
index 8f6a20db6..808d7ce32 100644
--- a/netbox/extras/admin.py
+++ b/netbox/extras/admin.py
@@ -46,24 +46,19 @@ class WebhookAdmin(admin.ModelAdmin):
form = WebhookForm
fieldsets = (
(None, {
- 'fields': (
- 'name', 'obj_type', 'enabled',
- )
+ 'fields': ('name', 'obj_type', 'enabled')
}),
('Events', {
- 'fields': (
- 'type_create', 'type_update', 'type_delete',
- )
+ 'fields': ('type_create', 'type_update', 'type_delete')
}),
('HTTP Request', {
'fields': (
'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret',
- )
+ ),
+ 'classes': ('monospace',)
}),
('SSL', {
- 'fields': (
- 'ssl_verification', 'ca_file_path',
- )
+ 'fields': ('ssl_verification', 'ca_file_path')
})
)
@@ -121,6 +116,8 @@ class CustomLinkForm(forms.ModelForm):
'url': forms.Textarea,
}
help_texts = {
+ 'weight': 'A numeric weight to influence the ordering of this link among its peers. Lower weights appear '
+ 'first in a list.',
'text': 'Jinja2 template code for the link text. Reference the object as {{ obj }}
. Links '
'which render as empty text will not be displayed.',
'url': 'Jinja2 template code for the link URL. Reference the object as {{ obj }}
.',
@@ -136,6 +133,15 @@ class CustomLinkForm(forms.ModelForm):
@admin.register(CustomLink)
class CustomLinkAdmin(admin.ModelAdmin):
+ fieldsets = (
+ ('Custom Link', {
+ 'fields': ('content_type', 'name', 'group_name', 'weight', 'button_class', 'new_window')
+ }),
+ ('Templates', {
+ 'fields': ('text', 'url'),
+ 'classes': ('monospace',)
+ })
+ )
list_display = [
'name', 'content_type', 'group_name', 'weight',
]
@@ -149,8 +155,29 @@ class CustomLinkAdmin(admin.ModelAdmin):
# Graphs
#
+class GraphForm(forms.ModelForm):
+
+ class Meta:
+ model = Graph
+ exclude = ()
+ widgets = {
+ 'source': forms.Textarea,
+ 'link': forms.Textarea,
+ }
+
+
@admin.register(Graph)
class GraphAdmin(admin.ModelAdmin):
+ fieldsets = (
+ ('Graph', {
+ 'fields': ('type', 'name', 'weight')
+ }),
+ ('Templates', {
+ 'fields': ('template_language', 'source', 'link'),
+ 'classes': ('monospace',)
+ })
+ )
+ form = GraphForm
list_display = [
'name', 'type', 'weight', 'template_language', 'source',
]
@@ -179,6 +206,15 @@ class ExportTemplateForm(forms.ModelForm):
@admin.register(ExportTemplate)
class ExportTemplateAdmin(admin.ModelAdmin):
+ fieldsets = (
+ ('Export Template', {
+ 'fields': ('content_type', 'name', 'description', 'mime_type', 'file_extension')
+ }),
+ ('Content', {
+ 'fields': ('template_language', 'template_code'),
+ 'classes': ('monospace',)
+ })
+ )
list_display = [
'name', 'content_type', 'description', 'mime_type', 'file_extension',
]
diff --git a/netbox/extras/api/nested_serializers.py b/netbox/extras/api/nested_serializers.py
index 11367aba9..672b10a78 100644
--- a/netbox/extras/api/nested_serializers.py
+++ b/netbox/extras/api/nested_serializers.py
@@ -1,15 +1,49 @@
from rest_framework import serializers
-from extras.models import ReportResult
+from extras import models
+from utilities.api import WritableNestedSerializer
__all__ = [
+ 'NestedConfigContextSerializer',
+ 'NestedExportTemplateSerializer',
+ 'NestedGraphSerializer',
'NestedReportResultSerializer',
+ 'NestedTagSerializer',
]
-#
-# Reports
-#
+class NestedConfigContextSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='extras-api:configcontext-detail')
+
+ class Meta:
+ model = models.ConfigContext
+ fields = ['id', 'url', 'name']
+
+
+class NestedExportTemplateSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='extras-api:exporttemplate-detail')
+
+ class Meta:
+ model = models.ExportTemplate
+ fields = ['id', 'url', 'name']
+
+
+class NestedGraphSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='extras-api:graph-detail')
+
+ class Meta:
+ model = models.Graph
+ fields = ['id', 'url', 'name']
+
+
+class NestedTagSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='extras-api:tag-detail')
+ tagged_items = serializers.IntegerField(read_only=True)
+
+ class Meta:
+ model = models.Tag
+ fields = ['id', 'url', 'name', 'slug', 'color', 'tagged_items']
+
class NestedReportResultSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(
@@ -19,5 +53,5 @@ class NestedReportResultSerializer(serializers.ModelSerializer):
)
class Meta:
- model = ReportResult
+ model = models.ReportResult
fields = ['url', 'created', 'user', 'failed']
diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py
index 3ab9eaaf0..2635fbbdc 100644
--- a/netbox/extras/tests/test_api.py
+++ b/netbox/extras/tests/test_api.py
@@ -5,13 +5,11 @@ from django.urls import reverse
from django.utils import timezone
from rest_framework import status
-from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Platform, Rack, RackGroup, RackRole, Region, Site
+from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, RackGroup, RackRole, Site
from extras.api.views import ScriptViewSet
from extras.models import ConfigContext, Graph, ExportTemplate, Tag
from extras.scripts import BooleanVar, IntegerVar, Script, StringVar
-from extras.utils import FeatureQuery
-from tenancy.models import Tenant, TenantGroup
-from utilities.testing import APITestCase
+from utilities.testing import APITestCase, APIViewTestCases
class AppTest(APITestCase):
@@ -24,489 +22,150 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class GraphTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- site_ct = ContentType.objects.get_for_model(Site)
- self.graph1 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 1',
- source='http://example.com/graphs.py?site={{ obj.name }}&foo=1'
- )
- self.graph2 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 2',
- source='http://example.com/graphs.py?site={{ obj.name }}&foo=2'
- )
- self.graph3 = Graph.objects.create(
- type=site_ct,
- name='Test Graph 3',
- source='http://example.com/graphs.py?site={{ obj.name }}&foo=3'
- )
-
- def test_get_graph(self):
-
- url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.graph1.name)
-
- def test_list_graphs(self):
-
- url = reverse('extras-api:graph-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_graph(self):
-
- data = {
+class GraphTest(APIViewTestCases.APIViewTestCase):
+ model = Graph
+ brief_fields = ['id', 'name', 'url']
+ create_data = [
+ {
'type': 'dcim.site',
- 'name': 'Test Graph 4',
+ 'name': 'Graph 4',
'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=4',
- }
-
- url = reverse('extras-api:graph-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Graph.objects.count(), 4)
- graph4 = Graph.objects.get(pk=response.data['id'])
- self.assertEqual(graph4.type, ContentType.objects.get_for_model(Site))
- self.assertEqual(graph4.name, data['name'])
- self.assertEqual(graph4.source, data['source'])
-
- def test_create_graph_bulk(self):
-
- data = [
- {
- 'type': 'dcim.site',
- 'name': 'Test Graph 4',
- 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=4',
- },
- {
- 'type': 'dcim.site',
- 'name': 'Test Graph 5',
- 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=5',
- },
- {
- 'type': 'dcim.site',
- 'name': 'Test Graph 6',
- 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=6',
- },
- ]
-
- url = reverse('extras-api:graph-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Graph.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_graph(self):
-
- data = {
+ },
+ {
'type': 'dcim.site',
- 'name': 'Test Graph X',
- 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=99',
- }
+ 'name': 'Graph 5',
+ 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=5',
+ },
+ {
+ 'type': 'dcim.site',
+ 'name': 'Graph 6',
+ 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=6',
+ },
+ ]
- url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk})
- response = self.client.put(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
+ ct = ContentType.objects.get_for_model(Site)
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Graph.objects.count(), 3)
- graph1 = Graph.objects.get(pk=response.data['id'])
- self.assertEqual(graph1.type, ContentType.objects.get_for_model(Site))
- self.assertEqual(graph1.name, data['name'])
- self.assertEqual(graph1.source, data['source'])
-
- def test_delete_graph(self):
-
- url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Graph.objects.count(), 2)
-
-
-class ExportTemplateTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- content_type = ContentType.objects.get_for_model(Device)
- self.exporttemplate1 = ExportTemplate.objects.create(
- content_type=content_type, name='Test Export Template 1',
- template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
- )
- self.exporttemplate2 = ExportTemplate.objects.create(
- content_type=content_type, name='Test Export Template 2',
- template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
- )
- self.exporttemplate3 = ExportTemplate.objects.create(
- content_type=content_type, name='Test Export Template 3',
- template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
+ graphs = (
+ Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.name }}&foo=1'),
+ Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.name }}&foo=2'),
+ Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.name }}&foo=3'),
)
+ Graph.objects.bulk_create(graphs)
- def test_get_exporttemplate(self):
- url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.exporttemplate1.name)
-
- def test_list_exporttemplates(self):
-
- url = reverse('extras-api:exporttemplate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_exporttemplate(self):
-
- data = {
+class ExportTemplateTest(APIViewTestCases.APIViewTestCase):
+ model = ExportTemplate
+ brief_fields = ['id', 'name', 'url']
+ create_data = [
+ {
'content_type': 'dcim.device',
'name': 'Test Export Template 4',
'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
- }
-
- url = reverse('extras-api:exporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ExportTemplate.objects.count(), 4)
- exporttemplate4 = ExportTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(exporttemplate4.content_type, ContentType.objects.get_for_model(Device))
- self.assertEqual(exporttemplate4.name, data['name'])
- self.assertEqual(exporttemplate4.template_code, data['template_code'])
-
- def test_create_exporttemplate_bulk(self):
-
- data = [
- {
- 'content_type': 'dcim.device',
- 'name': 'Test Export Template 4',
- 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
- },
- {
- 'content_type': 'dcim.device',
- 'name': 'Test Export Template 5',
- 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
- },
- {
- 'content_type': 'dcim.device',
- 'name': 'Test Export Template 6',
- 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
- },
- ]
-
- url = reverse('extras-api:exporttemplate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ExportTemplate.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_exporttemplate(self):
-
- data = {
+ },
+ {
'content_type': 'dcim.device',
- 'name': 'Test Export Template X',
+ 'name': 'Test Export Template 5',
'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
- }
+ },
+ {
+ 'content_type': 'dcim.device',
+ 'name': 'Test Export Template 6',
+ 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}',
+ },
+ ]
- url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
+ ct = ContentType.objects.get_for_model(Device)
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ExportTemplate.objects.count(), 3)
- exporttemplate1 = ExportTemplate.objects.get(pk=response.data['id'])
- self.assertEqual(exporttemplate1.name, data['name'])
- self.assertEqual(exporttemplate1.template_code, data['template_code'])
-
- def test_delete_exporttemplate(self):
-
- url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ExportTemplate.objects.count(), 2)
-
-
-class TagTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.tag1 = Tag.objects.create(name='Test Tag 1', slug='test-tag-1')
- self.tag2 = Tag.objects.create(name='Test Tag 2', slug='test-tag-2')
- self.tag3 = Tag.objects.create(name='Test Tag 3', slug='test-tag-3')
-
- def test_get_tag(self):
-
- url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.tag1.name)
-
- def test_list_tags(self):
-
- url = reverse('extras-api:tag-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_tag(self):
-
- data = {
- 'name': 'Test Tag 4',
- 'slug': 'test-tag-4',
- }
-
- url = reverse('extras-api:tag-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Tag.objects.count(), 4)
- tag4 = Tag.objects.get(pk=response.data['id'])
- self.assertEqual(tag4.name, data['name'])
- self.assertEqual(tag4.slug, data['slug'])
-
- def test_create_tag_bulk(self):
-
- data = [
- {
- 'name': 'Test Tag 4',
- 'slug': 'test-tag-4',
- },
- {
- 'name': 'Test Tag 5',
- 'slug': 'test-tag-5',
- },
- {
- 'name': 'Test Tag 6',
- 'slug': 'test-tag-6',
- },
- ]
-
- url = reverse('extras-api:tag-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Tag.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_tag(self):
-
- data = {
- 'name': 'Test Tag X',
- 'slug': 'test-tag-x',
- }
-
- url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Tag.objects.count(), 3)
- tag1 = Tag.objects.get(pk=response.data['id'])
- self.assertEqual(tag1.name, data['name'])
- self.assertEqual(tag1.slug, data['slug'])
-
- def test_delete_tag(self):
-
- url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Tag.objects.count(), 2)
-
-
-class ConfigContextTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.configcontext1 = ConfigContext.objects.create(
- name='Test Config Context 1',
- weight=100,
- data={'foo': 123}
+ export_templates = (
+ ExportTemplate(
+ content_type=ct,
+ name='Export Template 1',
+ template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
+ ),
+ ExportTemplate(
+ content_type=ct,
+ name='Export Template 2',
+ template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
+ ),
+ ExportTemplate(
+ content_type=ct,
+ name='Export Template 3',
+ template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}'
+ ),
)
- self.configcontext2 = ConfigContext.objects.create(
- name='Test Config Context 2',
- weight=200,
- data={'bar': 456}
+ ExportTemplate.objects.bulk_create(export_templates)
+
+
+class TagTest(APIViewTestCases.APIViewTestCase):
+ model = Tag
+ brief_fields = ['color', 'id', 'name', 'slug', 'tagged_items', 'url']
+ create_data = [
+ {
+ 'name': 'Tag 4',
+ 'slug': 'tag-4',
+ },
+ {
+ 'name': 'Tag 5',
+ 'slug': 'tag-5',
+ },
+ {
+ 'name': 'Tag 6',
+ 'slug': 'tag-6',
+ },
+ ]
+
+ @classmethod
+ def setUpTestData(cls):
+
+ tags = (
+ Tag(name='Tag 1', slug='tag-1'),
+ Tag(name='Tag 2', slug='tag-2'),
+ Tag(name='Tag 3', slug='tag-3'),
)
- self.configcontext3 = ConfigContext.objects.create(
- name='Test Config Context 3',
- weight=300,
- data={'baz': 789}
+ Tag.objects.bulk_create(tags)
+
+
+class ConfigContextTest(APIViewTestCases.APIViewTestCase):
+ model = ConfigContext
+ brief_fields = ['id', 'name', 'url']
+ create_data = [
+ {
+ 'name': 'Config Context 4',
+ 'data': {'more_foo': True},
+ },
+ {
+ 'name': 'Config Context 5',
+ 'data': {'more_bar': False},
+ },
+ {
+ 'name': 'Config Context 6',
+ 'data': {'more_baz': None},
+ },
+ ]
+
+ @classmethod
+ def setUpTestData(cls):
+
+ config_contexts = (
+ ConfigContext(name='Config Context 1', weight=100, data={'foo': 123}),
+ ConfigContext(name='Config Context 2', weight=200, data={'bar': 456}),
+ ConfigContext(name='Config Context 3', weight=300, data={'baz': 789}),
)
-
- def test_get_configcontext(self):
-
- url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.configcontext1.name)
- self.assertEqual(response.data['data'], self.configcontext1.data)
-
- def test_list_configcontexts(self):
-
- url = reverse('extras-api:configcontext-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_configcontext(self):
-
- region1 = Region.objects.create(name='Test Region 1', slug='test-region-1')
- region2 = Region.objects.create(name='Test Region 2', slug='test-region-2')
- site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- site2 = Site.objects.create(name='Test Site 2', slug='test-site-2')
- role1 = DeviceRole.objects.create(name='Test Role 1', slug='test-role-1')
- role2 = DeviceRole.objects.create(name='Test Role 2', slug='test-role-2')
- platform1 = Platform.objects.create(name='Test Platform 1', slug='test-platform-1')
- platform2 = Platform.objects.create(name='Test Platform 2', slug='test-platform-2')
- tenantgroup1 = TenantGroup(name='Test Tenant Group 1', slug='test-tenant-group-1')
- tenantgroup1.save()
- tenantgroup2 = TenantGroup(name='Test Tenant Group 2', slug='test-tenant-group-2')
- tenantgroup2.save()
- tenant1 = Tenant.objects.create(name='Test Tenant 1', slug='test-tenant-1')
- tenant2 = Tenant.objects.create(name='Test Tenant 2', slug='test-tenant-2')
- tag1 = Tag.objects.create(name='Test Tag 1', slug='test-tag-1')
- tag2 = Tag.objects.create(name='Test Tag 2', slug='test-tag-2')
-
- data = {
- 'name': 'Test Config Context 4',
- 'weight': 1000,
- 'regions': [region1.pk, region2.pk],
- 'sites': [site1.pk, site2.pk],
- 'roles': [role1.pk, role2.pk],
- 'platforms': [platform1.pk, platform2.pk],
- 'tenant_groups': [tenantgroup1.pk, tenantgroup2.pk],
- 'tenants': [tenant1.pk, tenant2.pk],
- 'tags': [tag1.slug, tag2.slug],
- 'data': {'foo': 'XXX'}
- }
-
- url = reverse('extras-api:configcontext-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConfigContext.objects.count(), 4)
- configcontext4 = ConfigContext.objects.get(pk=response.data['id'])
- self.assertEqual(configcontext4.name, data['name'])
- self.assertEqual(region1.pk, data['regions'][0])
- self.assertEqual(region2.pk, data['regions'][1])
- self.assertEqual(site1.pk, data['sites'][0])
- self.assertEqual(site2.pk, data['sites'][1])
- self.assertEqual(role1.pk, data['roles'][0])
- self.assertEqual(role2.pk, data['roles'][1])
- self.assertEqual(platform1.pk, data['platforms'][0])
- self.assertEqual(platform2.pk, data['platforms'][1])
- self.assertEqual(tenantgroup1.pk, data['tenant_groups'][0])
- self.assertEqual(tenantgroup2.pk, data['tenant_groups'][1])
- self.assertEqual(tenant1.pk, data['tenants'][0])
- self.assertEqual(tenant2.pk, data['tenants'][1])
- self.assertEqual(tag1.slug, data['tags'][0])
- self.assertEqual(tag2.slug, data['tags'][1])
- self.assertEqual(configcontext4.data, data['data'])
-
- def test_create_configcontext_bulk(self):
-
- data = [
- {
- 'name': 'Test Config Context 4',
- 'data': {'more_foo': True},
- },
- {
- 'name': 'Test Config Context 5',
- 'data': {'more_bar': False},
- },
- {
- 'name': 'Test Config Context 6',
- 'data': {'more_baz': None},
- },
- ]
-
- url = reverse('extras-api:configcontext-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ConfigContext.objects.count(), 6)
- for i in range(0, 3):
- self.assertEqual(response.data[i]['name'], data[i]['name'])
- self.assertEqual(response.data[i]['data'], data[i]['data'])
-
- def test_update_configcontext(self):
-
- region1 = Region.objects.create(name='Test Region 1', slug='test-region-1')
- region2 = Region.objects.create(name='Test Region 2', slug='test-region-2')
-
- data = {
- 'name': 'Test Config Context X',
- 'weight': 999,
- 'regions': [region1.pk, region2.pk],
- 'data': {'foo': 'XXX'}
- }
-
- url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ConfigContext.objects.count(), 3)
- configcontext1 = ConfigContext.objects.get(pk=response.data['id'])
- self.assertEqual(configcontext1.name, data['name'])
- self.assertEqual(configcontext1.weight, data['weight'])
- self.assertEqual(sorted([r.pk for r in configcontext1.regions.all()]), sorted(data['regions']))
- self.assertEqual(configcontext1.data, data['data'])
-
- def test_delete_configcontext(self):
-
- url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ConfigContext.objects.count(), 2)
+ ConfigContext.objects.bulk_create(config_contexts)
def test_render_configcontext_for_object(self):
-
- # Create a Device for which we'll render a config context
- manufacturer = Manufacturer.objects.create(
- name='Test Manufacturer',
- slug='test-manufacturer'
- )
- device_type = DeviceType.objects.create(
- manufacturer=manufacturer,
- model='Test Device Type'
- )
- device_role = DeviceRole.objects.create(
- name='Test Role',
- slug='test-role'
- )
- site = Site.objects.create(
- name='Test Site',
- slug='test-site'
- )
- device = Device.objects.create(
- name='Test Device',
- device_type=device_type,
- device_role=device_role,
- site=site
- )
+ """
+ Test rendering config context data for a device.
+ """
+ manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
+ devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
+ site = Site.objects.create(name='Site-1', slug='site-1')
+ device = Device.objects.create(name='Device 1', device_type=devicetype, device_role=devicerole, site=site)
# Test default config contexts (created at test setup)
rendered_context = device.get_config_context()
@@ -516,7 +175,7 @@ class ConfigContextTest(APITestCase):
# Add another context specific to the site
configcontext4 = ConfigContext(
- name='Test Config Context 4',
+ name='Config Context 4',
data={'site_data': 'ABC'}
)
configcontext4.save()
@@ -526,7 +185,7 @@ class ConfigContextTest(APITestCase):
# Override one of the default contexts
configcontext5 = ConfigContext(
- name='Test Config Context 5',
+ name='Config Context 5',
weight=2000,
data={'foo': 999}
)
@@ -536,12 +195,9 @@ class ConfigContextTest(APITestCase):
self.assertEqual(rendered_context['foo'], 999)
# Add a context which does NOT match our device and ensure it does not apply
- site2 = Site.objects.create(
- name='Test Site 2',
- slug='test-site-2'
- )
+ site2 = Site.objects.create(name='Site 2', slug='site-2')
configcontext6 = ConfigContext(
- name='Test Config Context 6',
+ name='Config Context 6',
weight=2000,
data={'bar': 999}
)
diff --git a/netbox/ipam/api/nested_serializers.py b/netbox/ipam/api/nested_serializers.py
index aa7c95f1c..abe75b261 100644
--- a/netbox/ipam/api/nested_serializers.py
+++ b/netbox/ipam/api/nested_serializers.py
@@ -1,6 +1,6 @@
from rest_framework import serializers
-from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, VLAN, VLANGroup, VRF
+from ipam import models
from utilities.api import WritableNestedSerializer
__all__ = [
@@ -9,6 +9,7 @@ __all__ = [
'NestedPrefixSerializer',
'NestedRIRSerializer',
'NestedRoleSerializer',
+ 'NestedServiceSerializer',
'NestedVLANGroupSerializer',
'NestedVLANSerializer',
'NestedVRFSerializer',
@@ -24,7 +25,7 @@ class NestedVRFSerializer(WritableNestedSerializer):
prefix_count = serializers.IntegerField(read_only=True)
class Meta:
- model = VRF
+ model = models.VRF
fields = ['id', 'url', 'name', 'rd', 'prefix_count']
@@ -37,7 +38,7 @@ class NestedRIRSerializer(WritableNestedSerializer):
aggregate_count = serializers.IntegerField(read_only=True)
class Meta:
- model = RIR
+ model = models.RIR
fields = ['id', 'url', 'name', 'slug', 'aggregate_count']
@@ -45,7 +46,7 @@ class NestedAggregateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail')
class Meta:
- model = Aggregate
+ model = models.Aggregate
fields = ['id', 'url', 'family', 'prefix']
@@ -59,7 +60,7 @@ class NestedRoleSerializer(WritableNestedSerializer):
vlan_count = serializers.IntegerField(read_only=True)
class Meta:
- model = Role
+ model = models.Role
fields = ['id', 'url', 'name', 'slug', 'prefix_count', 'vlan_count']
@@ -68,7 +69,7 @@ class NestedVLANGroupSerializer(WritableNestedSerializer):
vlan_count = serializers.IntegerField(read_only=True)
class Meta:
- model = VLANGroup
+ model = models.VLANGroup
fields = ['id', 'url', 'name', 'slug', 'vlan_count']
@@ -76,7 +77,7 @@ class NestedVLANSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
class Meta:
- model = VLAN
+ model = models.VLAN
fields = ['id', 'url', 'vid', 'name', 'display_name']
@@ -88,7 +89,7 @@ class NestedPrefixSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:prefix-detail')
class Meta:
- model = Prefix
+ model = models.Prefix
fields = ['id', 'url', 'family', 'prefix']
@@ -96,10 +97,21 @@ class NestedPrefixSerializer(WritableNestedSerializer):
# IP addresses
#
-
class NestedIPAddressSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
class Meta:
- model = IPAddress
+ model = models.IPAddress
fields = ['id', 'url', 'family', 'address']
+
+
+#
+# Services
+#
+
+class NestedServiceSerializer(WritableNestedSerializer):
+ url = serializers.HyperlinkedIdentityField(view_name='ipam-api:service-detail')
+
+ class Meta:
+ model = models.Service
+ fields = ['id', 'url', 'name', 'protocol', 'port']
diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py
index bf430f633..dd3652b1f 100644
--- a/netbox/ipam/api/views.py
+++ b/netbox/ipam/api/views.py
@@ -276,7 +276,7 @@ class VLANViewSet(CustomFieldModelViewSet):
queryset = VLAN.objects.prefetch_related(
'site', 'group', 'tenant', 'role', 'tags'
).annotate(
- prefix_count=get_subquery(Prefix, 'role')
+ prefix_count=get_subquery(Prefix, 'vlan')
)
serializer_class = serializers.VLANSerializer
filterset_class = filters.VLANFilterSet
diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py
index c20ef6158..a5cb76953 100644
--- a/netbox/ipam/tests/test_api.py
+++ b/netbox/ipam/tests/test_api.py
@@ -7,7 +7,7 @@ from rest_framework import status
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from ipam.choices import *
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
-from utilities.testing import APITestCase, disable_warnings
+from utilities.testing import APITestCase, APIViewTestCases, disable_warnings
class AppTest(APITestCase):
@@ -20,536 +20,158 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class VRFTest(APITestCase):
+class VRFTest(APIViewTestCases.APIViewTestCase):
+ model = VRF
+ brief_fields = ['id', 'name', 'prefix_count', 'rd', 'url']
+ create_data = [
+ {
+ 'name': 'VRF 4',
+ 'rd': '65000:4',
+ },
+ {
+ 'name': 'VRF 5',
+ 'rd': '65000:5',
+ },
+ {
+ 'name': 'VRF 6',
+ 'rd': '65000:6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1')
- self.vrf2 = VRF.objects.create(name='Test VRF 2', rd='65000:2')
- self.vrf3 = VRF.objects.create(name='Test VRF 3') # No RD
-
- def test_get_vrf(self):
-
- url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.vrf1.name)
-
- def test_list_vrfs(self):
-
- url = reverse('ipam-api:vrf-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_vrfs_brief(self):
-
- url = reverse('ipam-api:vrf-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'prefix_count', 'rd', 'url']
+ vrfs = (
+ VRF(name='VRF 1', rd='65000:1'),
+ VRF(name='VRF 2', rd='65000:2'),
+ VRF(name='VRF 3'), # No RD
)
-
- def test_create_vrf(self):
-
- data_list = [
- # VRF with RD
- {
- 'name': 'Test VRF 4',
- 'rd': '65000:4',
- },
- # VRF without RD
- {
- 'name': 'Test VRF 5',
- }
- ]
-
- url = reverse('ipam-api:vrf-list')
-
- for data in data_list:
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- vrf = VRF.objects.get(pk=response.data['id'])
- self.assertEqual(vrf.name, data['name'])
- self.assertEqual(vrf.rd, data['rd'] if 'rd' in data else None)
-
- def test_create_vrf_bulk(self):
-
- data = [
- {
- 'name': 'Test VRF 4',
- 'rd': '65000:4',
- },
- {
- 'name': 'Test VRF 5',
- 'rd': '65000:5',
- },
- {
- 'name': 'Test VRF 6',
- 'rd': '65000:6',
- },
- ]
-
- url = reverse('ipam-api:vrf-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VRF.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_vrf(self):
-
- data = {
- 'name': 'Test VRF X',
- 'rd': '65000:99',
- }
-
- url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(VRF.objects.count(), 3)
- vrf1 = VRF.objects.get(pk=response.data['id'])
- self.assertEqual(vrf1.name, data['name'])
- self.assertEqual(vrf1.rd, data['rd'])
-
- def test_delete_vrf(self):
-
- url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(VRF.objects.count(), 2)
+ VRF.objects.bulk_create(vrfs)
-class RIRTest(APITestCase):
+class RIRTest(APIViewTestCases.APIViewTestCase):
+ model = RIR
+ brief_fields = ['aggregate_count', 'id', 'name', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'RIR 4',
+ 'slug': 'rir-4',
+ },
+ {
+ 'name': 'RIR 5',
+ 'slug': 'rir-5',
+ },
+ {
+ 'name': 'RIR 6',
+ 'slug': 'rir-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.rir1 = RIR.objects.create(name='Test RIR 1', slug='test-rir-1')
- self.rir2 = RIR.objects.create(name='Test RIR 2', slug='test-rir-2')
- self.rir3 = RIR.objects.create(name='Test RIR 3', slug='test-rir-3')
-
- def test_get_rir(self):
-
- url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.rir1.name)
-
- def test_list_rirs(self):
-
- url = reverse('ipam-api:rir-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_rirs_brief(self):
-
- url = reverse('ipam-api:rir-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['aggregate_count', 'id', 'name', 'slug', 'url']
+ rirs = (
+ RIR(name='RIR 1', slug='rir-1'),
+ RIR(name='RIR 2', slug='rir-2'),
+ RIR(name='RIR 3', slug='rir-3'),
)
-
- def test_create_rir(self):
-
- data = {
- 'name': 'Test RIR 4',
- 'slug': 'test-rir-4',
- }
-
- url = reverse('ipam-api:rir-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RIR.objects.count(), 4)
- rir4 = RIR.objects.get(pk=response.data['id'])
- self.assertEqual(rir4.name, data['name'])
- self.assertEqual(rir4.slug, data['slug'])
-
- def test_create_rir_bulk(self):
-
- data = [
- {
- 'name': 'Test RIR 4',
- 'slug': 'test-rir-4',
- },
- {
- 'name': 'Test RIR 5',
- 'slug': 'test-rir-5',
- },
- {
- 'name': 'Test RIR 6',
- 'slug': 'test-rir-6',
- },
- ]
-
- url = reverse('ipam-api:rir-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(RIR.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_rir(self):
-
- data = {
- 'name': 'Test RIR X',
- 'slug': 'test-rir-x',
- }
-
- url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(RIR.objects.count(), 3)
- rir1 = RIR.objects.get(pk=response.data['id'])
- self.assertEqual(rir1.name, data['name'])
- self.assertEqual(rir1.slug, data['slug'])
-
- def test_delete_rir(self):
-
- url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(RIR.objects.count(), 2)
+ RIR.objects.bulk_create(rirs)
-class AggregateTest(APITestCase):
+class AggregateTest(APIViewTestCases.APIViewTestCase):
+ model = Aggregate
+ brief_fields = ['family', 'id', 'prefix', 'url']
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.rir1 = RIR.objects.create(name='Test RIR 1', slug='test-rir-1')
- self.rir2 = RIR.objects.create(name='Test RIR 2', slug='test-rir-2')
- self.aggregate1 = Aggregate.objects.create(prefix=IPNetwork('10.0.0.0/8'), rir=self.rir1)
- self.aggregate2 = Aggregate.objects.create(prefix=IPNetwork('172.16.0.0/12'), rir=self.rir1)
- self.aggregate3 = Aggregate.objects.create(prefix=IPNetwork('192.168.0.0/16'), rir=self.rir1)
-
- def test_get_aggregate(self):
-
- url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['family']['value'], 4)
- self.assertEqual(response.data['prefix'], str(self.aggregate1.prefix))
-
- def test_list_aggregates(self):
-
- url = reverse('ipam-api:aggregate-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_aggregates_brief(self):
-
- url = reverse('ipam-api:aggregate-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['family', 'id', 'prefix', 'url']
+ rirs = (
+ RIR(name='RIR 1', slug='rir-1'),
+ RIR(name='RIR 2', slug='rir-2'),
)
+ RIR.objects.bulk_create(rirs)
- def test_create_aggregate(self):
+ aggregates = (
+ Aggregate(prefix=IPNetwork('10.0.0.0/8'), rir=rirs[0]),
+ Aggregate(prefix=IPNetwork('172.16.0.0/12'), rir=rirs[0]),
+ Aggregate(prefix=IPNetwork('192.168.0.0/16'), rir=rirs[0]),
+ )
+ Aggregate.objects.bulk_create(aggregates)
- data = {
- 'prefix': '192.0.2.0/24',
- 'rir': self.rir1.pk,
- }
-
- url = reverse('ipam-api:aggregate-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Aggregate.objects.count(), 4)
- aggregate4 = Aggregate.objects.get(pk=response.data['id'])
- self.assertEqual(str(aggregate4.prefix), data['prefix'])
- self.assertEqual(aggregate4.rir_id, data['rir'])
-
- def test_create_aggregate_bulk(self):
-
- data = [
+ cls.create_data = [
{
'prefix': '100.0.0.0/8',
- 'rir': self.rir1.pk,
+ 'rir': rirs[1].pk,
},
{
'prefix': '101.0.0.0/8',
- 'rir': self.rir1.pk,
+ 'rir': rirs[1].pk,
},
{
'prefix': '102.0.0.0/8',
- 'rir': self.rir1.pk,
+ 'rir': rirs[1].pk,
},
]
- url = reverse('ipam-api:aggregate-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Aggregate.objects.count(), 6)
- self.assertEqual(response.data[0]['prefix'], data[0]['prefix'])
- self.assertEqual(response.data[1]['prefix'], data[1]['prefix'])
- self.assertEqual(response.data[2]['prefix'], data[2]['prefix'])
+class RoleTest(APIViewTestCases.APIViewTestCase):
+ model = Role
+ brief_fields = ['id', 'name', 'prefix_count', 'slug', 'url', 'vlan_count']
+ create_data = [
+ {
+ 'name': 'Role 4',
+ 'slug': 'role-4',
+ },
+ {
+ 'name': 'Role 5',
+ 'slug': 'role-5',
+ },
+ {
+ 'name': 'Role 6',
+ 'slug': 'role-6',
+ },
+ ]
- def test_update_aggregate(self):
+ @classmethod
+ def setUpTestData(cls):
- data = {
- 'prefix': '11.0.0.0/8',
- 'rir': self.rir2.pk,
- }
-
- url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Aggregate.objects.count(), 3)
- aggregate1 = Aggregate.objects.get(pk=response.data['id'])
- self.assertEqual(str(aggregate1.prefix), data['prefix'])
- self.assertEqual(aggregate1.rir_id, data['rir'])
-
- def test_delete_aggregate(self):
-
- url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Aggregate.objects.count(), 2)
-
-
-class RoleTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.role1 = Role.objects.create(name='Test Role 1', slug='test-role-1')
- self.role2 = Role.objects.create(name='Test Role 2', slug='test-role-2')
- self.role3 = Role.objects.create(name='Test Role 3', slug='test-role-3')
-
- def test_get_role(self):
-
- url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.role1.name)
-
- def test_list_roles(self):
-
- url = reverse('ipam-api:role-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_roles_brief(self):
-
- url = reverse('ipam-api:role-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'prefix_count', 'slug', 'url', 'vlan_count']
+ roles = (
+ Role(name='Role 1', slug='role-1'),
+ Role(name='Role 2', slug='role-2'),
+ Role(name='Role 3', slug='role-3'),
)
-
- def test_create_role(self):
-
- data = {
- 'name': 'Test Role 4',
- 'slug': 'test-role-4',
- }
-
- url = reverse('ipam-api:role-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Role.objects.count(), 4)
- role4 = Role.objects.get(pk=response.data['id'])
- self.assertEqual(role4.name, data['name'])
- self.assertEqual(role4.slug, data['slug'])
-
- def test_create_role_bulk(self):
-
- data = [
- {
- 'name': 'Test Role 4',
- 'slug': 'test-role-4',
- },
- {
- 'name': 'Test Role 5',
- 'slug': 'test-role-5',
- },
- {
- 'name': 'Test Role 6',
- 'slug': 'test-role-6',
- },
- ]
-
- url = reverse('ipam-api:role-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Role.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_role(self):
-
- data = {
- 'name': 'Test Role X',
- 'slug': 'test-role-x',
- }
-
- url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Role.objects.count(), 3)
- role1 = Role.objects.get(pk=response.data['id'])
- self.assertEqual(role1.name, data['name'])
- self.assertEqual(role1.slug, data['slug'])
-
- def test_delete_role(self):
-
- url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Role.objects.count(), 2)
+ Role.objects.bulk_create(roles)
-class PrefixTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1')
- self.vlan1 = VLAN.objects.create(vid=1, name='Test VLAN 1')
- self.role1 = Role.objects.create(name='Test Role 1', slug='test-role-1')
- self.prefix1 = Prefix.objects.create(prefix=IPNetwork('192.168.1.0/24'))
- self.prefix2 = Prefix.objects.create(prefix=IPNetwork('192.168.2.0/24'))
- self.prefix3 = Prefix.objects.create(prefix=IPNetwork('192.168.3.0/24'))
-
- def test_get_prefix(self):
-
- url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['family']['value'], 4)
- self.assertEqual(response.data['prefix'], str(self.prefix1.prefix))
-
- def test_list_prefixes(self):
-
- url = reverse('ipam-api:prefix-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_prefixes_brief(self):
-
- url = reverse('ipam-api:prefix-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['family', 'id', 'prefix', 'url']
- )
-
- def test_create_prefix(self):
-
- data = {
+class PrefixTest(APIViewTestCases.APIViewTestCase):
+ model = Prefix
+ brief_fields = ['family', 'id', 'prefix', 'url']
+ create_data = [
+ {
'prefix': '192.168.4.0/24',
- 'site': self.site1.pk,
- 'vrf': self.vrf1.pk,
- 'vlan': self.vlan1.pk,
- 'role': self.role1.pk,
- }
+ },
+ {
+ 'prefix': '192.168.5.0/24',
+ },
+ {
+ 'prefix': '192.168.6.0/24',
+ },
+ ]
- url = reverse('ipam-api:prefix-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Prefix.objects.count(), 4)
- prefix4 = Prefix.objects.get(pk=response.data['id'])
- self.assertEqual(str(prefix4.prefix), data['prefix'])
- self.assertEqual(prefix4.site_id, data['site'])
- self.assertEqual(prefix4.vrf_id, data['vrf'])
- self.assertEqual(prefix4.vlan_id, data['vlan'])
- self.assertEqual(prefix4.role_id, data['role'])
-
- def test_create_prefix_bulk(self):
-
- data = [
- {
- 'prefix': '10.0.1.0/24',
- },
- {
- 'prefix': '10.0.2.0/24',
- },
- {
- 'prefix': '10.0.3.0/24',
- },
- ]
-
- url = reverse('ipam-api:prefix-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Prefix.objects.count(), 6)
- self.assertEqual(response.data[0]['prefix'], data[0]['prefix'])
- self.assertEqual(response.data[1]['prefix'], data[1]['prefix'])
- self.assertEqual(response.data[2]['prefix'], data[2]['prefix'])
-
- def test_update_prefix(self):
-
- data = {
- 'prefix': '192.168.99.0/24',
- 'site': self.site1.pk,
- 'vrf': self.vrf1.pk,
- 'vlan': self.vlan1.pk,
- 'role': self.role1.pk,
- }
-
- url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Prefix.objects.count(), 3)
- prefix1 = Prefix.objects.get(pk=response.data['id'])
- self.assertEqual(str(prefix1.prefix), data['prefix'])
- self.assertEqual(prefix1.site_id, data['site'])
- self.assertEqual(prefix1.vrf_id, data['vrf'])
- self.assertEqual(prefix1.vlan_id, data['vlan'])
- self.assertEqual(prefix1.role_id, data['role'])
-
- def test_delete_prefix(self):
-
- url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Prefix.objects.count(), 2)
+ prefixes = (
+ Prefix(prefix=IPNetwork('192.168.1.0/24')),
+ Prefix(prefix=IPNetwork('192.168.2.0/24')),
+ Prefix(prefix=IPNetwork('192.168.3.0/24')),
+ )
+ Prefix.objects.bulk_create(prefixes)
def test_list_available_prefixes(self):
-
+ """
+ Test retrieval of all available prefixes within a parent prefix.
+ """
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/24'))
Prefix.objects.create(prefix=IPNetwork('192.0.2.64/26'))
Prefix.objects.create(prefix=IPNetwork('192.0.2.192/27'))
@@ -562,7 +184,9 @@ class PrefixTest(APITestCase):
self.assertEqual(p['prefix'], available_prefixes[i])
def test_create_single_available_prefix(self):
-
+ """
+ Test retrieval of the first available prefix within a parent prefix.
+ """
vrf = VRF.objects.create(name='Test VRF 1', rd='1234')
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/28'), vrf=vrf, is_pool=True)
url = reverse('ipam-api:prefix-available-prefixes', kwargs={'pk': prefix.pk})
@@ -596,7 +220,9 @@ class PrefixTest(APITestCase):
self.assertIn('prefix_length', response.data[0])
def test_create_multiple_available_prefixes(self):
-
+ """
+ Test the creation of available prefixes within a parent prefix.
+ """
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/28'), is_pool=True)
url = reverse('ipam-api:prefix-available-prefixes', kwargs={'pk': prefix.pk})
@@ -622,7 +248,9 @@ class PrefixTest(APITestCase):
self.assertEqual(len(response.data), 4)
def test_list_available_ips(self):
-
+ """
+ Test retrieval of all available IP addresses within a parent prefix.
+ """
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/29'), is_pool=True)
url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk})
@@ -637,7 +265,9 @@ class PrefixTest(APITestCase):
self.assertEqual(len(response.data), 6) # 8 - 2 because prefix.is_pool = False
def test_create_single_available_ip(self):
-
+ """
+ Test retrieval of the first available IP address within a parent prefix.
+ """
vrf = VRF.objects.create(name='Test VRF 1', rd='1234')
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/30'), vrf=vrf, is_pool=True)
url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk})
@@ -658,7 +288,9 @@ class PrefixTest(APITestCase):
self.assertIn('detail', response.data)
def test_create_multiple_available_ips(self):
-
+ """
+ Test the creation of available IP addresses within a parent prefix.
+ """
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/29'), is_pool=True)
url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk})
@@ -679,317 +311,107 @@ class PrefixTest(APITestCase):
self.assertEqual(len(response.data), 8)
-class IPAddressTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1')
- self.ipaddress1 = IPAddress.objects.create(address=IPNetwork('192.168.0.1/24'))
- self.ipaddress2 = IPAddress.objects.create(address=IPNetwork('192.168.0.2/24'))
- self.ipaddress3 = IPAddress.objects.create(address=IPNetwork('192.168.0.3/24'))
-
- def test_get_ipaddress(self):
-
- url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['family']['value'], 4)
- self.assertEqual(response.data['address'], str(self.ipaddress1.address))
-
- def test_list_ipaddresss(self):
-
- url = reverse('ipam-api:ipaddress-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_ipaddresses_brief(self):
-
- url = reverse('ipam-api:ipaddress-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['address', 'family', 'id', 'url']
- )
-
- def test_create_ipaddress(self):
-
- data = {
+class IPAddressTest(APIViewTestCases.APIViewTestCase):
+ model = IPAddress
+ brief_fields = ['address', 'family', 'id', 'url']
+ create_data = [
+ {
'address': '192.168.0.4/24',
- 'vrf': self.vrf1.pk,
- }
+ },
+ {
+ 'address': '192.168.0.5/24',
+ },
+ {
+ 'address': '192.168.0.6/24',
+ },
+ ]
- url = reverse('ipam-api:ipaddress-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(IPAddress.objects.count(), 4)
- ipaddress4 = IPAddress.objects.get(pk=response.data['id'])
- self.assertEqual(str(ipaddress4.address), data['address'])
- self.assertEqual(ipaddress4.vrf_id, data['vrf'])
-
- def test_create_ipaddress_bulk(self):
-
- data = [
- {
- 'address': '192.168.0.4/24',
- },
- {
- 'address': '192.168.0.5/24',
- },
- {
- 'address': '192.168.0.6/24',
- },
- ]
-
- url = reverse('ipam-api:ipaddress-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(IPAddress.objects.count(), 6)
- self.assertEqual(response.data[0]['address'], data[0]['address'])
- self.assertEqual(response.data[1]['address'], data[1]['address'])
- self.assertEqual(response.data[2]['address'], data[2]['address'])
-
- def test_update_ipaddress(self):
-
- data = {
- 'address': '192.168.0.99/24',
- 'vrf': self.vrf1.pk,
- }
-
- url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(IPAddress.objects.count(), 3)
- ipaddress1 = IPAddress.objects.get(pk=response.data['id'])
- self.assertEqual(str(ipaddress1.address), data['address'])
- self.assertEqual(ipaddress1.vrf_id, data['vrf'])
-
- def test_delete_ipaddress(self):
-
- url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(IPAddress.objects.count(), 2)
-
-
-class VLANGroupTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1')
- self.vlangroup1 = VLANGroup.objects.create(name='Test VLAN Group 1', slug='test-vlan-group-1')
- self.vlangroup2 = VLANGroup.objects.create(name='Test VLAN Group 2', slug='test-vlan-group-2')
- self.vlangroup3 = VLANGroup.objects.create(name='Test VLAN Group 3', slug='test-vlan-group-3')
-
- def test_get_vlangroup(self):
-
- url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.vlangroup1.name)
-
- def test_list_vlangroups(self):
-
- url = reverse('ipam-api:vlangroup-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_vlangroups_brief(self):
-
- url = reverse('ipam-api:vlangroup-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'slug', 'url', 'vlan_count']
+ ip_addresses = (
+ IPAddress(address=IPNetwork('192.168.0.1/24')),
+ IPAddress(address=IPNetwork('192.168.0.2/24')),
+ IPAddress(address=IPNetwork('192.168.0.3/24')),
)
-
- def test_create_vlangroup(self):
-
- data = {
- 'name': 'Test VLAN Group 4',
- 'slug': 'test-vlan-group-4',
- 'site': self.site1.pk,
- }
-
- url = reverse('ipam-api:vlangroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VLANGroup.objects.count(), 4)
- vlangroup4 = VLANGroup.objects.get(pk=response.data['id'])
- self.assertEqual(vlangroup4.name, data['name'])
- self.assertEqual(vlangroup4.slug, data['slug'])
-
- def test_create_vlangroup_bulk(self):
-
- data = [
- {
- 'name': 'Test VLAN Group 4',
- 'slug': 'test-vlan-group-4',
- },
- {
- 'name': 'Test VLAN Group 5',
- 'slug': 'test-vlan-group-5',
- },
- {
- 'name': 'Test VLAN Group 6',
- 'slug': 'test-vlan-group-6',
- },
- ]
-
- url = reverse('ipam-api:vlangroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VLANGroup.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_vlangroup(self):
-
- data = {
- 'name': 'Test VLAN Group X',
- 'slug': 'test-vlan-group-x',
- }
-
- url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(VLANGroup.objects.count(), 3)
- vlangroup1 = VLANGroup.objects.get(pk=response.data['id'])
- self.assertEqual(vlangroup1.name, data['name'])
- self.assertEqual(vlangroup1.slug, data['slug'])
-
- def test_delete_vlangroup(self):
-
- url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(VLANGroup.objects.count(), 2)
+ IPAddress.objects.bulk_create(ip_addresses)
-class VLANTest(APITestCase):
+class VLANGroupTest(APIViewTestCases.APIViewTestCase):
+ model = VLANGroup
+ brief_fields = ['id', 'name', 'slug', 'url', 'vlan_count']
+ create_data = [
+ {
+ 'name': 'VLAN Group 4',
+ 'slug': 'vlan-group-4',
+ },
+ {
+ 'name': 'VLAN Group 5',
+ 'slug': 'vlan-group-5',
+ },
+ {
+ 'name': 'VLAN Group 6',
+ 'slug': 'vlan-group-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.group1 = VLANGroup.objects.create(name='Test VLAN Group 1', slug='test-vlan-group-1')
- self.vlan1 = VLAN.objects.create(vid=1, name='Test VLAN 1')
- self.vlan2 = VLAN.objects.create(vid=2, name='Test VLAN 2')
- self.vlan3 = VLAN.objects.create(vid=3, name='Test VLAN 3')
- self.prefix1 = Prefix.objects.create(prefix=IPNetwork('192.168.1.0/24'))
-
- def test_get_vlan(self):
-
- url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.vlan1.name)
-
- def test_list_vlans(self):
-
- url = reverse('ipam-api:vlan-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_vlans_brief(self):
-
- url = reverse('ipam-api:vlan-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['display_name', 'id', 'name', 'url', 'vid']
+ vlan_groups = (
+ VLANGroup(name='VLAN Group 1', slug='vlan-group-1'),
+ VLANGroup(name='VLAN Group 2', slug='vlan-group-2'),
+ VLANGroup(name='VLAN Group 3', slug='vlan-group-3'),
)
+ VLANGroup.objects.bulk_create(vlan_groups)
- def test_create_vlan(self):
- data = {
- 'vid': 4,
- 'name': 'Test VLAN 4',
- 'group': self.group1.pk,
- }
+class VLANTest(APIViewTestCases.APIViewTestCase):
+ model = VLAN
+ brief_fields = ['display_name', 'id', 'name', 'url', 'vid']
- url = reverse('ipam-api:vlan-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VLAN.objects.count(), 4)
- vlan4 = VLAN.objects.get(pk=response.data['id'])
- self.assertEqual(vlan4.vid, data['vid'])
- self.assertEqual(vlan4.name, data['name'])
+ vlan_groups = (
+ VLANGroup(name='VLAN Group 1', slug='vlan-group-1'),
+ VLANGroup(name='VLAN Group 2', slug='vlan-group-2'),
+ )
+ VLANGroup.objects.bulk_create(vlan_groups)
- def test_create_vlan_bulk(self):
+ vlans = (
+ VLAN(name='VLAN 1', vid=1, group=vlan_groups[0]),
+ VLAN(name='VLAN 2', vid=2, group=vlan_groups[0]),
+ VLAN(name='VLAN 3', vid=3, group=vlan_groups[0]),
+ )
+ VLAN.objects.bulk_create(vlans)
- data = [
+ cls.create_data = [
{
'vid': 4,
- 'name': 'Test VLAN 4',
+ 'name': 'VLAN 4',
+ 'group': vlan_groups[1].pk,
},
{
'vid': 5,
- 'name': 'Test VLAN 5',
+ 'name': 'VLAN 5',
+ 'group': vlan_groups[1].pk,
},
{
'vid': 6,
- 'name': 'Test VLAN 6',
+ 'name': 'VLAN 6',
+ 'group': vlan_groups[1].pk,
},
]
- url = reverse('ipam-api:vlan-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VLAN.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_vlan(self):
-
- data = {
- 'vid': 99,
- 'name': 'Test VLAN X',
- }
-
- url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(VLAN.objects.count(), 3)
- vlan1 = VLAN.objects.get(pk=response.data['id'])
- self.assertEqual(vlan1.vid, data['vid'])
- self.assertEqual(vlan1.name, data['name'])
-
- def test_delete_vlan(self):
-
- url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(VLAN.objects.count(), 2)
-
def test_delete_vlan_with_prefix(self):
- self.prefix1.vlan = self.vlan1
- self.prefix1.save()
+ """
+ Attempt and fail to delete a VLAN with a Prefix assigned to it.
+ """
+ vlan = VLAN.objects.first()
+ Prefix.objects.create(prefix=IPNetwork('192.0.2.0/24'), vlan=vlan)
- url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
+ url = reverse('ipam-api:vlan-detail', kwargs={'pk': vlan.pk})
with disable_warnings('django.request'):
response = self.client.delete(url, **self.header)
@@ -1000,125 +422,47 @@ class VLANTest(APITestCase):
self.assertTrue(content['detail'].startswith('Unable to delete object.'))
-class ServiceTest(APITestCase):
+class ServiceTest(APIViewTestCases.APIViewTestCase):
+ model = Service
+ brief_fields = ['id', 'name', 'port', 'protocol', 'url']
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
+ site = Site.objects.create(name='Site 1', slug='site-1')
+ manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
+ devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1')
+ devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
- super().setUp()
-
- site = Site.objects.create(name='Test Site 1', slug='test-site-1')
- manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
- devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device Type 1')
- devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1')
- self.device1 = Device.objects.create(
- name='Test Device 1', site=site, device_type=devicetype, device_role=devicerole
+ devices = (
+ Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole),
+ Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole),
)
- self.device2 = Device.objects.create(
- name='Test Device 2', site=site, device_type=devicetype, device_role=devicerole
- )
- self.service1 = Service.objects.create(
- device=self.device1, name='Test Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1
- )
- self.service1 = Service.objects.create(
- device=self.device1, name='Test Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2
- )
- self.service1 = Service.objects.create(
- device=self.device1, name='Test Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3
+ Device.objects.bulk_create(devices)
+
+ services = (
+ Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1),
+ Service(device=devices[0], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2),
+ Service(device=devices[0], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3),
)
+ Service.objects.bulk_create(services)
- def test_get_service(self):
-
- url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.service1.name)
-
- def test_list_services(self):
-
- url = reverse('ipam-api:service-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_create_service(self):
-
- data = {
- 'device': self.device1.pk,
- 'name': 'Test Service 4',
- 'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
- 'port': 4,
- 'tags': ['Foo', 'Bar'],
- }
-
- url = reverse('ipam-api:service-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Service.objects.count(), 4)
- service4 = Service.objects.get(pk=response.data['id'])
- self.assertEqual(service4.device_id, data['device'])
- self.assertEqual(service4.name, data['name'])
- self.assertEqual(service4.protocol, data['protocol'])
- self.assertEqual(service4.port, data['port'])
- tags = [tag.name for tag in service4.tags.all()]
- self.assertEqual(sorted(tags), sorted(data['tags']))
-
- def test_create_service_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'device': self.device1.pk,
- 'name': 'Test Service 4',
+ 'device': devices[1].pk,
+ 'name': 'Service 4',
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
'port': 4,
},
{
- 'device': self.device1.pk,
- 'name': 'Test Service 5',
+ 'device': devices[1].pk,
+ 'name': 'Service 5',
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
'port': 5,
},
{
- 'device': self.device1.pk,
- 'name': 'Test Service 6',
+ 'device': devices[1].pk,
+ 'name': 'Service 6',
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
'port': 6,
},
]
-
- url = reverse('ipam-api:service-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Service.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_service(self):
-
- data = {
- 'device': self.device2.pk,
- 'name': 'Test Service X',
- 'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
- 'port': 99,
- }
-
- url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Service.objects.count(), 3)
- service1 = Service.objects.get(pk=response.data['id'])
- self.assertEqual(service1.device_id, data['device'])
- self.assertEqual(service1.name, data['name'])
- self.assertEqual(service1.protocol, data['protocol'])
- self.assertEqual(service1.port, data['port'])
-
- def test_delete_service(self):
-
- url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Service.objects.count(), 2)
diff --git a/netbox/secrets/forms.py b/netbox/secrets/forms.py
index 089771bd8..296469900 100644
--- a/netbox/secrets/forms.py
+++ b/netbox/secrets/forms.py
@@ -115,6 +115,16 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm):
'plaintext2': "The two given plaintext values do not match. Please check your input."
})
+ # Validate uniqueness
+ if Secret.objects.filter(
+ device=self.cleaned_data['device'],
+ role=self.cleaned_data['role'],
+ name=self.cleaned_data['name']
+ ).exists():
+ raise forms.ValidationError(
+ "Each secret assigned to a device must have a unique combination of role and name"
+ )
+
class SecretCSVForm(CustomFieldModelCSVForm):
device = CSVModelChoiceField(
diff --git a/netbox/secrets/tests/test_api.py b/netbox/secrets/tests/test_api.py
index 8d716a465..1df052f0f 100644
--- a/netbox/secrets/tests/test_api.py
+++ b/netbox/secrets/tests/test_api.py
@@ -5,7 +5,7 @@ from rest_framework import status
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from secrets.models import Secret, SecretRole, SessionKey, UserKey
-from utilities.testing import APITestCase
+from utilities.testing import APITestCase, APIViewTestCases
from .constants import PRIVATE_KEY, PUBLIC_KEY
@@ -19,107 +19,36 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class SecretRoleTest(APITestCase):
+class SecretRoleTest(APIViewTestCases.APIViewTestCase):
+ model = SecretRole
+ brief_fields = ['id', 'name', 'secret_count', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Secret Role 4',
+ 'slug': 'secret-role-4',
+ },
+ {
+ 'name': 'Secret Role 5',
+ 'slug': 'secret-role-5',
+ },
+ {
+ 'name': 'Secret Role 6',
+ 'slug': 'secret-role-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1')
- self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2')
- self.secretrole3 = SecretRole.objects.create(name='Test Secret Role 3', slug='test-secret-role-3')
-
- def test_get_secretrole(self):
-
- url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.secretrole1.name)
-
- def test_list_secretroles(self):
-
- url = reverse('secrets-api:secretrole-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_secretroles_brief(self):
-
- url = reverse('secrets-api:secretrole-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'secret_count', 'slug', 'url']
+ secret_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'),
)
-
- def test_create_secretrole(self):
-
- data = {
- 'name': 'Test Secret Role 4',
- 'slug': 'test-secret-role-4',
- }
-
- url = reverse('secrets-api:secretrole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(SecretRole.objects.count(), 4)
- secretrole4 = SecretRole.objects.get(pk=response.data['id'])
- self.assertEqual(secretrole4.name, data['name'])
- self.assertEqual(secretrole4.slug, data['slug'])
-
- def test_create_secretrole_bulk(self):
-
- data = [
- {
- 'name': 'Test Secret Role 4',
- 'slug': 'test-secret-role-4',
- },
- {
- 'name': 'Test Secret Role 5',
- 'slug': 'test-secret-role-5',
- },
- {
- 'name': 'Test Secret Role 6',
- 'slug': 'test-secret-role-6',
- },
- ]
-
- url = reverse('secrets-api:secretrole-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(SecretRole.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_secretrole(self):
-
- data = {
- 'name': 'Test SecretRole X',
- 'slug': 'test-secretrole-x',
- }
-
- url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(SecretRole.objects.count(), 3)
- secretrole1 = SecretRole.objects.get(pk=response.data['id'])
- self.assertEqual(secretrole1.name, data['name'])
- self.assertEqual(secretrole1.slug, data['slug'])
-
- def test_delete_secretrole(self):
-
- url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(SecretRole.objects.count(), 2)
+ SecretRole.objects.bulk_create(secret_roles)
+# TODO: Standardize SecretTest
class SecretTest(APITestCase):
def setUp(self):
diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py
index 8da3d7594..b06a8213a 100644
--- a/netbox/tenancy/tests/test_api.py
+++ b/netbox/tenancy/tests/test_api.py
@@ -1,8 +1,7 @@
from django.urls import reverse
-from rest_framework import status
from tenancy.models import Tenant, TenantGroup
-from utilities.testing import APITestCase
+from utilities.testing import APITestCase, APIViewTestCases
class AppTest(APITestCase):
@@ -15,235 +14,74 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class TenantGroupTest(APITestCase):
+class TenantGroupTest(APIViewTestCases.APIViewTestCase):
+ model = TenantGroup
+ brief_fields = ['id', 'name', 'slug', 'tenant_count', 'url']
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.parent_tenant_groups = (
- TenantGroup(name='Parent Tenant Group 1', slug='parent-tenant-group-1'),
- TenantGroup(name='Parent Tenant Group 2', slug='parent-tenant-group-2'),
- )
- for tenantgroup in self.parent_tenant_groups:
- tenantgroup.save()
-
- self.tenant_groups = (
- TenantGroup(name='Tenant Group 1', slug='tenant-group-1', parent=self.parent_tenant_groups[0]),
- TenantGroup(name='Tenant Group 2', slug='tenant-group-2', parent=self.parent_tenant_groups[0]),
- TenantGroup(name='Tenant Group 3', slug='tenant-group-3', parent=self.parent_tenant_groups[0]),
- )
- for tenantgroup in self.tenant_groups:
- tenantgroup.save()
-
- def test_get_tenantgroup(self):
-
- url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.tenant_groups[0].name)
-
- def test_list_tenantgroups(self):
-
- url = reverse('tenancy-api:tenantgroup-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 5)
-
- def test_list_tenantgroups_brief(self):
-
- url = reverse('tenancy-api:tenantgroup-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'slug', 'tenant_count', 'url']
+ parent_tenant_groups = (
+ TenantGroup.objects.create(name='Parent Tenant Group 1', slug='parent-tenant-group-1'),
+ TenantGroup.objects.create(name='Parent Tenant Group 2', slug='parent-tenant-group-2'),
)
- def test_create_tenantgroup(self):
+ TenantGroup.objects.create(name='Tenant Group 1', slug='tenant-group-1', parent=parent_tenant_groups[0])
+ TenantGroup.objects.create(name='Tenant Group 2', slug='tenant-group-2', parent=parent_tenant_groups[0])
+ TenantGroup.objects.create(name='Tenant Group 3', slug='tenant-group-3', parent=parent_tenant_groups[0])
- data = {
- 'name': 'Tenant Group 4',
- 'slug': 'tenant-group-4',
- 'parent': self.parent_tenant_groups[0].pk,
- }
-
- url = reverse('tenancy-api:tenantgroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(TenantGroup.objects.count(), 6)
- tenantgroup4 = TenantGroup.objects.get(pk=response.data['id'])
- self.assertEqual(tenantgroup4.name, data['name'])
- self.assertEqual(tenantgroup4.slug, data['slug'])
- self.assertEqual(tenantgroup4.parent_id, data['parent'])
-
- def test_create_tenantgroup_bulk(self):
-
- data = [
+ cls.create_data = [
{
'name': 'Tenant Group 4',
'slug': 'tenant-group-4',
- 'parent': self.parent_tenant_groups[0].pk,
+ 'parent': parent_tenant_groups[1].pk,
},
{
'name': 'Tenant Group 5',
'slug': 'tenant-group-5',
- 'parent': self.parent_tenant_groups[0].pk,
+ 'parent': parent_tenant_groups[1].pk,
},
{
'name': 'Tenant Group 6',
'slug': 'tenant-group-6',
- 'parent': self.parent_tenant_groups[0].pk,
+ 'parent': parent_tenant_groups[1].pk,
},
]
- url = reverse('tenancy-api:tenantgroup-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(TenantGroup.objects.count(), 8)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class TenantTest(APIViewTestCases.APIViewTestCase):
+ model = Tenant
+ brief_fields = ['id', 'name', 'slug', 'url']
- def test_update_tenantgroup(self):
+ @classmethod
+ def setUpTestData(cls):
- data = {
- 'name': 'Tenant Group X',
- 'slug': 'tenant-group-x',
- 'parent': self.parent_tenant_groups[1].pk,
- }
-
- url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(TenantGroup.objects.count(), 5)
- tenantgroup1 = TenantGroup.objects.get(pk=response.data['id'])
- self.assertEqual(tenantgroup1.name, data['name'])
- self.assertEqual(tenantgroup1.slug, data['slug'])
- self.assertEqual(tenantgroup1.parent_id, data['parent'])
-
- def test_delete_tenantgroup(self):
-
- url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(TenantGroup.objects.count(), 4)
-
-
-class TenantTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.tenant_groups = (
- TenantGroup(name='Tenant Group 1', slug='tenant-group-1'),
- TenantGroup(name='Tenant Group 2', slug='tenant-group-2'),
- )
- for tenantgroup in self.tenant_groups:
- tenantgroup.save()
-
- self.tenants = (
- Tenant(name='Test Tenant 1', slug='test-tenant-1', group=self.tenant_groups[0]),
- Tenant(name='Test Tenant 2', slug='test-tenant-2', group=self.tenant_groups[0]),
- Tenant(name='Test Tenant 3', slug='test-tenant-3', group=self.tenant_groups[0]),
- )
- Tenant.objects.bulk_create(self.tenants)
-
- def test_get_tenant(self):
-
- url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.tenants[0].name)
-
- def test_list_tenants(self):
-
- url = reverse('tenancy-api:tenant-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_tenants_brief(self):
-
- url = reverse('tenancy-api:tenant-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'slug', 'url']
+ tenant_groups = (
+ TenantGroup.objects.create(name='Tenant Group 1', slug='tenant-group-1'),
+ TenantGroup.objects.create(name='Tenant Group 2', slug='tenant-group-2'),
)
- def test_create_tenant(self):
+ tenants = (
+ Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]),
+ Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[0]),
+ Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[0]),
+ )
+ Tenant.objects.bulk_create(tenants)
- data = {
- 'name': 'Test Tenant 4',
- 'slug': 'test-tenant-4',
- 'group': self.tenant_groups[0].pk,
- }
-
- url = reverse('tenancy-api:tenant-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Tenant.objects.count(), 4)
- tenant4 = Tenant.objects.get(pk=response.data['id'])
- self.assertEqual(tenant4.name, data['name'])
- self.assertEqual(tenant4.slug, data['slug'])
- self.assertEqual(tenant4.group_id, data['group'])
-
- def test_create_tenant_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Tenant 4',
- 'slug': 'test-tenant-4',
+ 'name': 'Tenant 4',
+ 'slug': 'tenant-4',
+ 'group': tenant_groups[1].pk,
},
{
- 'name': 'Test Tenant 5',
- 'slug': 'test-tenant-5',
+ 'name': 'Tenant 5',
+ 'slug': 'tenant-5',
+ 'group': tenant_groups[1].pk,
},
{
- 'name': 'Test Tenant 6',
- 'slug': 'test-tenant-6',
+ 'name': 'Tenant 6',
+ 'slug': 'tenant-6',
+ 'group': tenant_groups[1].pk,
},
]
-
- url = reverse('tenancy-api:tenant-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Tenant.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_tenant(self):
-
- data = {
- 'name': 'Test Tenant X',
- 'slug': 'test-tenant-x',
- 'group': self.tenant_groups[1].pk,
- }
-
- url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Tenant.objects.count(), 3)
- tenant1 = Tenant.objects.get(pk=response.data['id'])
- self.assertEqual(tenant1.name, data['name'])
- self.assertEqual(tenant1.slug, data['slug'])
- self.assertEqual(tenant1.group_id, data['group'])
-
- def test_delete_tenant(self):
-
- url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Tenant.objects.count(), 2)
diff --git a/netbox/utilities/testing/testcases.py b/netbox/utilities/testing/testcases.py
index 0db0ff936..dabadc2fa 100644
--- a/netbox/utilities/testing/testcases.py
+++ b/netbox/utilities/testing/testcases.py
@@ -1,9 +1,11 @@
-from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
+from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.forms.models import model_to_dict
from django.test import Client, TestCase as _TestCase, override_settings
from django.urls import reverse, NoReverseMatch
+from netaddr import IPNetwork
+from rest_framework import status
from rest_framework.test import APIClient
from users.models import ObjectPermission, Token
@@ -52,6 +54,49 @@ class TestCase(_TestCase):
expected_status, response.status_code, getattr(response, 'data', 'No data')
))
+ def assertInstanceEqual(self, instance, data, api=False):
+ """
+ Compare a model instance to a dictionary, checking that its attribute values match those specified
+ in the dictionary.
+
+ :instance: Python object instance
+ :data: Dictionary of test data used to define the instance
+ :api: Set to True is the data is a JSON representation of the instance
+ """
+ model_dict = model_to_dict(instance, fields=data.keys())
+
+ for key, value in list(model_dict.items()):
+
+ # TODO: Differentiate between tags assigned to the instance and a M2M field for tags (ex: ConfigContext)
+ if key == 'tags':
+ model_dict[key] = ','.join(sorted([tag.name for tag in value]))
+
+ # Convert ManyToManyField to list of instance PKs
+ elif model_dict[key] and type(value) in (list, tuple) and hasattr(value[0], 'pk'):
+ model_dict[key] = [obj.pk for obj in value]
+
+ if api:
+
+ # Replace ContentType numeric IDs with .
+ if type(getattr(instance, key)) is ContentType:
+ ct = ContentType.objects.get(pk=value)
+ model_dict[key] = f'{ct.app_label}.{ct.model}'
+
+ # Convert IPNetwork instances to strings
+ if type(value) is IPNetwork:
+ model_dict[key] = str(value)
+
+ # Omit any dictionary keys which are not instance attributes
+ relevant_data = {
+ k: v for k, v in data.items() if hasattr(instance, k)
+ }
+
+ self.assertDictEqual(model_dict, relevant_data)
+
+
+#
+# UI Tests
+#
class ModelViewTestCase(TestCase):
"""
@@ -99,42 +144,6 @@ class ModelViewTestCase(TestCase):
else:
raise Exception("Invalid action for URL resolution: {}".format(action))
- def assertInstanceEqual(self, instance, data):
- """
- Compare a model instance to a dictionary, checking that its attribute values match those specified
- in the dictionary.
- """
- model_dict = model_to_dict(instance, fields=data.keys())
-
- for key in list(model_dict.keys()):
-
- # TODO: Differentiate between tags assigned to the instance and a M2M field for tags (ex: ConfigContext)
- if key == 'tags':
- model_dict[key] = ','.join(sorted([tag.name for tag in model_dict['tags']]))
-
- # Convert ManyToManyField to list of instance PKs
- elif model_dict[key] and type(model_dict[key]) in (list, tuple) and hasattr(model_dict[key][0], 'pk'):
- model_dict[key] = [obj.pk for obj in model_dict[key]]
-
- # Omit any dictionary keys which are not instance attributes
- relevant_data = {
- k: v for k, v in data.items() if hasattr(instance, k)
- }
-
- self.assertDictEqual(model_dict, relevant_data)
-
-
-class APITestCase(TestCase):
- client_class = APIClient
-
- def setUp(self):
- """
- Create a superuser and token for API calls.
- """
- self.user = User.objects.create(username='testuser', is_superuser=True)
- self.token = Token.objects.create(user=self.user)
- self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(self.token.key)}
-
class ViewTestCases:
"""
@@ -193,6 +202,13 @@ class ViewTestCases:
# Try GET to non-permitted object
self.assertHttpStatus(self.client.get(instance2.get_absolute_url()), 404)
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
+ def test_get_object_anonymous(self):
+ # Make the request as an unauthenticated user
+ self.client.logout()
+ response = self.client.get(self.model.objects.first().get_absolute_url())
+ self.assertHttpStatus(response, 200)
+
class CreateObjectViewTestCase(ModelViewTestCase):
"""
Create a single new instance.
@@ -783,3 +799,129 @@ class ViewTestCases:
TestCase suitable for testing device component models (ConsolePorts, Interfaces, etc.)
"""
maxDiff = None
+
+
+#
+# REST API Tests
+#
+
+class APITestCase(TestCase):
+ client_class = APIClient
+ model = None
+
+ def setUp(self):
+ """
+ Create a superuser and token for API calls.
+ """
+ self.user = User.objects.create(username='testuser', is_superuser=True)
+ self.token = Token.objects.create(user=self.user)
+ self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(self.token.key)}
+
+ def _get_detail_url(self, instance):
+ viewname = f'{instance._meta.app_label}-api:{instance._meta.model_name}-detail'
+ return reverse(viewname, kwargs={'pk': instance.pk})
+
+ def _get_list_url(self):
+ viewname = f'{self.model._meta.app_label}-api:{self.model._meta.model_name}-list'
+ return reverse(viewname)
+
+
+class APIViewTestCases:
+
+ class GetObjectViewTestCase(APITestCase):
+
+ def test_get_object(self):
+ """
+ GET a single object identified by its numeric ID.
+ """
+ instance = self.model.objects.first()
+ url = self._get_detail_url(instance)
+ response = self.client.get(url, **self.header)
+
+ self.assertEqual(response.data['id'], instance.pk)
+
+ class ListObjectsViewTestCase(APITestCase):
+ brief_fields = []
+
+ def test_list_objects(self):
+ """
+ GET a list of objects.
+ """
+ url = self._get_list_url()
+ response = self.client.get(url, **self.header)
+
+ self.assertEqual(len(response.data['results']), self.model.objects.count())
+
+ def test_list_objects_brief(self):
+ """
+ GET a list of objects using the "brief" parameter.
+ """
+ url = f'{self._get_list_url()}?brief=1'
+ response = self.client.get(url, **self.header)
+
+ self.assertEqual(len(response.data['results']), self.model.objects.count())
+ self.assertEqual(sorted(response.data['results'][0]), self.brief_fields)
+
+ class CreateObjectViewTestCase(APITestCase):
+ create_data = []
+
+ def test_create_object(self):
+ """
+ POST a single object.
+ """
+ initial_count = self.model.objects.count()
+ url = self._get_list_url()
+ response = self.client.post(url, self.create_data[0], format='json', **self.header)
+
+ self.assertHttpStatus(response, status.HTTP_201_CREATED)
+ self.assertEqual(self.model.objects.count(), initial_count + 1)
+ self.assertInstanceEqual(self.model.objects.get(pk=response.data['id']), self.create_data[0], api=True)
+
+ def test_bulk_create_object(self):
+ """
+ POST a set of objects in a single request.
+ """
+ initial_count = self.model.objects.count()
+ url = self._get_list_url()
+ response = self.client.post(url, self.create_data, format='json', **self.header)
+
+ self.assertHttpStatus(response, status.HTTP_201_CREATED)
+ self.assertEqual(self.model.objects.count(), initial_count + len(self.create_data))
+
+ class UpdateObjectViewTestCase(APITestCase):
+ update_data = {}
+
+ def test_update_object(self):
+ """
+ PATCH a single object identified by its numeric ID.
+ """
+ instance = self.model.objects.first()
+ url = self._get_detail_url(instance)
+ update_data = self.update_data or getattr(self, 'create_data')[0]
+ response = self.client.patch(url, update_data, format='json', **self.header)
+
+ self.assertHttpStatus(response, status.HTTP_200_OK)
+ instance.refresh_from_db()
+ self.assertInstanceEqual(instance, self.update_data, api=True)
+
+ class DeleteObjectViewTestCase(APITestCase):
+
+ def test_delete_object(self):
+ """
+ DELETE a single object identified by its numeric ID.
+ """
+ instance = self.model.objects.first()
+ url = self._get_detail_url(instance)
+ response = self.client.delete(url, **self.header)
+
+ self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
+ self.assertFalse(self.model.objects.filter(pk=instance.pk).exists())
+
+ class APIViewTestCase(
+ GetObjectViewTestCase,
+ ListObjectsViewTestCase,
+ CreateObjectViewTestCase,
+ UpdateObjectViewTestCase,
+ DeleteObjectViewTestCase
+ ):
+ pass
diff --git a/netbox/virtualization/tests/test_api.py b/netbox/virtualization/tests/test_api.py
index 8568e21e9..e436a46c5 100644
--- a/netbox/virtualization/tests/test_api.py
+++ b/netbox/virtualization/tests/test_api.py
@@ -1,11 +1,10 @@
from django.urls import reverse
-from netaddr import IPNetwork
from rest_framework import status
from dcim.choices import InterfaceModeChoices
from dcim.models import Interface
-from ipam.models import IPAddress, VLAN
-from utilities.testing import APITestCase, disable_warnings
+from ipam.models import VLAN
+from utilities.testing import APITestCase, APIViewTestCases
from virtualization.choices import *
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@@ -20,487 +19,181 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
-class ClusterTypeTest(APITestCase):
+class ClusterTypeTest(APIViewTestCases.APIViewTestCase):
+ model = ClusterType
+ brief_fields = ['cluster_count', 'id', 'name', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Cluster Type 4',
+ 'slug': 'cluster-type-4',
+ },
+ {
+ 'name': 'Cluster Type 5',
+ 'slug': 'cluster-type-5',
+ },
+ {
+ 'name': 'Cluster Type 6',
+ 'slug': 'cluster-type-6',
+ },
+ ]
- def setUp(self):
+ @classmethod
+ def setUpTestData(cls):
- super().setUp()
-
- self.clustertype1 = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1')
- self.clustertype2 = ClusterType.objects.create(name='Test Cluster Type 2', slug='test-cluster-type-2')
- self.clustertype3 = ClusterType.objects.create(name='Test Cluster Type 3', slug='test-cluster-type-3')
-
- def test_get_clustertype(self):
-
- url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.clustertype1.name)
-
- def test_list_clustertypes(self):
-
- url = reverse('virtualization-api:clustertype-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_clustertypes_brief(self):
-
- url = reverse('virtualization-api:clustertype-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cluster_count', 'id', 'name', 'slug', 'url']
+ cluster_types = (
+ ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
+ ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
+ ClusterType(name='Cluster Type 3', slug='cluster-type-3'),
)
+ ClusterType.objects.bulk_create(cluster_types)
- def test_create_clustertype(self):
- data = {
- 'name': 'Test Cluster Type 4',
- 'slug': 'test-cluster-type-4',
- }
+class ClusterGroupTest(APIViewTestCases.APIViewTestCase):
+ model = ClusterGroup
+ brief_fields = ['cluster_count', 'id', 'name', 'slug', 'url']
+ create_data = [
+ {
+ 'name': 'Cluster Group 4',
+ 'slug': 'cluster-type-4',
+ },
+ {
+ 'name': 'Cluster Group 5',
+ 'slug': 'cluster-type-5',
+ },
+ {
+ 'name': 'Cluster Group 6',
+ 'slug': 'cluster-type-6',
+ },
+ ]
- url = reverse('virtualization-api:clustertype-list')
- response = self.client.post(url, data, format='json', **self.header)
+ @classmethod
+ def setUpTestData(cls):
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ClusterType.objects.count(), 4)
- clustertype4 = ClusterType.objects.get(pk=response.data['id'])
- self.assertEqual(clustertype4.name, data['name'])
- self.assertEqual(clustertype4.slug, data['slug'])
+ cluster_Groups = (
+ ClusterGroup(name='Cluster Group 1', slug='cluster-type-1'),
+ ClusterGroup(name='Cluster Group 2', slug='cluster-type-2'),
+ ClusterGroup(name='Cluster Group 3', slug='cluster-type-3'),
+ )
+ ClusterGroup.objects.bulk_create(cluster_Groups)
- def test_create_clustertype_bulk(self):
- data = [
+class ClusterTest(APIViewTestCases.APIViewTestCase):
+ model = Cluster
+ brief_fields = ['id', 'name', 'url', 'virtualmachine_count']
+
+ @classmethod
+ def setUpTestData(cls):
+
+ cluster_types = (
+ ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
+ ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
+ )
+ ClusterType.objects.bulk_create(cluster_types)
+
+ cluster_groups = (
+ ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
+ ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
+ )
+ ClusterGroup.objects.bulk_create(cluster_groups)
+
+ clusters = (
+ Cluster(name='Cluster 1', type=cluster_types[0], group=cluster_groups[0]),
+ Cluster(name='Cluster 2', type=cluster_types[0], group=cluster_groups[0]),
+ Cluster(name='Cluster 3', type=cluster_types[0], group=cluster_groups[0]),
+ )
+ Cluster.objects.bulk_create(clusters)
+
+ cls.create_data = [
{
- 'name': 'Test Cluster Type 4',
- 'slug': 'test-cluster-type-4',
+ 'name': 'Cluster 4',
+ 'type': cluster_types[1].pk,
+ 'group': cluster_groups[1].pk,
},
{
- 'name': 'Test Cluster Type 5',
- 'slug': 'test-cluster-type-5',
+ 'name': 'Cluster 5',
+ 'type': cluster_types[1].pk,
+ 'group': cluster_groups[1].pk,
},
{
- 'name': 'Test Cluster Type 6',
- 'slug': 'test-cluster-type-6',
+ 'name': 'Cluster 6',
+ 'type': cluster_types[1].pk,
+ 'group': cluster_groups[1].pk,
},
]
- url = reverse('virtualization-api:clustertype-list')
- response = self.client.post(url, data, format='json', **self.header)
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ClusterType.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
+class VirtualMachineTest(APIViewTestCases.APIViewTestCase):
+ model = VirtualMachine
+ brief_fields = ['id', 'name', 'url']
- def test_update_clustertype(self):
+ @classmethod
+ def setUpTestData(cls):
+ clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
+ clustergroup = ClusterGroup.objects.create(name='Cluster Group 1', slug='cluster-group-1')
- data = {
- 'name': 'Test Cluster Type X',
- 'slug': 'test-cluster-type-x',
- }
-
- url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ClusterType.objects.count(), 3)
- clustertype1 = ClusterType.objects.get(pk=response.data['id'])
- self.assertEqual(clustertype1.name, data['name'])
- self.assertEqual(clustertype1.slug, data['slug'])
-
- def test_delete_clustertype(self):
-
- url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ClusterType.objects.count(), 2)
-
-
-class ClusterGroupTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- self.clustergroup1 = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1')
- self.clustergroup2 = ClusterGroup.objects.create(name='Test Cluster Group 2', slug='test-cluster-group-2')
- self.clustergroup3 = ClusterGroup.objects.create(name='Test Cluster Group 3', slug='test-cluster-group-3')
-
- def test_get_clustergroup(self):
-
- url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.clustergroup1.name)
-
- def test_list_clustergroups(self):
-
- url = reverse('virtualization-api:clustergroup-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_clustergroups_brief(self):
-
- url = reverse('virtualization-api:clustergroup-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['cluster_count', 'id', 'name', 'slug', 'url']
+ clusters = (
+ Cluster(name='Cluster 1', type=clustertype, group=clustergroup),
+ Cluster(name='Cluster 2', type=clustertype, group=clustergroup),
)
+ Cluster.objects.bulk_create(clusters)
- def test_create_clustergroup(self):
+ virtual_machines = (
+ VirtualMachine(name='Virtual Machine 1', cluster=clusters[0], local_context_data={'A': 1}),
+ VirtualMachine(name='Virtual Machine 2', cluster=clusters[0], local_context_data={'B': 2}),
+ VirtualMachine(name='Virtual Machine 3', cluster=clusters[0], local_context_data={'C': 3}),
+ )
+ VirtualMachine.objects.bulk_create(virtual_machines)
- data = {
- 'name': 'Test Cluster Group 4',
- 'slug': 'test-cluster-group-4',
- }
-
- url = reverse('virtualization-api:clustergroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ClusterGroup.objects.count(), 4)
- clustergroup4 = ClusterGroup.objects.get(pk=response.data['id'])
- self.assertEqual(clustergroup4.name, data['name'])
- self.assertEqual(clustergroup4.slug, data['slug'])
-
- def test_create_clustergroup_bulk(self):
-
- data = [
+ cls.create_data = [
{
- 'name': 'Test Cluster Group 4',
- 'slug': 'test-cluster-group-4',
+ 'name': 'Virtual Machine 4',
+ 'cluster': clusters[1].pk,
},
{
- 'name': 'Test Cluster Group 5',
- 'slug': 'test-cluster-group-5',
+ 'name': 'Virtual Machine 5',
+ 'cluster': clusters[1].pk,
},
{
- 'name': 'Test Cluster Group 6',
- 'slug': 'test-cluster-group-6',
+ 'name': 'Virtual Machine 6',
+ 'cluster': clusters[1].pk,
},
]
- url = reverse('virtualization-api:clustergroup-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(ClusterGroup.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_clustergroup(self):
-
- data = {
- 'name': 'Test Cluster Group X',
- 'slug': 'test-cluster-group-x',
- }
-
- url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(ClusterGroup.objects.count(), 3)
- clustergroup1 = ClusterGroup.objects.get(pk=response.data['id'])
- self.assertEqual(clustergroup1.name, data['name'])
- self.assertEqual(clustergroup1.slug, data['slug'])
-
- def test_delete_clustergroup(self):
-
- url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(ClusterGroup.objects.count(), 2)
-
-
-class ClusterTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1')
- cluster_group = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1')
-
- self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type, group=cluster_group)
- self.cluster2 = Cluster.objects.create(name='Test Cluster 2', type=cluster_type, group=cluster_group)
- self.cluster3 = Cluster.objects.create(name='Test Cluster 3', type=cluster_type, group=cluster_group)
-
- def test_get_cluster(self):
-
- url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.cluster1.name)
-
- def test_list_clusters(self):
-
- url = reverse('virtualization-api:cluster-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 3)
-
- def test_list_clusters_brief(self):
-
- url = reverse('virtualization-api:cluster-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'url', 'virtualmachine_count']
- )
-
- def test_create_cluster(self):
-
- data = {
- 'name': 'Test Cluster 4',
- 'type': ClusterType.objects.first().pk,
- 'group': ClusterGroup.objects.first().pk,
- }
-
- url = reverse('virtualization-api:cluster-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Cluster.objects.count(), 4)
- cluster4 = Cluster.objects.get(pk=response.data['id'])
- self.assertEqual(cluster4.name, data['name'])
- self.assertEqual(cluster4.type.pk, data['type'])
- self.assertEqual(cluster4.group.pk, data['group'])
-
- def test_create_cluster_bulk(self):
-
- data = [
- {
- 'name': 'Test Cluster 4',
- 'type': ClusterType.objects.first().pk,
- 'group': ClusterGroup.objects.first().pk,
- },
- {
- 'name': 'Test Cluster 5',
- 'type': ClusterType.objects.first().pk,
- 'group': ClusterGroup.objects.first().pk,
- },
- {
- 'name': 'Test Cluster 6',
- 'type': ClusterType.objects.first().pk,
- 'group': ClusterGroup.objects.first().pk,
- },
- ]
-
- url = reverse('virtualization-api:cluster-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(Cluster.objects.count(), 6)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_cluster(self):
-
- cluster_type2 = ClusterType.objects.create(name='Test Cluster Type 2', slug='test-cluster-type-2')
- cluster_group2 = ClusterGroup.objects.create(name='Test Cluster Group 2', slug='test-cluster-group-2')
- data = {
- 'name': 'Test Cluster X',
- 'type': cluster_type2.pk,
- 'group': cluster_group2.pk,
- }
-
- url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(Cluster.objects.count(), 3)
- cluster1 = Cluster.objects.get(pk=response.data['id'])
- self.assertEqual(cluster1.name, data['name'])
- self.assertEqual(cluster1.type.pk, data['type'])
- self.assertEqual(cluster1.group.pk, data['group'])
-
- def test_delete_cluster(self):
-
- url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(Cluster.objects.count(), 2)
-
-
-class VirtualMachineTest(APITestCase):
-
- def setUp(self):
-
- super().setUp()
-
- cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1')
- cluster_group = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1')
- self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type, group=cluster_group)
-
- self.virtualmachine1 = VirtualMachine.objects.create(name='Test Virtual Machine 1', cluster=self.cluster1)
- self.virtualmachine2 = VirtualMachine.objects.create(name='Test Virtual Machine 2', cluster=self.cluster1)
- self.virtualmachine3 = VirtualMachine.objects.create(name='Test Virtual Machine 3', cluster=self.cluster1)
- self.virtualmachine_with_context_data = VirtualMachine.objects.create(
- name='VM with context data',
- cluster=self.cluster1,
- local_context_data={
- 'A': 1,
- 'B': 2
- }
- )
-
- def test_get_virtualmachine(self):
-
- url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk})
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['name'], self.virtualmachine1.name)
-
- def test_list_virtualmachines(self):
-
- url = reverse('virtualization-api:virtualmachine-list')
- response = self.client.get(url, **self.header)
-
- self.assertEqual(response.data['count'], 4)
-
- def test_list_virtualmachines_brief(self):
-
- url = reverse('virtualization-api:virtualmachine-list')
- response = self.client.get('{}?brief=1'.format(url), **self.header)
-
- self.assertEqual(
- sorted(response.data['results'][0]),
- ['id', 'name', 'url']
- )
-
- def test_create_virtualmachine(self):
-
- data = {
- 'name': 'Test Virtual Machine 4',
- 'cluster': self.cluster1.pk,
- }
-
- url = reverse('virtualization-api:virtualmachine-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VirtualMachine.objects.count(), 5)
- virtualmachine4 = VirtualMachine.objects.get(pk=response.data['id'])
- self.assertEqual(virtualmachine4.name, data['name'])
- self.assertEqual(virtualmachine4.cluster.pk, data['cluster'])
-
- def test_create_virtualmachine_without_cluster(self):
-
- data = {
- 'name': 'Test Virtual Machine 4',
- }
-
- url = reverse('virtualization-api:virtualmachine-list')
- with disable_warnings('django.request'):
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
- self.assertEqual(VirtualMachine.objects.count(), 4)
-
- def test_create_virtualmachine_bulk(self):
-
- data = [
- {
- 'name': 'Test Virtual Machine 4',
- 'cluster': self.cluster1.pk,
- },
- {
- 'name': 'Test Virtual Machine 5',
- 'cluster': self.cluster1.pk,
- },
- {
- 'name': 'Test Virtual Machine 6',
- 'cluster': self.cluster1.pk,
- },
- ]
-
- url = reverse('virtualization-api:virtualmachine-list')
- response = self.client.post(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
- self.assertEqual(VirtualMachine.objects.count(), 7)
- self.assertEqual(response.data[0]['name'], data[0]['name'])
- self.assertEqual(response.data[1]['name'], data[1]['name'])
- self.assertEqual(response.data[2]['name'], data[2]['name'])
-
- def test_update_virtualmachine(self):
-
- interface = Interface.objects.create(name='Test Interface 1', virtual_machine=self.virtualmachine1)
- ip4_address = IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), interface=interface)
- ip6_address = IPAddress.objects.create(address=IPNetwork('2001:db8::1/64'), interface=interface)
-
- cluster2 = Cluster.objects.create(
- name='Test Cluster 2',
- type=ClusterType.objects.first(),
- group=ClusterGroup.objects.first()
- )
- data = {
- 'name': 'Test Virtual Machine X',
- 'cluster': cluster2.pk,
- 'primary_ip4': ip4_address.pk,
- 'primary_ip6': ip6_address.pk,
- }
-
- url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk})
- response = self.client.put(url, data, format='json', **self.header)
-
- self.assertHttpStatus(response, status.HTTP_200_OK)
- self.assertEqual(VirtualMachine.objects.count(), 4)
- virtualmachine1 = VirtualMachine.objects.get(pk=response.data['id'])
- self.assertEqual(virtualmachine1.name, data['name'])
- self.assertEqual(virtualmachine1.cluster.pk, data['cluster'])
- self.assertEqual(virtualmachine1.primary_ip4.pk, data['primary_ip4'])
- self.assertEqual(virtualmachine1.primary_ip6.pk, data['primary_ip6'])
-
- def test_delete_virtualmachine(self):
-
- url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk})
- response = self.client.delete(url, **self.header)
-
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
- self.assertEqual(VirtualMachine.objects.count(), 3)
-
def test_config_context_included_by_default_in_list_view(self):
-
+ """
+ Check that config context data is included by default in the virtual machines list.
+ """
+ virtualmachine = VirtualMachine.objects.first()
url = reverse('virtualization-api:virtualmachine-list')
- url = '{}?id={}'.format(url, self.virtualmachine_with_context_data.pk)
+ url = '{}?id={}'.format(url, virtualmachine.pk)
response = self.client.get(url, **self.header)
self.assertEqual(response.data['results'][0].get('config_context', {}).get('A'), 1)
def test_config_context_excluded(self):
-
+ """
+ Check that config context data can be excluded by passing ?exclude=config_context.
+ """
url = reverse('virtualization-api:virtualmachine-list') + '?exclude=config_context'
response = self.client.get(url, **self.header)
self.assertFalse('config_context' in response.data['results'][0])
def test_unique_name_per_cluster_constraint(self):
-
+ """
+ Check that creating a virtual machine with a duplicate name fails.
+ """
data = {
- 'name': 'Test Virtual Machine 1',
- 'cluster': self.cluster1.pk,
+ 'name': 'Virtual Machine 1',
+ 'cluster': Cluster.objects.first().pk,
}
-
url = reverse('virtualization-api:virtualmachine-list')
response = self.client.post(url, data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+# TODO: Standardize InterfaceTest (pending #4721)
class InterfaceTest(APITestCase):
def setUp(self):
diff --git a/netbox/virtualization/tests/test_views.py b/netbox/virtualization/tests/test_views.py
index 5cd19381f..9fde12186 100644
--- a/netbox/virtualization/tests/test_views.py
+++ b/netbox/virtualization/tests/test_views.py
@@ -187,6 +187,7 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
# TODO: Update base class to DeviceComponentViewTestCase
class InterfaceTestCase(
+ ViewTestCases.GetObjectViewTestCase,
ViewTestCases.EditObjectViewTestCase,
ViewTestCases.DeleteObjectViewTestCase,
ViewTestCases.BulkCreateObjectsViewTestCase,