Просмотр исходного кода

Rewrote test for DeviceType import

Jeremy Stretch 6 лет назад
Родитель
Сommit
ee4e68b082
4 измененных файлов с 140 добавлено и 113 удалено
  1. 1 2
      netbox/dcim/forms.py
  2. 0 104
      netbox/dcim/tests/test_forms.py
  3. 130 3
      netbox/dcim/tests/test_views.py
  4. 9 4
      netbox/utilities/views.py

+ 1 - 2
netbox/dcim/forms.py

@@ -1212,7 +1212,6 @@ class ComponentTemplateImportForm(BootstrapMixin, forms.ModelForm):
         data.update({
         data.update({
             'device_type': device_type.pk,
             'device_type': device_type.pk,
         })
         })
-        print(data)
 
 
         super().__init__(data, *args, **kwargs)
         super().__init__(data, *args, **kwargs)
 
 
@@ -1279,7 +1278,7 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
 
 
 
 
 class FrontPortTemplateImportForm(ComponentTemplateImportForm):
 class FrontPortTemplateImportForm(ComponentTemplateImportForm):
-    power_port = forms.ModelChoiceField(
+    rear_port = forms.ModelChoiceField(
         queryset=RearPortTemplate.objects.all(),
         queryset=RearPortTemplate.objects.all(),
         to_field_name='name',
         to_field_name='name',
         required=False
         required=False

+ 0 - 104
netbox/dcim/tests/test_forms.py

@@ -8,110 +8,6 @@ def get_id(model, slug):
     return model.objects.get(slug=slug).id
     return model.objects.get(slug=slug).id
 
 
 
 
-DEVICETYPE_DATA = {
-    'manufacturer': 'Generic',
-    'model': 'TEST-1000',
-    'slug': 'test-1000',
-    'u_height': 2,
-    'console-ports': [
-        {'name': 'Console Port 1'},
-        {'name': 'Console Port 2'},
-        {'name': 'Console Port 3'},
-    ],
-    'console-server-ports': [
-        {'name': 'Console Server Port 1'},
-        {'name': 'Console Server Port 2'},
-        {'name': 'Console Server Port 3'},
-    ],
-    'power-ports': [
-        {'name': 'Power Port 1'},
-        {'name': 'Power Port 2'},
-        {'name': 'Power Port 3'},
-    ],
-    'power-outlets': [
-        {'name': 'Power Outlet 1', 'power_port': 'Power Port 1', 'feed_leg': POWERFEED_LEG_A},
-        {'name': 'Power Outlet 2', 'power_port': 'Power Port 1', 'feed_leg': POWERFEED_LEG_A},
-        {'name': 'Power Outlet 3', 'power_port': 'Power Port 1', 'feed_leg': POWERFEED_LEG_A},
-    ],
-    'interfaces': [
-        {'name': 'Interface 1', 'type': IFACE_TYPE_1GE_FIXED, 'mgmt_only': True},
-        {'name': 'Interface 2', 'type': IFACE_TYPE_1GE_FIXED},
-        {'name': 'Interface 3', 'type': IFACE_TYPE_1GE_FIXED},
-    ],
-    'rear-ports': [
-        {'name': 'Rear Port 1', 'type': PORT_TYPE_8P8C},
-        {'name': 'Rear Port 2', 'type': PORT_TYPE_8P8C},
-        {'name': 'Rear Port 3', 'type': PORT_TYPE_8P8C},
-    ],
-    'front-ports': [
-        {'name': 'Front Port 1', 'type': PORT_TYPE_8P8C, 'rear_port': 'Rear Port 1'},
-        {'name': 'Front Port 2', 'type': PORT_TYPE_8P8C, 'rear_port': 'Rear Port 2'},
-        {'name': 'Front Port 3', 'type': PORT_TYPE_8P8C, 'rear_port': 'Rear Port 3'},
-    ],
-    'device-bays': [
-        {'name': 'Device Bay 1'},
-        {'name': 'Device Bay 2'},
-        {'name': 'Device Bay 3'},
-    ],
-}
-
-
-class DeviceTypeImportTestCase(TestCase):
-
-    def setUp(self):
-
-        Manufacturer(name='Generic', slug='generic').save()
-
-    def test_import_devicetype_yaml(self):
-
-        form = DeviceTypeImportForm(DEVICETYPE_DATA)
-
-        self.assertTrue(form.is_valid(), "Form validation failed: {}".format(form.errors))
-
-        form.save()
-        dt = DeviceType.objects.get(model='TEST-1000')
-
-        # Verify all of the components were created
-        # TODO: The creation of components now occurs in the view rather than the form
-        self.assertEqual(dt.consoleport_templates.count(), 3)
-        cp1 = ConsolePortTemplate.objects.first()
-        self.assertEqual(cp1.name, 'Console Port 1')
-
-        self.assertEqual(dt.consoleserverport_templates.count(), 3)
-        csp1 = ConsoleServerPortTemplate.objects.first()
-        self.assertEqual(csp1.name, 'Console Server Port 1')
-
-        self.assertEqual(dt.powerport_templates.count(), 3)
-        pp1 = PowerPortTemplate.objects.first()
-        self.assertEqual(pp1.name, 'Power Port 1')
-
-        self.assertEqual(dt.poweroutlet_templates.count(), 3)
-        po1 = PowerOutletTemplate.objects.first()
-        self.assertEqual(po1.name, 'Power Outlet 1')
-        self.assertEqual(po1.power_port, pp1)
-        self.assertEqual(po1.feed_leg, POWERFEED_LEG_A)
-
-        self.assertEqual(dt.interface_templates.count(), 4)
-        iface1 = Interface.objects.first()
-        self.assertEqual(iface1.name, 'Interface 1')
-        self.assertEqual(iface1.type, IFACE_TYPE_1GE_FIXED)
-        self.assertTrue(iface1.mgmt_only)
-
-        self.assertEqual(dt.rearport_templates.count(), 3)
-        rp1 = RearPortTemplate.objects.first()
-        self.assertEqual(rp1.name, 'Rear Port 1')
-
-        self.assertEqual(dt.frontport_templates.count(), 3)
-        fp1 = FrontPortTemplate.objects.first()
-        self.assertEqual(fp1.name, 'Front Port 1')
-        self.assertEqual(fp1.rear_port, rp1)
-        self.assertEqual(fp1.rear_port_position, 1)
-
-        self.assertEqual(dt.devicebay_templates.count(), 3)
-        db1 = DeviceBayTemplate.objects.first()
-        self.assertEqual(db1.name, 'Device Bay 1')
-
-
 class DeviceTestCase(TestCase):
 class DeviceTestCase(TestCase):
 
 
     fixtures = ['dcim', 'ipam']
     fixtures = ['dcim', 'ipam']

+ 130 - 3
netbox/dcim/tests/test_views.py

@@ -3,10 +3,11 @@ 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.constants import CABLE_TYPE_CAT6, IFACE_TYPE_1GE_FIXED
+from dcim.constants import *
 from dcim.models import (
 from dcim.models import (
-    Cable, Device, DeviceRole, DeviceType, Interface, InventoryItem, Manufacturer, Platform, Rack, RackGroup,
-    RackReservation, RackRole, Site, Region, VirtualChassis,
+    Cable, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceBayTemplate, DeviceRole, DeviceType,
+    FrontPortTemplate, Interface, InterfaceTemplate, InventoryItem, Manufacturer, Platform, PowerPortTemplate,
+    PowerOutletTemplate, Rack, RackGroup, RackReservation, RackRole, RearPortTemplate, Site, Region, VirtualChassis,
 )
 )
 from utilities.testing import create_test_user
 from utilities.testing import create_test_user
 
 
@@ -221,6 +222,132 @@ class DeviceTypeTestCase(TestCase):
         response = self.client.get(devicetype.get_absolute_url())
         response = self.client.get(devicetype.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    def test_devicetype_import(self):
+
+        IMPORT_DATA = """
+manufacturer: Generic
+model: TEST-1000
+slug: test-1000
+u_height: 2
+console-ports:
+  - name: Console Port 1
+  - name: Console Port 2
+  - name: Console Port 3
+console-server-ports:
+  - name: Console Server Port 1
+  - name: Console Server Port 2
+  - name: Console Server Port 3
+power-ports:
+  - name: Power Port 1
+  - name: Power Port 2
+  - name: Power Port 3
+power-outlets:
+  - name: Power Outlet 1
+    power_port: Power Port 1
+    feed_leg: 1
+  - name: Power Outlet 2
+    power_port: Power Port 1
+    feed_leg: 1
+  - name: Power Outlet 3
+    power_port: Power Port 1
+    feed_leg: 1
+interfaces:
+  - name: Interface 1
+    type: 1000
+    mgmt_only: true
+  - name: Interface 2
+    type: 1000
+  - name: Interface 3
+    type: 1000
+rear-ports:
+  - name: Rear Port 1
+    type: 1000
+  - name: Rear Port 2
+    type: 1000
+  - name: Rear Port 3
+    type: 1000
+front-ports:
+  - name: Front Port 1
+    type: 1000
+    rear_port: Rear Port 1
+  - name: Front Port 2
+    type: 1000
+    rear_port: Rear Port 2
+  - name: Front Port 3
+    type: 1000
+    rear_port: Rear Port 3
+device-bays:
+  - name: Device Bay 1
+  - name: Device Bay 2
+  - name: Device Bay 3
+"""
+
+        # Create the manufacturer
+        Manufacturer(name='Generic', slug='generic').save()
+
+        # Authenticate as user with necessary permissions
+        user = create_test_user(username='testuser2', permissions=[
+            'dcim.view_devicetype',
+            'dcim.add_devicetype',
+            'dcim.add_consoleporttemplate',
+            'dcim.add_consoleserverporttemplate',
+            'dcim.add_powerporttemplate',
+            'dcim.add_poweroutlettemplate',
+            'dcim.add_interfacetemplate',
+            'dcim.add_frontporttemplate',
+            'dcim.add_rearporttemplate',
+            'dcim.add_devicebaytemplate',
+        ])
+        self.client.force_login(user)
+
+        form_data = {
+            'data': IMPORT_DATA,
+            'format': 'yaml'
+        }
+        response = self.client.post(reverse('dcim:devicetype_import'), data=form_data, follow=True)
+
+        dt = DeviceType.objects.get(model='TEST-1000')
+
+        # Verify all of the components were created
+        self.assertEqual(dt.consoleport_templates.count(), 3)
+        cp1 = ConsolePortTemplate.objects.first()
+        self.assertEqual(cp1.name, 'Console Port 1')
+
+        self.assertEqual(dt.consoleserverport_templates.count(), 3)
+        csp1 = ConsoleServerPortTemplate.objects.first()
+        self.assertEqual(csp1.name, 'Console Server Port 1')
+
+        self.assertEqual(dt.powerport_templates.count(), 3)
+        pp1 = PowerPortTemplate.objects.first()
+        self.assertEqual(pp1.name, 'Power Port 1')
+
+        self.assertEqual(dt.poweroutlet_templates.count(), 3)
+        po1 = PowerOutletTemplate.objects.first()
+        self.assertEqual(po1.name, 'Power Outlet 1')
+        self.assertEqual(po1.power_port, pp1)
+        self.assertEqual(po1.feed_leg, POWERFEED_LEG_A)
+
+        self.assertEqual(dt.interface_templates.count(), 3)
+        iface1 = InterfaceTemplate.objects.first()
+        self.assertEqual(iface1.name, 'Interface 1')
+        self.assertEqual(iface1.type, IFACE_TYPE_1GE_FIXED)
+        self.assertTrue(iface1.mgmt_only)
+
+        self.assertEqual(dt.rearport_templates.count(), 3)
+        rp1 = RearPortTemplate.objects.first()
+        self.assertEqual(rp1.name, 'Rear Port 1')
+
+        self.assertEqual(dt.frontport_templates.count(), 3)
+        fp1 = FrontPortTemplate.objects.first()
+        self.assertEqual(fp1.name, 'Front Port 1')
+        self.assertEqual(fp1.rear_port, rp1)
+        self.assertEqual(fp1.rear_port_position, 1)
+
+        self.assertEqual(dt.device_bay_templates.count(), 3)
+        db1 = DeviceBayTemplate.objects.first()
+        self.assertEqual(db1.name, 'Device Bay 1')
+
+
 
 
 class DeviceRoleTestCase(TestCase):
 class DeviceRoleTestCase(TestCase):
 
 

+ 9 - 4
netbox/utilities/views.py

@@ -445,18 +445,23 @@ class ObjectImportView(GetReturnURLMixin, View):
                         obj = model_form.save()
                         obj = model_form.save()
 
 
                         # Iterate through the related object forms (if any), validating and saving each instance.
                         # Iterate through the related object forms (if any), validating and saving each instance.
-                        for field, related_object_form in self.related_object_forms.items():
+                        for field_name, related_object_form in self.related_object_forms.items():
 
 
-                            for i, rel_obj_data in enumerate(data.get(field, list())):
+                            for i, rel_obj_data in enumerate(data.get(field_name, list())):
 
 
                                 f = related_object_form(obj, rel_obj_data)
                                 f = related_object_form(obj, rel_obj_data)
+
+                                for subfield_name, field in f.fields.items():
+                                    if subfield_name not in rel_obj_data and hasattr(field, 'initial'):
+                                        f.data[subfield_name] = field.initial
+
                                 if f.is_valid():
                                 if f.is_valid():
                                     f.save()
                                     f.save()
                                 else:
                                 else:
                                     # Replicate errors on the related object form to the primary form for display
                                     # Replicate errors on the related object form to the primary form for display
-                                    for field_name, errors in f.errors.items():
+                                    for subfield_name, errors in f.errors.items():
                                         for err in errors:
                                         for err in errors:
-                                            err_msg = "{}[{}] {}: {}".format(field, i, field_name, err)
+                                            err_msg = "{}[{}] {}: {}".format(field_name, i, subfield_name, err)
                                             model_form.add_error(None, err_msg)
                                             model_form.add_error(None, err_msg)
                                     raise AbortTransaction()
                                     raise AbortTransaction()