mirror of
https://github.com/netbox-community/netbox.git
synced 2026-03-25 19:02:15 +01:00
Address review feedback
This commit is contained in:
@@ -203,6 +203,7 @@ class ModuleSerializer(PrimaryModelSerializer):
|
||||
module_type = data.get('module_type')
|
||||
module_bay = data.get('module_bay')
|
||||
|
||||
# Required-field validation fires separately; skip here if any are missing.
|
||||
if not all([device, module_type, module_bay]):
|
||||
return data
|
||||
|
||||
@@ -238,8 +239,7 @@ class ModuleSerializer(PrimaryModelSerializer):
|
||||
if template.name.count(MODULE_TOKEN) != len(module_bays):
|
||||
raise serializers.ValidationError(
|
||||
_(
|
||||
"Cannot install module with placeholder values in a module bay tree {level} in tree "
|
||||
"but {tokens} placeholders given."
|
||||
"Cannot install module with {tokens} placeholder(s) in a module bay at depth {level}."
|
||||
).format(
|
||||
level=len(module_bays), tokens=template.name.count(MODULE_TOKEN)
|
||||
)
|
||||
@@ -274,8 +274,8 @@ class ModuleSerializer(PrimaryModelSerializer):
|
||||
# Tags are handled after save; pop them here to pass to _save_tags()
|
||||
tags = validated_data.pop('tags', None)
|
||||
|
||||
# Build the instance without saving so we can set private attributes
|
||||
# that control component replication behaviour in Module.save()
|
||||
# _adopt_components and _disable_replication must be set on the instance before
|
||||
# save() is called, so we cannot delegate to super().create() here.
|
||||
instance = self.Meta.model(**validated_data)
|
||||
if adopt_components:
|
||||
instance._adopt_components = True
|
||||
|
||||
@@ -1846,9 +1846,42 @@ class ModuleTest(APIViewTestCases.APIViewTestCase):
|
||||
}
|
||||
response = self.client.patch(url, data, format='json', **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['serial'], 'PATCHED')
|
||||
# No interfaces should have been created by the PATCH
|
||||
self.assertFalse(device.interfaces.exists())
|
||||
|
||||
def test_adopt_and_replicate_components(self):
|
||||
"""
|
||||
Installing a module with both adopt_components=True and replicate_components=True
|
||||
should adopt existing unowned components and create new components for templates
|
||||
that have no matching existing component.
|
||||
"""
|
||||
self.add_permissions('dcim.add_module')
|
||||
manufacturer = Manufacturer.objects.get(name='Generic')
|
||||
device = create_test_device('Device for Adopt+Replicate Test')
|
||||
module_type = ModuleType.objects.create(manufacturer=manufacturer, model='Adopt+Replicate Test Module Type')
|
||||
InterfaceTemplate.objects.create(module_type=module_type, name='eth0', type='1000base-t')
|
||||
InterfaceTemplate.objects.create(module_type=module_type, name='eth1', type='1000base-t')
|
||||
module_bay = ModuleBay.objects.create(device=device, name='Adopt+Replicate Bay')
|
||||
# eth0 already exists (unowned); eth1 does not
|
||||
existing_iface = Interface.objects.create(device=device, name='eth0', type='1000base-t')
|
||||
|
||||
url = reverse('dcim-api:module-list')
|
||||
data = {
|
||||
'device': device.pk,
|
||||
'module_bay': module_bay.pk,
|
||||
'module_type': module_type.pk,
|
||||
'adopt_components': True,
|
||||
'replicate_components': True,
|
||||
}
|
||||
response = self.client.post(url, data, format='json', **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
||||
# eth0 should have been adopted (now owned by the new module)
|
||||
existing_iface.refresh_from_db()
|
||||
self.assertIsNotNone(existing_iface.module)
|
||||
# eth1 should have been created
|
||||
self.assertTrue(device.interfaces.filter(name='eth1').exists())
|
||||
|
||||
|
||||
class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
|
||||
model = ConsolePort
|
||||
|
||||
Reference in New Issue
Block a user