Per arthanson's review request, updated docs/models/dcim/moduletype.md
to document:
- {module} placeholder behavior (single vs multiple use)
- {module_path} placeholder for full path expansion
- Position field resolution for nested module bays
1. Add validation to reject mixing {module} and {module_path} in same attribute
2. Refactor resolve_position() to match resolve_name()/resolve_label() pattern
- Moved to ModuleBayTemplate where it can access self.position directly
- No longer takes position as argument
3. Added test for mixed placeholder validation
Constants should only contain constant values, not functions with logic.
The helper function now lives in dcim/utils.py alongside other utilities
like update_interface_bridges and create_port_mappings.
Per sigprof's feedback, this implements two distinct placeholders:
- {module_path}: Always expands to full /-separated path (e.g., 1/2/3)
Use case: Generic modules like SFPs that work at any depth
- {module} (single): Expands to parent bay position only
Use case: Building custom paths via position field with user-controlled separators
- {module}/{module}: Level-by-level substitution (unchanged for backwards compat)
This design allows two ways to build module hierarchies:
1. Use {module_path} for automatic path joining (hardcodes / separator)
2. Use position field with {module} for custom separators
Fixes#20474, #20467, #19796
Per sigprof's review feedback, extract the duplicated token substitution
logic into a single resolve_module_token() helper in constants.py.
This addresses two review comments:
1. Duplication between ModuleCommonForm.clean() and resolve_name()
2. Duplication between resolve_name() and resolve_label()
Benefits:
- Single source of truth for substitution logic
- MODULE_TOKEN_SEPARATOR constant for future configurability
- Cleaner, more maintainable code (-7 net lines)
- Easier to modify separator handling in one place
Per sigprof's feedback, the previous validation (depth >= token_count)
allowed a questionable case where token_count > 1 but < depth, which
would lose position information for some levels.
New validation: token_count must be either 1 (full path expansion) or
exactly match the tree depth (level-by-level substitution).
Updated test T2 to verify this mismatched case is now rejected.
- Add resolve_position() method to ModularComponentTemplateModel
- Update ModuleBayTemplate.instantiate() to resolve {module} in position field
- Add test_module_bay_position_resolves_placeholder test
This completes the fix for nested module placeholder issues by ensuring
the position field also resolves {module} placeholders, which is required
for building correct full paths in 3+ level hierarchies.
The legacy pre-commit hook script was scheduled for removal in NetBox v4.3, as noted in the TODO comment within the file. Users should now use the pre-commit tool instead.
Adds support for PATCHing ConfigContext and ConfigContextProfile with
integer IDs for `data_source` and `data_file`.
Adds regression tests to validate assignment and API functionality.
Fixes#20933
Corrects the format string for mounting depth to include a space
between the value and the unit (`mm`) for consistency with other
measurements.
Fixes#21178
Replace `gettext()` with `gettext_lazy()` to avoid locale-dependent
model serialization (and false-positive pending migration warnings).
Also make a missing `ValidationError` message translatable and
format-safe.
Fixes#21175
PluginMenuItem and PluginMenuButton classes used mutable class-level
defaults for `permissions` and `buttons` attributes, causing permission
leakage between instances when these attributes were modified without
explicit parameters.
Changed to initialize these attributes as fresh lists per instance in
__init__ when not explicitly provided, following standard Python pattern
for avoiding mutable default arguments.
Disable reassignment of IP addresses designated as primary or OOB for
parent objects. Adds validation to block changes when an IP is marked as
the OOB IP.
Fixes#21050
@@ -16,9 +16,33 @@ Note that device bays and module bays may _not_ be added to modules.
## Automatic Component Renaming
When adding component templates to a module type, the string `{module}` can be used to reference the `position` field of the module bay into which an instance of the module type is being installed.
When adding component templates to a module type, placeholders can be used to dynamically incorporate the module bay's `position` field into component names. Two placeholders are available:
For example, you can create a module type with interface templates named `Gi{module}/0/[1-48]`. When a new module of this type is "installed" to a module bay with a position of "3", NetBox will automatically name these interfaces `Gi3/0/[1-48]`.
### `{module}` Placeholder
The `{module}` placeholder references the position of the parent module bay:
* **Single use**: Expands to the immediate parent's position only
* **Multiple uses**: Each `{module}` token is replaced level-by-level (the number of tokens must match the nesting depth)
For example, a module type with interface templates named `Gi{module}/0/[1-48]`, when installed in a module bay with position "3", will create interfaces named `Gi3/0/[1-48]`.
### `{module_path}` Placeholder
The `{module_path}` placeholder expands to the full path from the root device to the current module, with positions joined by `/`. This is useful for modules that can be installed at any nesting depth without modification.
For example, consider an SFP module type with an interface template named `eth{module_path}`:
* Installed directly in slot 2: creates interface `eth2`
* Installed in slot 1's nested bay 1: creates interface `eth1/1`
* Installed in slot 1's nested bay 2's sub-bay 3: creates interface `eth1/2/3`
!!! note
`{module_path}` can only be used once per template attribute, and cannot be mixed with `{module}` in the same attribute.
### Position Field Resolution
The `{module}` placeholder can also be used in the `position` field of [module bay templates](./modulebaytemplate.md) defined on a module type. This allows nested module bays to build hierarchical position values. For example, a module bay template with `position="{module}/1"`, when its parent module is installed in a bay with position "2", will have its position resolved to "2/1".
Automatic renaming is supported for all modular component types (those listed above).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.