Skip to content

Commit 269112a

Browse files
jnovingerjeremystretch
authored andcommitted
Fixes #19918: Resolve {module} placeholders in nested module bay labels
ModuleBayTemplate.instantiate() now calls resolve_name() and resolve_label() to properly resolve {module} placeholders, making it consistent with other modular components like InterfaceTemplate. When a module with nested module bays is installed (e.g., a module with SFP bays in position "A"), the nested bay labels now correctly show "A-21" instead of "{module}-21". This also removes the inconsistent fix from #17436 which only handled name resolution post-instantiation. The proper resolution now happens during instantiation using the existing resolve methods.
1 parent c667253 commit 269112a

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

netbox/dcim/models/device_component_templates.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,8 @@ class Meta(ModularComponentTemplateModel.Meta):
681681

682682
def instantiate(self, **kwargs):
683683
return self.component_model(
684-
name=self.name,
685-
label=self.label,
684+
name=self.resolve_name(kwargs.get('module')),
685+
label=self.resolve_label(kwargs.get('module')),
686686
position=self.position,
687687
**kwargs
688688
)

netbox/dcim/models/modules.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from jsonschema.exceptions import ValidationError as JSONValidationError
88

99
from dcim.choices import *
10-
from dcim.constants import MODULE_TOKEN
1110
from dcim.utils import update_interface_bridges
1211
from extras.models import ConfigContextModel, CustomField
1312
from netbox.models import PrimaryModel
@@ -331,7 +330,6 @@ def save(self, *args, **kwargs):
331330
else:
332331
# ModuleBays must be saved individually for MPTT
333332
for instance in create_instances:
334-
instance.name = instance.name.replace(MODULE_TOKEN, str(self.module_bay.position))
335333
instance.save()
336334

337335
update_fields = ['module']

netbox/dcim/tests/test_models.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,54 @@ def test_single_module_token(self):
792792
)
793793
device.consoleports.first()
794794

795-
def test_nested_module_token(self):
796-
pass
795+
@tag('regression') # #19918
796+
def test_nested_module_bay_label_resolution(self):
797+
"""Test that nested module bay labels properly resolve {module} placeholders"""
798+
manufacturer = Manufacturer.objects.first()
799+
site = Site.objects.first()
800+
device_role = DeviceRole.objects.first()
801+
802+
# Create device type with module bay template (position='A')
803+
device_type = DeviceType.objects.create(
804+
manufacturer=manufacturer,
805+
model='Device with Bays',
806+
slug='device-with-bays'
807+
)
808+
ModuleBayTemplate.objects.create(
809+
device_type=device_type,
810+
name='Bay A',
811+
position='A'
812+
)
813+
814+
# Create module type with nested bay template using {module} placeholder
815+
module_type = ModuleType.objects.create(
816+
manufacturer=manufacturer,
817+
model='Module with Nested Bays'
818+
)
819+
ModuleBayTemplate.objects.create(
820+
module_type=module_type,
821+
name='SFP {module}-21',
822+
label='{module}-21',
823+
position='21'
824+
)
825+
826+
# Create device and install module
827+
device = Device.objects.create(
828+
name='Test Device',
829+
device_type=device_type,
830+
role=device_role,
831+
site=site
832+
)
833+
module_bay = device.modulebays.get(name='Bay A')
834+
module = Module.objects.create(
835+
device=device,
836+
module_bay=module_bay,
837+
module_type=module_type
838+
)
839+
840+
# Verify nested bay label resolves {module} to parent position
841+
nested_bay = module.modulebays.get(name='SFP A-21')
842+
self.assertEqual(nested_bay.label, 'A-21')
797843

798844

799845
class CableTestCase(TestCase):

0 commit comments

Comments
 (0)