Skip to content

Fix: Render tag values with device context in ObjectViewTable#111

Open
berlikm wants to merge 8 commits into
OpensourceICTSolutions:developmentfrom
berlikm:fix/tag-table-device-context
Open

Fix: Render tag values with device context in ObjectViewTable#111
berlikm wants to merge 8 commits into
OpensourceICTSolutions:developmentfrom
berlikm:fix/tag-table-device-context

Conversation

@berlikm

@berlikm berlikm commented Jul 13, 2026

Copy link
Copy Markdown

Summary

Applies the same device-context fix as #110 to the ObjectViewTable — tag values in the Zabbix tab on the device page now render with the device as Jinja2 context, not the assignment's source object.

Dependencies

Stacks on PR #115. Merge after #110.

Testing

All existing tests pass.

Part of #121.

@berlikm
berlikm force-pushed the fix/tag-table-device-context branch 2 times, most recently from f2b7a6d to 443521c Compare July 14, 2026 13:23
berlikm added 3 commits July 14, 2026 14:15
Adds Site, SiteGroup, and Region as valid assignment targets for all
ZabbixServerAssignment, ZabbixHostgroupAssignment, ZabbixTemplateAssignment,
ZabbixTagAssignment, ZabbixMacroAssignment, and ZabbixHostInventory objects.

This allows assignments made at the Site/SiteGroup/Region level to be
inherited by all devices and VMs at that site or below, via the existing
inheritance_chain mechanism.

Changes:
- Constants: Site/SiteGroup/Region added to ASSIGNMENT_MODELS, ASSIGNMENT_TYPE_TO_FIELD, PATH_LABELS
- Forms: All 7 assignment forms get Site/SiteGroup/Region DynamicModelChoiceField + FieldSet
- Settings: inheritance_chain extended with Site/SiteGroup/Region resolution paths
- Jobs: SyncHostJob._prepare_assignment() creates detached copies for inherited assignments
- HostSync: _get_sync_target() resolves actual Device/VM for Jinja2 rendering
- HostSync: get_tag_attributes() deduplicates tags by (tag, value) to prevent
  Zabbix 7 rejecting duplicate pairs inherited from multiple sources
- HostInterfaceSync: get_create_params() falls back to the device's primary IP
  when the interface has no IP assigned (e.g. when inherited from SiteGroup)
- HostInterfaceSync: errors are caught per-interface so one failing interface
  does not prevent the remaining interfaces and templates from being synced
- Inheritance: ConfigGroup interface expansion removed; interfaces are now
  resolved naturally via the inheritance chain with primary IP fallback
- SyncBase: _is_inherited_copy guard prevents save()/update_sync_info() on inherited copies
- Views: ZabbixSiteTabView, ZabbixSiteGroupTabView, ZabbixRegionTabView added
- Tests: 9 new tests for inheritance resolution

Tested: all 1076 existing tests pass. Verified end-to-end on dev NetBox.
- Filter inherited/direct ZabbixServerAssignment and ZabbixHostInterface by zabbixserver
- Resolve ConfigGroup interface IP from primary_ip4/primary_ip6
- Add seen-set cycle guard to resolve_path
- Fixes silent dropping of Site/SiteGroup assignments
@berlikm
berlikm force-pushed the fix/tag-table-device-context branch from 443521c to 5ef64df Compare July 14, 2026 14:34
berlikm added 4 commits July 14, 2026 14:54
Fixes inherited Site/SiteGroup/Region assignments reading custom fields from
the intermediate object instead of the actual Device/VM.
When a ZabbixTagAssignment is inherited (e.g. from a DeviceRole, Platform,
or Site), the Jinja2 template value was rendered against the assigned
object — the Role/Platform — rather than the actual Device or VM being
synced. This meant templates referencing $`object.name`$ resolved to
the Role name instead of the device name.

This passes `object=sync_target` to `assigned_tag.render()`, mirroring
the existing pattern in `get_defined_macros()` and
`get_hostinventory()` which already render against the device.

Additionally, tags are deduplicated by (tag, value) to prevent Zabbix 7
from rejecting duplicate pairs that arise when the same assignment is
inherited from multiple sources in the chain (e.g. a tag on both a
specific role and its parent role).

Updated `DummyAssignedTag.render()` in test_hostsync.py to accept
`**kwargs`. Documented the behavior in dynamic_values.md.

Tested: all 1076 existing tests pass.
The ZabbixTagAssignmentObjectViewTable used a TemplateColumn with a
custom template tag that called assignment.render() without passing
the device instance. This caused Jinja2 tag values to render against
the assigned_object (e.g. DeviceRole) instead of the actual device.

The fix switches to JinjaValueColumn (already used by the macro table),
which passes object=table.instance to render(). The attach_instance=True
flag is added to ensure table.instance is set, mirroring the macro
table pattern on the line above.

The accessor is set to zabbixtag__name because regex-rule-wrapper tags
have pk=None, and django-tables2 skips rendering when the accessor
resolves to None.

Tested: all 1092 existing tests pass.
- Use value accessor in tag ObjectViewTable
- Guard render() with try/except and success flag
@berlikm

berlikm commented Jul 14, 2026

Copy link
Copy Markdown
Author

This PR is part of the zero-touch provisioning feature set described in #121. Please see that issue for the full architecture and motivation.

berlikm added a commit to berlikm/nbxsync that referenced this pull request Jul 15, 2026
# Conflicts:
#	nbxsync/tables/zabbixtagassignment.py
@berlikm
berlikm force-pushed the fix/tag-table-device-context branch from 454151c to f38dac1 Compare July 16, 2026 07:33
When viewing assignment tables without a specific device context
(instance=None), record.render(object=None) would override the
default assigned_object with None, causing UndefinedError for
templates like {{ object.role.name }}.

Now only passes object=instance when instance is not None, falling
back to record.render() which uses the assignment's assigned_object.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant