fix(templatetags): render hostgroup/tag previews with representative device#130
Open
berlikm wants to merge 2 commits into
Open
fix(templatetags): render hostgroup/tag previews with representative device#130berlikm wants to merge 2 commits into
berlikm wants to merge 2 commits into
Conversation
…device
Templates like 'Roles/{{ object.role.name }}' assigned to a DeviceRole,
or 'Sites/{{ object.site.group.name }}/{{ object.site.name }}' assigned
to a SiteGroup, fail in the NetBox UI 'Rendered Value' preview card
and ObjectViewTable because the render context uses the assignment
target (DeviceRole/SiteGroup) as 'object', which lacks the traversed
attributes (.role, .site).
The sync engine was already fixed in PR OpensourceICTSolutions#110 to pass object=Device
explicitly, but the UI preview path (render_zabbix_hostgroup_assignment
/ render_zabbix_tag_assignment) was never addressed and leaked the raw
Jinja2 UndefinedError string into the page.
Fix: substitute a representative Device/VM that inherits the assignment
so device-context templates render the same value the sync produces.
Cached via lru_cache(maxsize=64) for the table case. Returns '' on
failure instead of the error string.
- nbxsync/utils/preview.py (new): representative-device resolver with
dispatch table covering DeviceRole, Platform, Manufacturer, DeviceType,
Site, SiteGroup (recursive), Region (recursive), Cluster, ClusterType.
- nbxsync/templatetags/zabbix_hostgroups.py: takes_context=True,
substitute representative when no explicit object= passed.
- nbxsync/templatetags/zabbix_tags.py: mirror for tags.
- nbxsync/tests/templatetags/test_preview_render.py: covers DeviceRole
rep, recursive SiteGroup, empty role (graceful ''), static passthrough,
explicit object= override (sync-engine path preserved).
berlikm
added a commit
to berlikm/nbxsync
that referenced
this pull request
Jul 17, 2026
…ag preview representative device Merges fix/preview-device-context into integration-test for VM testing. Resolves UndefinedError leak in NetBox UI 'Rendered Value' card for inherited hostgroup/tag assignments.
create_test_device(name, site, **attrs) already passes role=devicerole internally, so passing role= via **attrs collides. Use a _make_device wrapper that creates then sets the role. Also fix assertIs(rep, device) → assertEqual(rep.pk, device.pk): the resolver returns a fresh DB fetch, not the same Python instance. All 10 tests now pass.
|
This is a much needed PR. It makes things more NetBox native. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Templates like
Roles/{{ object.role.name }}(assigned toDeviceRole) andSites/{{ object.site.group.name }}/{{ object.site.name }}(assigned toSiteGroup) fail in the NetBox UI 'Rendered Value' preview card and ObjectViewTable. The render context uses the assignment target (DeviceRole/SiteGroup) asobject, which lacks.role/.site:The sync engine was already fixed in #110 to pass
object=Deviceexplicitly, but the UI preview path (render_zabbix_hostgroup_assignment/render_zabbix_tag_assignment) was never addressed and leaked the raw Jinja2UndefinedErrorstring into the page.Fix
Substitute a representative Device/VM that inherits the assignment so device-context templates resolve to the same value the sync produces. When no representative is found (empty role/site), the tag returns
''instead of the error string.Files
nbxsync/utils/preview.py(new):get_representative_device(assignment)resolver with dispatch table coveringDeviceRole,Platform,Manufacturer,DeviceType,Site,SiteGroup(recursive viaget_descendants),Region(recursive),Cluster,ClusterType. Cached via@lru_cache(maxsize=64)for the table case.nbxsync/templatetags/zabbix_hostgroups.py:takes_context=True, substitute representative when no explicitobject=passed.if 'object' not in extraguard preserves the sync-engine path (which passesobject=Deviceexplicitly).nbxsync/templatetags/zabbix_tags.py: mirror for tags.nbxsync/tests/templatetags/test_preview_render.py(+__init__.py): covers DeviceRole rep, recursive SiteGroup, empty role (graceful''), static passthrough, explicitobject=override.Behaviour
Roles/{{ object.role.name }}on DeviceRole 'Cohesity'Roles/CohesitySites/{{ object.site.group.name }}/{{ object.site.name }}on SiteGroup 'CH'Sites/CH-NKN/CH-NKN-G08(first CH device)Managed/nbxSync(static)Managed/nbxSyncManaged/nbxSync(unchanged)''(graceful)Compatibility
HostSyncalready passesobject=Deviceexplicitly (Fix: Pass device context to tag render for Jinja2 values #110), and theif 'object' not in extraguard keeps the resolver dormant on that path.Supplements #102 (taofineberg's related-context PR) — #102 adds alternative context keys (
device,site,role); this PR overridesobjectso existing templates keep working without rewrite.