Ver Fonte

Merge pull request #3756 from netbox-community/csv-import-tests

CSV import tests
Jeremy Stretch há 6 anos atrás
pai
commit
93837c5b9e

+ 60 - 3
netbox/circuits/tests/test_views.py

@@ -10,7 +10,12 @@ from utilities.testing import create_test_user
 class ProviderTestCase(TestCase):
 class ProviderTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['circuits.view_provider'])
+        user = create_test_user(
+            permissions=[
+                'circuits.view_provider',
+                'circuits.add_provider',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -36,11 +41,30 @@ class ProviderTestCase(TestCase):
         response = self.client.get(provider.get_absolute_url())
         response = self.client.get(provider.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_provider_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Provider 4,provider-4",
+            "Provider 5,provider-5",
+            "Provider 6,provider-6",
+        )
+
+        response = self.client.post(reverse('circuits:provider_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Provider.objects.count(), 6)
+
 
 
 class CircuitTypeTestCase(TestCase):
 class CircuitTypeTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['circuits.view_circuittype'])
+        user = create_test_user(
+            permissions=[
+                'circuits.view_circuittype',
+                'circuits.add_circuittype',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -57,11 +81,30 @@ class CircuitTypeTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_circuittype_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Circuit Type 4,circuit-type-4",
+            "Circuit Type 5,circuit-type-5",
+            "Circuit Type 6,circuit-type-6",
+        )
+
+        response = self.client.post(reverse('circuits:circuittype_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(CircuitType.objects.count(), 6)
+
 
 
 class CircuitTestCase(TestCase):
 class CircuitTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['circuits.view_circuit'])
+        user = create_test_user(
+            permissions=[
+                'circuits.view_circuit',
+                'circuits.add_circuit',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -93,3 +136,17 @@ class CircuitTestCase(TestCase):
         circuit = Circuit.objects.first()
         circuit = Circuit.objects.first()
         response = self.client.get(circuit.get_absolute_url())
         response = self.client.get(circuit.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
+
+    def test_circuit_import(self):
+
+        csv_data = (
+            "cid,provider,type",
+            "Circuit 4,Provider 1,Circuit Type 1",
+            "Circuit 5,Provider 1,Circuit Type 1",
+            "Circuit 6,Provider 1,Circuit Type 1",
+        )
+
+        response = self.client.post(reverse('circuits:circuit_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Circuit.objects.count(), 6)

+ 689 - 16
netbox/dcim/tests/test_views.py

@@ -5,18 +5,19 @@ from django.urls import reverse
 
 
 from dcim.choices import *
 from dcim.choices import *
 from dcim.constants import *
 from dcim.constants import *
-from dcim.models import (
-    Cable, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceBayTemplate, DeviceRole, DeviceType,
-    FrontPortTemplate, Interface, InterfaceTemplate, InventoryItem, Manufacturer, Platform, PowerPortTemplate,
-    PowerOutletTemplate, Rack, RackGroup, RackReservation, RackRole, RearPortTemplate, Site, Region, VirtualChassis,
-)
+from dcim.models import *
 from utilities.testing import create_test_user
 from utilities.testing import create_test_user
 
 
 
 
 class RegionTestCase(TestCase):
 class RegionTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_region'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_region',
+                'dcim.add_region',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -31,11 +32,30 @@ class RegionTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_region_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Region 4,region-4",
+            "Region 5,region-5",
+            "Region 6,region-6",
+        )
+
+        response = self.client.post(reverse('dcim:region_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Region.objects.count(), 6)
+
 
 
 class SiteTestCase(TestCase):
 class SiteTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_site'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_site',
+                'dcim.add_site',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -64,11 +84,30 @@ class SiteTestCase(TestCase):
         response = self.client.get(site.get_absolute_url())
         response = self.client.get(site.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_site_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Site 4,site-4",
+            "Site 5,site-5",
+            "Site 6,site-6",
+        )
+
+        response = self.client.post(reverse('dcim:site_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Site.objects.count(), 6)
+
 
 
 class RackGroupTestCase(TestCase):
 class RackGroupTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_rackgroup'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_rackgroup',
+                'dcim.add_rackgroup',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -88,11 +127,30 @@ class RackGroupTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_rackgroup_import(self):
+
+        csv_data = (
+            "site,name,slug",
+            "Site 1,Rack Group 4,rack-group-4",
+            "Site 1,Rack Group 5,rack-group-5",
+            "Site 1,Rack Group 6,rack-group-6",
+        )
+
+        response = self.client.post(reverse('dcim:rackgroup_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(RackGroup.objects.count(), 6)
+
 
 
 class RackRoleTestCase(TestCase):
 class RackRoleTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_rackrole'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_rackrole',
+                'dcim.add_rackrole',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -109,6 +167,20 @@ class RackRoleTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_rackrole_import(self):
+
+        csv_data = (
+            "name,slug,color",
+            "Rack Role 4,rack-role-4,ff0000",
+            "Rack Role 5,rack-role-5,00ff00",
+            "Rack Role 6,rack-role-6,0000ff",
+        )
+
+        response = self.client.post(reverse('dcim:rackrole_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(RackRole.objects.count(), 6)
+
 
 
 class RackReservationTestCase(TestCase):
 class RackReservationTestCase(TestCase):
 
 
@@ -140,7 +212,12 @@ class RackReservationTestCase(TestCase):
 class RackTestCase(TestCase):
 class RackTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_rack'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_rack',
+                'dcim.add_rack',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -169,11 +246,30 @@ class RackTestCase(TestCase):
         response = self.client.get(rack.get_absolute_url())
         response = self.client.get(rack.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_rack_import(self):
+
+        csv_data = (
+            "site,name,width,u_height",
+            "Site 1,Rack 4,19,42",
+            "Site 1,Rack 5,19,42",
+            "Site 1,Rack 6,19,42",
+        )
+
+        response = self.client.post(reverse('dcim:rack_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Rack.objects.count(), 6)
+
 
 
 class ManufacturerTypeTestCase(TestCase):
 class ManufacturerTypeTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_manufacturer'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_manufacturer',
+                'dcim.add_manufacturer',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -190,6 +286,20 @@ class ManufacturerTypeTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_manufacturer_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Manufacturer 4,manufacturer-4",
+            "Manufacturer 5,manufacturer-5",
+            "Manufacturer 6,manufacturer-6",
+        )
+
+        response = self.client.post(reverse('dcim:manufacturer_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Manufacturer.objects.count(), 6)
+
 
 
 class DeviceTypeTestCase(TestCase):
 class DeviceTypeTestCase(TestCase):
 
 
@@ -369,7 +479,12 @@ device-bays:
 class DeviceRoleTestCase(TestCase):
 class DeviceRoleTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_devicerole'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_devicerole',
+                'dcim.add_devicerole',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -386,11 +501,30 @@ class DeviceRoleTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_devicerole_import(self):
+
+        csv_data = (
+            "name,slug,color",
+            "Device Role 4,device-role-4,ff0000",
+            "Device Role 5,device-role-5,00ff00",
+            "Device Role 6,device-role-6,0000ff",
+        )
+
+        response = self.client.post(reverse('dcim:devicerole_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(DeviceRole.objects.count(), 6)
+
 
 
 class PlatformTestCase(TestCase):
 class PlatformTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_platform'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_platform',
+                'dcim.add_platform',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -407,11 +541,30 @@ class PlatformTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_platform_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Platform 4,platform-4",
+            "Platform 5,platform-5",
+            "Platform 6,platform-6",
+        )
+
+        response = self.client.post(reverse('dcim:platform_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Platform.objects.count(), 6)
+
 
 
 class DeviceTestCase(TestCase):
 class DeviceTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_device'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_device',
+                'dcim.add_device',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -450,11 +603,486 @@ class DeviceTestCase(TestCase):
         response = self.client.get(device.get_absolute_url())
         response = self.client.get(device.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_device_import(self):
+
+        csv_data = (
+            "device_role,manufacturer,model_name,status,site,name",
+            "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 4",
+            "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 5",
+            "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 6",
+        )
+
+        response = self.client.post(reverse('dcim:device_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Device.objects.count(), 6)
+
+
+class ConsolePortTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_consoleport',
+                'dcim.add_consoleport',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        ConsolePort.objects.bulk_create([
+            ConsolePort(device=device, name='Console Port 1'),
+            ConsolePort(device=device, name='Console Port 2'),
+            ConsolePort(device=device, name='Console Port 3'),
+        ])
+
+    def test_consoleport_list(self):
+
+        url = reverse('dcim:consoleport_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_consoleport_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Console Port 4",
+            "Device 1,Console Port 5",
+            "Device 1,Console Port 6",
+        )
+
+        response = self.client.post(reverse('dcim:consoleport_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(ConsolePort.objects.count(), 6)
+
+
+class ConsoleServerPortTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_consoleserverport',
+                'dcim.add_consoleserverport',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        ConsoleServerPort.objects.bulk_create([
+            ConsoleServerPort(device=device, name='Console Server Port 1'),
+            ConsoleServerPort(device=device, name='Console Server Port 2'),
+            ConsoleServerPort(device=device, name='Console Server Port 3'),
+        ])
+
+    def test_consoleserverport_list(self):
+
+        url = reverse('dcim:consoleserverport_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_consoleserverport_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Console Server Port 4",
+            "Device 1,Console Server Port 5",
+            "Device 1,Console Server Port 6",
+        )
+
+        response = self.client.post(reverse('dcim:consoleserverport_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(ConsoleServerPort.objects.count(), 6)
+
+
+class PowerPortTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_powerport',
+                'dcim.add_powerport',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        PowerPort.objects.bulk_create([
+            PowerPort(device=device, name='Power Port 1'),
+            PowerPort(device=device, name='Power Port 2'),
+            PowerPort(device=device, name='Power Port 3'),
+        ])
+
+    def test_powerport_list(self):
+
+        url = reverse('dcim:powerport_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_powerport_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Power Port 4",
+            "Device 1,Power Port 5",
+            "Device 1,Power Port 6",
+        )
+
+        response = self.client.post(reverse('dcim:powerport_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(PowerPort.objects.count(), 6)
+
+
+class PowerOutletTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_poweroutlet',
+                'dcim.add_poweroutlet',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        PowerOutlet.objects.bulk_create([
+            PowerOutlet(device=device, name='Power Outlet 1'),
+            PowerOutlet(device=device, name='Power Outlet 2'),
+            PowerOutlet(device=device, name='Power Outlet 3'),
+        ])
+
+    def test_poweroutlet_list(self):
+
+        url = reverse('dcim:poweroutlet_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_poweroutlet_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Power Outlet 4",
+            "Device 1,Power Outlet 5",
+            "Device 1,Power Outlet 6",
+        )
+
+        response = self.client.post(reverse('dcim:poweroutlet_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(PowerOutlet.objects.count(), 6)
+
+
+class InterfaceTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_interface',
+                'dcim.add_interface',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        Interface.objects.bulk_create([
+            Interface(device=device, name='Interface 1'),
+            Interface(device=device, name='Interface 2'),
+            Interface(device=device, name='Interface 3'),
+        ])
+
+    def test_interface_list(self):
+
+        url = reverse('dcim:interface_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_interface_import(self):
+
+        csv_data = (
+            "device,name,type",
+            "Device 1,Interface 4,1000BASE-T (1GE)",
+            "Device 1,Interface 5,1000BASE-T (1GE)",
+            "Device 1,Interface 6,1000BASE-T (1GE)",
+        )
+
+        response = self.client.post(reverse('dcim:interface_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Interface.objects.count(), 6)
+
+
+class FrontPortTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_frontport',
+                'dcim.add_frontport',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        rearport1 = RearPort(device=device, name='Rear Port 1')
+        rearport1.save()
+        rearport2 = RearPort(device=device, name='Rear Port 2')
+        rearport2.save()
+        rearport3 = RearPort(device=device, name='Rear Port 3')
+        rearport3.save()
+
+        # RearPorts for CSV import test
+        RearPort(device=device, name='Rear Port 4').save()
+        RearPort(device=device, name='Rear Port 5').save()
+        RearPort(device=device, name='Rear Port 6').save()
+
+        FrontPort.objects.bulk_create([
+            FrontPort(device=device, name='Front Port 1', rear_port=rearport1),
+            FrontPort(device=device, name='Front Port 2', rear_port=rearport2),
+            FrontPort(device=device, name='Front Port 3', rear_port=rearport3),
+        ])
+
+    def test_frontport_list(self):
+
+        url = reverse('dcim:frontport_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_frontport_import(self):
+
+        csv_data = (
+            "device,name,type,rear_port,rear_port_position",
+            "Device 1,Front Port 4,8P8C,Rear Port 4,1",
+            "Device 1,Front Port 5,8P8C,Rear Port 5,1",
+            "Device 1,Front Port 6,8P8C,Rear Port 6,1",
+        )
+
+        response = self.client.post(reverse('dcim:frontport_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(FrontPort.objects.count(), 6)
+
+
+class RearPortTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_rearport',
+                'dcim.add_rearport',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        RearPort.objects.bulk_create([
+            RearPort(device=device, name='Rear Port 1'),
+            RearPort(device=device, name='Rear Port 2'),
+            RearPort(device=device, name='Rear Port 3'),
+        ])
+
+    def test_rearport_list(self):
+
+        url = reverse('dcim:rearport_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_rearport_import(self):
+
+        csv_data = (
+            "device,name,type,positions",
+            "Device 1,Rear Port 4,8P8C,1",
+            "Device 1,Rear Port 5,8P8C,1",
+            "Device 1,Rear Port 6,8P8C,1",
+        )
+
+        response = self.client.post(reverse('dcim:rearport_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(RearPort.objects.count(), 6)
+
+
+class DeviceBayTestCase(TestCase):
+
+    def setUp(self):
+        user = create_test_user(
+            permissions=[
+                'dcim.view_devicebay',
+                'dcim.add_devicebay',
+            ]
+        )
+        self.client = Client()
+        self.client.force_login(user)
+
+        site = Site(name='Site 1', slug='site-1')
+        site.save()
+
+        manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
+        manufacturer.save()
+
+        devicetype = DeviceType(
+            model='Device Type 1',
+            manufacturer=manufacturer,
+            subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
+        )
+        devicetype.save()
+
+        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
+        devicerole.save()
+
+        device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
+        device.save()
+
+        DeviceBay.objects.bulk_create([
+            DeviceBay(device=device, name='Device Bay 1'),
+            DeviceBay(device=device, name='Device Bay 2'),
+            DeviceBay(device=device, name='Device Bay 3'),
+        ])
+
+    def test_devicebay_list(self):
+
+        url = reverse('dcim:devicebay_list')
+
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_devicebay_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Device Bay 4",
+            "Device 1,Device Bay 5",
+            "Device 1,Device Bay 6",
+        )
+
+        response = self.client.post(reverse('dcim:devicebay_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(DeviceBay.objects.count(), 6)
+
 
 
 class InventoryItemTestCase(TestCase):
 class InventoryItemTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_inventoryitem'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_inventoryitem',
+                'dcim.add_inventoryitem',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -489,11 +1117,30 @@ class InventoryItemTestCase(TestCase):
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_inventoryitem_import(self):
+
+        csv_data = (
+            "device,name",
+            "Device 1,Inventory Item 4",
+            "Device 1,Inventory Item 5",
+            "Device 1,Inventory Item 6",
+        )
+
+        response = self.client.post(reverse('dcim:inventoryitem_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(InventoryItem.objects.count(), 6)
+
 
 
 class CableTestCase(TestCase):
 class CableTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['dcim.view_cable'])
+        user = create_test_user(
+            permissions=[
+                'dcim.view_cable',
+                'dcim.add_cable',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -513,6 +1160,10 @@ class CableTestCase(TestCase):
         device1.save()
         device1.save()
         device2 = Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole)
         device2 = Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole)
         device2.save()
         device2.save()
+        device3 = Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole)
+        device3.save()
+        device4 = Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole)
+        device4.save()
 
 
         iface1 = Interface(device=device1, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
         iface1 = Interface(device=device1, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
         iface1.save()
         iface1.save()
@@ -527,6 +1178,14 @@ class CableTestCase(TestCase):
         iface6 = Interface(device=device2, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
         iface6 = Interface(device=device2, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
         iface6.save()
         iface6.save()
 
 
+        # Interfaces for CSV import testing
+        Interface(device=device3, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+        Interface(device=device3, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+        Interface(device=device3, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+        Interface(device=device4, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+        Interface(device=device4, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+        Interface(device=device4, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED).save()
+
         Cable(termination_a=iface1, termination_b=iface4, type=CableTypeChoices.TYPE_CAT6).save()
         Cable(termination_a=iface1, termination_b=iface4, type=CableTypeChoices.TYPE_CAT6).save()
         Cable(termination_a=iface2, termination_b=iface5, type=CableTypeChoices.TYPE_CAT6).save()
         Cable(termination_a=iface2, termination_b=iface5, type=CableTypeChoices.TYPE_CAT6).save()
         Cable(termination_a=iface3, termination_b=iface6, type=CableTypeChoices.TYPE_CAT6).save()
         Cable(termination_a=iface3, termination_b=iface6, type=CableTypeChoices.TYPE_CAT6).save()
@@ -547,6 +1206,20 @@ class CableTestCase(TestCase):
         response = self.client.get(cable.get_absolute_url())
         response = self.client.get(cable.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_cable_import(self):
+
+        csv_data = (
+            "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
+            "Device 3,interface,Interface 1,Device 4,interface,Interface 1",
+            "Device 3,interface,Interface 2,Device 4,interface,Interface 2",
+            "Device 3,interface,Interface 3,Device 4,interface,Interface 3",
+        )
+
+        response = self.client.post(reverse('dcim:cable_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Cable.objects.count(), 6)
+
 
 
 class VirtualChassisTestCase(TestCase):
 class VirtualChassisTestCase(TestCase):
 
 

+ 164 - 12
netbox/ipam/tests/test_views.py

@@ -13,7 +13,12 @@ from utilities.testing import create_test_user
 class VRFTestCase(TestCase):
 class VRFTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_vrf'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_vrf',
+                'ipam.add_vrf',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -33,17 +38,36 @@ class VRFTestCase(TestCase):
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-    def test_configcontext(self):
+    def test_vrf(self):
 
 
         vrf = VRF.objects.first()
         vrf = VRF.objects.first()
         response = self.client.get(vrf.get_absolute_url())
         response = self.client.get(vrf.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_vrf_import(self):
+
+        csv_data = (
+            "name",
+            "VRF 4",
+            "VRF 5",
+            "VRF 6",
+        )
+
+        response = self.client.post(reverse('ipam:vrf_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(VRF.objects.count(), 6)
+
 
 
 class RIRTestCase(TestCase):
 class RIRTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_rir'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_rir',
+                'ipam.add_rir',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -60,11 +84,30 @@ class RIRTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_rir_import(self):
+
+        csv_data = (
+            "name,slug",
+            "RIR 4,rir-4",
+            "RIR 5,rir-5",
+            "RIR 6,rir-6",
+        )
+
+        response = self.client.post(reverse('ipam:rir_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(RIR.objects.count(), 6)
+
 
 
 class AggregateTestCase(TestCase):
 class AggregateTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_aggregate'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_aggregate',
+                'ipam.add_aggregate',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -93,11 +136,30 @@ class AggregateTestCase(TestCase):
         response = self.client.get(aggregate.get_absolute_url())
         response = self.client.get(aggregate.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_aggregate_import(self):
+
+        csv_data = (
+            "prefix,rir",
+            "10.4.0.0/16,RIR 1",
+            "10.5.0.0/16,RIR 1",
+            "10.6.0.0/16,RIR 1",
+        )
+
+        response = self.client.post(reverse('ipam:aggregate_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Aggregate.objects.count(), 6)
+
 
 
 class RoleTestCase(TestCase):
 class RoleTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_role'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_role',
+                'ipam.add_role',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -114,11 +176,30 @@ class RoleTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_role_import(self):
+
+        csv_data = (
+            "name,slug,weight",
+            "Role 4,role-4,1000",
+            "Role 5,role-5,1000",
+            "Role 6,role-6,1000",
+        )
+
+        response = self.client.post(reverse('ipam:role_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Role.objects.count(), 6)
+
 
 
 class PrefixTestCase(TestCase):
 class PrefixTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_prefix'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_prefix',
+                'ipam.add_prefix',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -147,11 +228,30 @@ class PrefixTestCase(TestCase):
         response = self.client.get(prefix.get_absolute_url())
         response = self.client.get(prefix.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_prefix_import(self):
+
+        csv_data = (
+            "prefix,status",
+            "10.4.0.0/16,Active",
+            "10.5.0.0/16,Active",
+            "10.6.0.0/16,Active",
+        )
+
+        response = self.client.post(reverse('ipam:prefix_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Prefix.objects.count(), 6)
+
 
 
 class IPAddressTestCase(TestCase):
 class IPAddressTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_ipaddress'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_ipaddress',
+                'ipam.add_ipaddress',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -159,9 +259,9 @@ class IPAddressTestCase(TestCase):
         vrf.save()
         vrf.save()
 
 
         IPAddress.objects.bulk_create([
         IPAddress.objects.bulk_create([
-            IPAddress(family=4, address=IPNetwork('10.1.0.0/16'), vrf=vrf),
-            IPAddress(family=4, address=IPNetwork('10.2.0.0/16'), vrf=vrf),
-            IPAddress(family=4, address=IPNetwork('10.3.0.0/16'), vrf=vrf),
+            IPAddress(family=4, address=IPNetwork('192.0.2.1/24'), vrf=vrf),
+            IPAddress(family=4, address=IPNetwork('192.0.2.2/24'), vrf=vrf),
+            IPAddress(family=4, address=IPNetwork('192.0.2.3/24'), vrf=vrf),
         ])
         ])
 
 
     def test_ipaddress_list(self):
     def test_ipaddress_list(self):
@@ -180,11 +280,30 @@ class IPAddressTestCase(TestCase):
         response = self.client.get(ipaddress.get_absolute_url())
         response = self.client.get(ipaddress.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_ipaddress_import(self):
+
+        csv_data = (
+            "address,status",
+            "192.0.2.4/24,Active",
+            "192.0.2.5/24,Active",
+            "192.0.2.6/24,Active",
+        )
+
+        response = self.client.post(reverse('ipam:ipaddress_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(IPAddress.objects.count(), 6)
+
 
 
 class VLANGroupTestCase(TestCase):
 class VLANGroupTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_vlangroup'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_vlangroup',
+                'ipam.add_vlangroup',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -207,11 +326,30 @@ class VLANGroupTestCase(TestCase):
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_vlangroup_import(self):
+
+        csv_data = (
+            "name,slug",
+            "VLAN Group 4,vlan-group-4",
+            "VLAN Group 5,vlan-group-5",
+            "VLAN Group 6,vlan-group-6",
+        )
+
+        response = self.client.post(reverse('ipam:vlangroup_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(VLANGroup.objects.count(), 6)
+
 
 
 class VLANTestCase(TestCase):
 class VLANTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['ipam.view_vlan'])
+        user = create_test_user(
+            permissions=[
+                'ipam.view_vlan',
+                'ipam.add_vlan',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -240,6 +378,20 @@ class VLANTestCase(TestCase):
         response = self.client.get(vlan.get_absolute_url())
         response = self.client.get(vlan.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_vlan_import(self):
+
+        csv_data = (
+            "vid,name,status",
+            "104,VLAN104,Active",
+            "105,VLAN105,Active",
+            "106,VLAN106,Active",
+        )
+
+        response = self.client.post(reverse('ipam:vlan_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(VLAN.objects.count(), 6)
+
 
 
 class ServiceTestCase(TestCase):
 class ServiceTestCase(TestCase):
 
 

+ 38 - 0
netbox/secrets/tests/constants.py

@@ -0,0 +1,38 @@
+# Dummy RSA key pair for testing use only
+PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA97wPWxpq5cClRu8Ssq609ZLfyx6E8ln/v/PdFZ7fxxmA4k+z
+1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqdd453d1eY95xYVbFrIHs7yJy8lcDR
+2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIbRjA2wmt2PVT26YbOX2qCMItV1+me
+o/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhhGY2b4PKuSTcsYjbg8adOGzFL9RXL
+I1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN5ZEEz+sIdlMPCAACaZAY/t9Kd/Lx
+Hr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xlqQIDAQABAoIBAQC4pDQVxNTTtQf6
+nImlH83EEto1++M+9pFFsi6fxLApJvsGsjzomke1Dy7uN93qVGk8rq3enzSYU58f
+sSs8BVKkH00vZ9ydAKxeAkREC1V9qkRsoTBHUY47sJcDkyZyssxfLNm7w0Q70h7a
+mLVEJBqr75eAxLN19vOpDk6Wkz3Bi0Dj27HLeme3hH5jLVQIIswWZnUDP3r/sdM/
+WA2GjoycPbug0r1FVZnxkFCrQ5yMfH3VzKBelj7356+5sc/TUXedDFN/DV2b90Ll
++au7EEXecFYZwmX3SX2hpe6IWEpUW3B0fvm+Ipm8h7x68i7J0oi9EUXW2+UQYfOx
+dDLxTLvhAoGBAPtJJox4XcpzipSAzKxyV8K9ikUZCG2wJU7VHyZ5zpSXwl/husls
+brAzHQcnWayhxxuWeiQ6pLnRFPFXjlOH2FZqHXSLnfpDaymEksDPvo9GqRE3Q+F+
+lDRn72H1NLIj3Y3t5SwWRB34Dhy+gd5Ht9L3dCTH8cYvJGnmS4sH/z0NAoGBAPxh
+2rhS1B0S9mqqvpduUPxqUIWaztXaHC6ZikloOFcgVMdh9MRrpa2sa+bqcygyqrbH
+GZIIeGcWpmzeitWgSUNLMSIpdl/VoBSvZUMggdJyOHXayo/EhfFddGHdkfz0B0GW
+LzH8ow4JcYdhkTl4+xQstXJNVRJyw5ezFy35FHwNAoGAGZzjKP470R7lyS03r3wY
+Jelb5p8elM+XfemLO0i/HbY6QbuoZk9/GMac9tWz9jynJtC3smmn0KjXEaJzB2CZ
+VHWMewygFZo5mgnBS5XhPoldQjv310wnnw/Y/osXy/CL7KOK8Gt0lflqttNUOWvl
++MLwO6+FnUXA2Gp42Lr/8SECgYANf2pEK2HewDHfmIwi6yp3pXPzAUmIlGanc1y6
++lDxD/CYzTta+erdc/g9XFKWVsdciR9r+Pn/gW2bKve/3xer+qyBCDilfXZXRN4k
+jeuDhspQO0hUEg2b0AS2azQwlBiDQHX7tWg/CvBAbk5nBXpgJNf7aflfyDV/untF
+4SlgTQKBgGmcyU02lyM6ogGbzWqSsHgR1ZhYyTV9DekQx9GysLG1wT2QzgjxOw4K
+5PnVkOXr/ORqt+vJsYrtqBZQihmPPREKEwr2n8BRw0364z02wjvP04hDBHp4S5Ej
+PQeC5qErboVGMMpM2SamqGEfr+HJ/uRF6mEmm+xjI57aOvAwPW0B
+-----END RSA PRIVATE KEY-----"""
+
+PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA97wPWxpq5cClRu8Ssq60
+9ZLfyx6E8ln/v/PdFZ7fxxmA4k+z1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqd
+d453d1eY95xYVbFrIHs7yJy8lcDR2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIb
+RjA2wmt2PVT26YbOX2qCMItV1+meo/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhh
+GY2b4PKuSTcsYjbg8adOGzFL9RXLI1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN
+5ZEEz+sIdlMPCAACaZAY/t9Kd/LxHr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xl
+qQIDAQAB
+-----END PUBLIC KEY-----"""

+ 1 - 39
netbox/secrets/tests/test_api.py

@@ -6,45 +6,7 @@ from rest_framework import status
 from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
 from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
 from secrets.models import Secret, SecretRole, SessionKey, UserKey
 from secrets.models import Secret, SecretRole, SessionKey, UserKey
 from utilities.testing import APITestCase
 from utilities.testing import APITestCase
-
-# Dummy RSA key pair for testing use only
-PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA97wPWxpq5cClRu8Ssq609ZLfyx6E8ln/v/PdFZ7fxxmA4k+z
-1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqdd453d1eY95xYVbFrIHs7yJy8lcDR
-2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIbRjA2wmt2PVT26YbOX2qCMItV1+me
-o/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhhGY2b4PKuSTcsYjbg8adOGzFL9RXL
-I1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN5ZEEz+sIdlMPCAACaZAY/t9Kd/Lx
-Hr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xlqQIDAQABAoIBAQC4pDQVxNTTtQf6
-nImlH83EEto1++M+9pFFsi6fxLApJvsGsjzomke1Dy7uN93qVGk8rq3enzSYU58f
-sSs8BVKkH00vZ9ydAKxeAkREC1V9qkRsoTBHUY47sJcDkyZyssxfLNm7w0Q70h7a
-mLVEJBqr75eAxLN19vOpDk6Wkz3Bi0Dj27HLeme3hH5jLVQIIswWZnUDP3r/sdM/
-WA2GjoycPbug0r1FVZnxkFCrQ5yMfH3VzKBelj7356+5sc/TUXedDFN/DV2b90Ll
-+au7EEXecFYZwmX3SX2hpe6IWEpUW3B0fvm+Ipm8h7x68i7J0oi9EUXW2+UQYfOx
-dDLxTLvhAoGBAPtJJox4XcpzipSAzKxyV8K9ikUZCG2wJU7VHyZ5zpSXwl/husls
-brAzHQcnWayhxxuWeiQ6pLnRFPFXjlOH2FZqHXSLnfpDaymEksDPvo9GqRE3Q+F+
-lDRn72H1NLIj3Y3t5SwWRB34Dhy+gd5Ht9L3dCTH8cYvJGnmS4sH/z0NAoGBAPxh
-2rhS1B0S9mqqvpduUPxqUIWaztXaHC6ZikloOFcgVMdh9MRrpa2sa+bqcygyqrbH
-GZIIeGcWpmzeitWgSUNLMSIpdl/VoBSvZUMggdJyOHXayo/EhfFddGHdkfz0B0GW
-LzH8ow4JcYdhkTl4+xQstXJNVRJyw5ezFy35FHwNAoGAGZzjKP470R7lyS03r3wY
-Jelb5p8elM+XfemLO0i/HbY6QbuoZk9/GMac9tWz9jynJtC3smmn0KjXEaJzB2CZ
-VHWMewygFZo5mgnBS5XhPoldQjv310wnnw/Y/osXy/CL7KOK8Gt0lflqttNUOWvl
-+MLwO6+FnUXA2Gp42Lr/8SECgYANf2pEK2HewDHfmIwi6yp3pXPzAUmIlGanc1y6
-+lDxD/CYzTta+erdc/g9XFKWVsdciR9r+Pn/gW2bKve/3xer+qyBCDilfXZXRN4k
-jeuDhspQO0hUEg2b0AS2azQwlBiDQHX7tWg/CvBAbk5nBXpgJNf7aflfyDV/untF
-4SlgTQKBgGmcyU02lyM6ogGbzWqSsHgR1ZhYyTV9DekQx9GysLG1wT2QzgjxOw4K
-5PnVkOXr/ORqt+vJsYrtqBZQihmPPREKEwr2n8BRw0364z02wjvP04hDBHp4S5Ej
-PQeC5qErboVGMMpM2SamqGEfr+HJ/uRF6mEmm+xjI57aOvAwPW0B
------END RSA PRIVATE KEY-----"""
-
-PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA97wPWxpq5cClRu8Ssq60
-9ZLfyx6E8ln/v/PdFZ7fxxmA4k+z1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqd
-d453d1eY95xYVbFrIHs7yJy8lcDR2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIb
-RjA2wmt2PVT26YbOX2qCMItV1+meo/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhh
-GY2b4PKuSTcsYjbg8adOGzFL9RXLI1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN
-5ZEEz+sIdlMPCAACaZAY/t9Kd/LxHr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xl
-qQIDAQAB
------END PUBLIC KEY-----"""
+from .constants import PRIVATE_KEY, PUBLIC_KEY
 
 
 
 
 class SecretRoleTest(APITestCase):
 class SecretRoleTest(APITestCase):

+ 55 - 3
netbox/secrets/tests/test_views.py

@@ -1,17 +1,24 @@
+import base64
 import urllib.parse
 import urllib.parse
 
 
 from django.test import Client, TestCase
 from django.test import Client, TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
 from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
 from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
-from secrets.models import Secret, SecretRole
+from secrets.models import Secret, SecretRole, SessionKey, UserKey
 from utilities.testing import create_test_user
 from utilities.testing import create_test_user
+from .constants import PRIVATE_KEY, PUBLIC_KEY
 
 
 
 
 class SecretRoleTestCase(TestCase):
 class SecretRoleTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['secrets.view_secretrole'])
+        user = create_test_user(
+            permissions=[
+                'secrets.view_secretrole',
+                'secrets.add_secretrole',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -28,11 +35,38 @@ class SecretRoleTestCase(TestCase):
         response = self.client.get(url, follow=True)
         response = self.client.get(url, follow=True)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_secretrole_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Secret Role 4,secret-role-4",
+            "Secret Role 5,secret-role-5",
+            "Secret Role 6,secret-role-6",
+        )
+
+        response = self.client.post(reverse('secrets:secretrole_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(SecretRole.objects.count(), 6)
+
 
 
 class SecretTestCase(TestCase):
 class SecretTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['secrets.view_secret'])
+        user = create_test_user(
+            permissions=[
+                'secrets.view_secret',
+                'secrets.add_secret',
+            ]
+        )
+
+        # Set up a master key
+        userkey = UserKey(user=user, public_key=PUBLIC_KEY)
+        userkey.save()
+        master_key = userkey.get_master_key(PRIVATE_KEY)
+        self.session_key = SessionKey(userkey=userkey)
+        self.session_key.save(master_key)
+
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -75,3 +109,21 @@ class SecretTestCase(TestCase):
         secret = Secret.objects.first()
         secret = Secret.objects.first()
         response = self.client.get(secret.get_absolute_url(), follow=True)
         response = self.client.get(secret.get_absolute_url(), follow=True)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
+
+    def test_secret_import(self):
+
+        csv_data = (
+            "device,role,name,plaintext",
+            "Device 1,Secret Role 1,Secret 4,abcdefghij",
+            "Device 1,Secret Role 1,Secret 5,abcdefghij",
+            "Device 1,Secret Role 1,Secret 6,abcdefghij",
+        )
+
+        # Set the session_key cookie on the request
+        session_key = base64.b64encode(self.session_key.key).decode('utf-8')
+        self.client.cookies['session_key'] = session_key
+
+        response = self.client.post(reverse('secrets:secret_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Secret.objects.count(), 6)

+ 40 - 2
netbox/tenancy/tests/test_views.py

@@ -10,7 +10,12 @@ from utilities.testing import create_test_user
 class TenantGroupTestCase(TestCase):
 class TenantGroupTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['tenancy.view_tenantgroup'])
+        user = create_test_user(
+            permissions=[
+                'tenancy.view_tenantgroup',
+                'tenancy.add_tenantgroup',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -27,11 +32,30 @@ class TenantGroupTestCase(TestCase):
         response = self.client.get(url, follow=True)
         response = self.client.get(url, follow=True)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_tenantgroup_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Tenant Group 4,tenant-group-4",
+            "Tenant Group 5,tenant-group-5",
+            "Tenant Group 6,tenant-group-6",
+        )
+
+        response = self.client.post(reverse('tenancy:tenantgroup_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(TenantGroup.objects.count(), 6)
+
 
 
 class TenantTestCase(TestCase):
 class TenantTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['tenancy.view_tenant'])
+        user = create_test_user(
+            permissions=[
+                'tenancy.view_tenant',
+                'tenancy.add_tenant',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -59,3 +83,17 @@ class TenantTestCase(TestCase):
         tenant = Tenant.objects.first()
         tenant = Tenant.objects.first()
         response = self.client.get(tenant.get_absolute_url(), follow=True)
         response = self.client.get(tenant.get_absolute_url(), follow=True)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
+
+    def test_tenant_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Tenant 4,tenant-4",
+            "Tenant 5,tenant-5",
+            "Tenant 6,tenant-6",
+        )
+
+        response = self.client.post(reverse('tenancy:tenant_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Tenant.objects.count(), 6)

+ 80 - 4
netbox/virtualization/tests/test_views.py

@@ -10,7 +10,12 @@ from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMac
 class ClusterGroupTestCase(TestCase):
 class ClusterGroupTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['virtualization.view_clustergroup'])
+        user = create_test_user(
+            permissions=[
+                'virtualization.view_clustergroup',
+                'virtualization.add_clustergroup',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -27,11 +32,30 @@ class ClusterGroupTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_clustergroup_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Cluster Group 4,cluster-group-4",
+            "Cluster Group 5,cluster-group-5",
+            "Cluster Group 6,cluster-group-6",
+        )
+
+        response = self.client.post(reverse('virtualization:clustergroup_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(ClusterGroup.objects.count(), 6)
+
 
 
 class ClusterTypeTestCase(TestCase):
 class ClusterTypeTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['virtualization.view_clustertype'])
+        user = create_test_user(
+            permissions=[
+                'virtualization.view_clustertype',
+                'virtualization.add_clustertype',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -48,11 +72,30 @@ class ClusterTypeTestCase(TestCase):
         response = self.client.get(url)
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_clustertype_import(self):
+
+        csv_data = (
+            "name,slug",
+            "Cluster Type 4,cluster-type-4",
+            "Cluster Type 5,cluster-type-5",
+            "Cluster Type 6,cluster-type-6",
+        )
+
+        response = self.client.post(reverse('virtualization:clustertype_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(ClusterType.objects.count(), 6)
+
 
 
 class ClusterTestCase(TestCase):
 class ClusterTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['virtualization.view_cluster'])
+        user = create_test_user(
+            permissions=[
+                'virtualization.view_cluster',
+                'virtualization.add_cluster',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -85,11 +128,30 @@ class ClusterTestCase(TestCase):
         response = self.client.get(cluster.get_absolute_url())
         response = self.client.get(cluster.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_cluster_import(self):
+
+        csv_data = (
+            "name,type",
+            "Cluster 4,Cluster Type 1",
+            "Cluster 5,Cluster Type 1",
+            "Cluster 6,Cluster Type 1",
+        )
+
+        response = self.client.post(reverse('virtualization:cluster_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(Cluster.objects.count(), 6)
+
 
 
 class VirtualMachineTestCase(TestCase):
 class VirtualMachineTestCase(TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        user = create_test_user(permissions=['virtualization.view_virtualmachine'])
+        user = create_test_user(
+            permissions=[
+                'virtualization.view_virtualmachine',
+                'virtualization.add_virtualmachine',
+            ]
+        )
         self.client = Client()
         self.client = Client()
         self.client.force_login(user)
         self.client.force_login(user)
 
 
@@ -120,3 +182,17 @@ class VirtualMachineTestCase(TestCase):
         virtualmachine = VirtualMachine.objects.first()
         virtualmachine = VirtualMachine.objects.first()
         response = self.client.get(virtualmachine.get_absolute_url())
         response = self.client.get(virtualmachine.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
+
+    def test_virtualmachine_import(self):
+
+        csv_data = (
+            "name,cluster",
+            "Virtual Machine 4,Cluster 1",
+            "Virtual Machine 5,Cluster 1",
+            "Virtual Machine 6,Cluster 1",
+        )
+
+        response = self.client.post(reverse('virtualization:virtualmachine_import'), {'csv': '\n'.join(csv_data)})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(VirtualMachine.objects.count(), 6)