Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Generated from the README compatibility table by `scripts/gen_changelog.py`. Do not edit by hand.

## v2.4.3

Fix: the pinned-query opt-in Health warning (2.4.1) over-claimed failure — it reads "nothing new syncs" and fires on any pinned map with the feature on, even after the query is fixed, because the Health page can't read a pinned query's contents. Reworded to a "Pinned — can't verify locally" heads-up that points at **Export Live Query Drift** to confirm (`source_matches_bundled`), instead of asserting failure. No behavior change.

## v2.4.2

Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing (validated live: 355 Avocent endpoints import; `Mgmt_*` tags sync). Adds a **Publish Bundled Queries** button on the sync Health page (beside Refresh Query IDs) and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (they double-apply rows for the same model and churn — enable one). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ Latest release requires NetBox `4.6.4` and `netbox-branching` `1.1.0+`. Expand f

| Plugin Release | NetBox Version | Status |
| --- | --- | --- |
| `v2.4.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Current release; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing (validated live: 355 Avocent endpoints import; `Mgmt_*` tags sync). Adds a **Publish Bundled Queries** button on the sync Health page (beside Refresh Query IDs) and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (they double-apply rows for the same model and churn — enable one). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.3` | `4.6.4` required; needs netbox-branching `1.1.0+` | Current release; Fix: the pinned-query opt-in Health warning (2.4.1) over-claimed failure — it reads "nothing new syncs" and fires on any pinned map with the feature on, even after the query is fixed, because the Health page can't read a pinned query's contents. Reworded to a "Pinned — can't verify locally" heads-up that points at **Export Live Query Drift** to confirm (`source_matches_bundled`), instead of asserting failure. No behavior change. |
| `v2.4.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.3`; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing (validated live: 355 Avocent endpoints import; `Mgmt_*` tags sync). Adds a **Publish Bundled Queries** button on the sync Health page (beside Refresh Query IDs) and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (they double-apply rows for the same model and churn — enable one). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.1` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.2`; Fix: opt-in features (SNMP endpoint import, device-tag sync) silently did nothing on sources that run org-managed **pinned** Forward query IDs predating the feature — the sync Health page now raises an actionable warning instead of a silent badge. Remediation: publish the bundled queries to your Forward org folder (Overwrite on), then use Refresh Query IDs, then re-sync. |
| `v2.4.0` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.1`; Fix: the "Import SNMP Endpoints as Devices" toggle now renders on the source form (the field shipped in 2.3.2 but was not in any fieldset, so it never showed), letting operators enable endpoint import from the GUI. |
| `v2.3.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.0`; Feature: optional import of Forward SNMP endpoints (e.g. Avocent console servers) as NetBox devices — off by default (`sync_endpoints`), enabled per source and scoped by the same device tags. |
Expand Down
9 changes: 5 additions & 4 deletions docs/01_User_Guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ pip install forward-netbox
Alternatively, install a specific wheel or source archive from GitHub Releases:

```bash
pip install /path/to/forward_netbox-2.4.2-py3-none-any.whl
pip install /path/to/forward_netbox-2.4.2.tar.gz
pip install /path/to/forward_netbox-2.4.3-py3-none-any.whl
pip install /path/to/forward_netbox-2.4.3.tar.gz
```

If you mirror the package into a private Python index, pin the same release version:

```bash
pip install forward-netbox==2.4.2
pip install forward-netbox==2.4.3
```

## Release Compatibility
Expand All @@ -39,7 +39,8 @@ Latest release requires NetBox `4.6.4` and `netbox-branching` `1.1.0+`. Expand f

| Plugin Release | NetBox Version | Status |
| --- | --- | --- |
| `v2.4.2` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Current release; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing. Adds a **Publish Bundled Queries** button on the sync Health page and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (duplicate-emission churn). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.3` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Current release; Fix: the pinned-query opt-in Health warning (2.4.1) over-claimed failure and fired even after the query was fixed (the Health page can't read a pinned query's contents). Reworded to a "Pinned — can't verify locally" heads-up pointing at Export Live Query Drift to confirm. No behavior change. |
| `v2.4.2` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.4.3`; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing. Adds a **Publish Bundled Queries** button on the sync Health page and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (duplicate-emission churn). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.1` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.4.2`; Fix: opt-in features (SNMP endpoint import, device-tag sync) silently did nothing on sources that run org-managed **pinned** Forward query IDs predating the feature — the sync Health page now raises an actionable warning instead of a silent badge. Remediation: publish the bundled queries to your Forward org folder (Overwrite on), then use Refresh Query IDs, then re-sync. |
| `v2.4.0` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.4.1`; Fix: the "Import SNMP Endpoints as Devices" toggle now renders on the source form (the field shipped in 2.3.2 but was not in any fieldset, so it never showed), letting operators enable endpoint import from the GUI. |
| `v2.3.2` | `4.6.4` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.4.0`; Feature: optional import of Forward SNMP endpoints (e.g. Avocent console servers) as NetBox devices — off by default (`sync_endpoints`), enabled per source and scoped by the same device tags. |
Expand Down
46 changes: 46 additions & 0 deletions docs/03_Plans/active/2026-07-08-soften-pinned-optin-warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Reword the pinned-query opt-in Health warning (2.4.3)

## Goal

Stop the 2.4.1 pinned-query opt-in warning from reading as a confirmed failure.
It fires on any `query_id` map with the feature enabled — including one that is
already current after publishing — and its wording ("silently ignored, so
nothing new syncs") led a design partner to think the fix hadn't worked.

## Constraints

- Wording-only; no change to when the warning fires or to any sync behavior.
- Must keep the badge label in sync with the elevated status (the 2.4.1 bug).
- Point operators at the check that CAN verify (Export Live Query Drift).

## Touched Surfaces

- `forward_netbox/utilities/health.py` (`_elevate_optin_pinned_query_drift` message/remediation/label)
- `forward_netbox/utilities/query_binding_resolution.py` (`_QUERY_DRIFT_STATUS_LABELS` badge)
- `forward_netbox/tests/test_endpoints_import.py` (assert new wording)

## Approach

- Badge label `direct_query_id_optin_stale_risk` → "Pinned — can't verify
locally".
- Message: state the Health page can't inspect a pinned query locally; frame the
staleness as a possibility ("may predate the feature"), not a fact.
- Remediation: verify with Export Live Query Drift (`source_matches_bundled`)
first; only if it mismatches, Publish Bundled Queries → Refresh Query IDs →
re-sync.

## Validation

`test_endpoints_import` asserts the reworded label/message/remediation and that
the badge tracks the elevated status. Full suite + lint + harness green.

## Rollback

Revert the branch — pure wording + test; no data or behavior change.

## Decision Log

- Keep severity `warn` (still a legitimate unverifiable-config heads-up) rather
than downgrading to `info`, which would hide the genuinely-stale case again.
The local summary intentionally makes no live call; the fix is honest wording
plus a pointer to the on-demand live check.
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ Latest release requires NetBox `4.6.4` and `netbox-branching` `1.1.0+`. Expand f

| Plugin Release | NetBox Version | Status |
| --- | --- | --- |
| `v2.4.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Current release; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing. Adds a **Publish Bundled Queries** button on the sync Health page and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (duplicate-emission churn). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.3` | `4.6.4` required; needs netbox-branching `1.1.0+` | Current release; Fix: the pinned-query opt-in Health warning (2.4.1) over-claimed failure and fired even after the query was fixed (the Health page can't read a pinned query's contents). Reworded to a "Pinned — can't verify locally" heads-up pointing at Export Live Query Drift to confirm. No behavior change. |
| `v2.4.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.3`; Fix: endpoint import (`sync_endpoints`) and device-tag sync (`sync_device_tags`) now work with the alias-aware and rules-aware query variants (`forward_devices_with_netbox_aliases`, `forward_device_feature_tags_with_rules`), not just the base queries — operators running the variants saw the toggles silently do nothing. Adds a **Publish Bundled Queries** button on the sync Health page and two Health warnings: when an opt-in feature is enabled but no enabled map provides it, and when a base query and its opt-in variant are both enabled (duplicate-emission churn). The alias-aware device query now emits the clean role name (e.g. `ROUTER`) to match the base query — expect a one-time role update on alias-mapped devices. |
| `v2.4.1` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.2`; Fix: opt-in features (SNMP endpoint import, device-tag sync) silently did nothing on sources that run org-managed **pinned** Forward query IDs predating the feature — the sync Health page now raises an actionable warning instead of a silent badge. Remediation: publish the bundled queries to your Forward org folder (Overwrite on), then use Refresh Query IDs, then re-sync. |
| `v2.4.0` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.1`; Fix: the "Import SNMP Endpoints as Devices" toggle now renders on the source form (the field shipped in 2.3.2 but was not in any fieldset, so it never showed), letting operators enable endpoint import from the GUI. |
| `v2.3.2` | `4.6.4` required; needs netbox-branching `1.1.0+` | Superseded by `v2.4.0`; Feature: optional import of Forward SNMP endpoints (e.g. Avocent console servers) as NetBox devices — off by default (`sync_endpoints`), enabled per source and scoped by the same device tags. |
Expand Down
2 changes: 1 addition & 1 deletion forward_netbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class NetboxForwardConfig(PluginConfig):
name = "forward_netbox"
verbose_name = "Forward"
description = "Sync Forward data into NetBox using built-in NQE queries."
version = "2.4.2"
version = "2.4.3"
base_url = "forward"
min_version = "4.6.4"

Expand Down
6 changes: 5 additions & 1 deletion forward_netbox/tests/test_endpoints_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,13 @@ def test_endpoints_enabled_elevates_pinned_device_query(self):
self.assertEqual(drift[0]["severity"], "warn")
self.assertEqual(drift[0]["status"], "direct_query_id_optin_stale_risk")
self.assertIn("Refresh Query IDs", drift[0]["remediation"])
# Wording is a "can't verify locally" heads-up pointing at the live
# check, not a confirmed failure.
self.assertIn("Live Query Drift", drift[0]["remediation"])
self.assertIn("can't inspect locally", drift[0]["message"])
# Badge label must track the elevated status, not the stale build-time one.
self.assertNotEqual(drift[0].get("status_label"), "Org-managed (pinned)")
self.assertIn("predate", drift[0].get("status_label", ""))
self.assertIn("verify", drift[0].get("status_label", ""))

def test_endpoints_disabled_leaves_pinned_device_query_silent(self):
drift = [self._pinned("forward_devices.nqe")]
Expand Down
18 changes: 12 additions & 6 deletions forward_netbox/utilities/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,23 @@ def _elevate_optin_pinned_query_drift(query_drift, source_parameters):
# stale "Org-managed (pinned)" badge on the elevated row.
item["status_label"] = _QUERY_DRIFT_STATUS_LABELS.get(
"direct_query_id_optin_stale_risk",
"Pinned — may predate an enabled feature",
"Pinned — can't verify locally",
)
item["severity"] = "warn"
# This is a "can't verify locally" heads-up, not a confirmed failure:
# the Health page can't read a pinned query's contents, so it warns for
# any pinned map with the feature on — including one that's already
# current after publishing. Point at the live check, don't claim failure.
item["message"] = (
f"“{label}” is enabled, but this map runs a pinned Forward query ID. "
"If that query predates the feature it is silently ignored, so "
"nothing new syncs."
f"“{label}” is enabled and this map runs a pinned Forward query ID, "
"which the Health page can't inspect locally to confirm it includes "
"the feature. If those rows aren't importing, the pinned query may "
"predate the feature."
)
item["remediation"] = (
"Publish the bundled queries to your Forward org folder (Overwrite "
"on), then use Refresh Query IDs on this Health page, then re-run the "
"Use Export Live Query Drift on this page to confirm the pinned "
"query matches the current bundled source. If it doesn't, use "
"Publish Bundled Queries, then Refresh Query IDs, then re-run the "
"sync."
)
item["remediation_action"] = "refresh_query_ids"
Expand Down
2 changes: 1 addition & 1 deletion forward_netbox/utilities/query_binding_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ def _committed_query_source(committed_query: dict) -> str:
# read like an error.
_QUERY_DRIFT_STATUS_LABELS = {
"direct_query_id_unverified": "Org-managed (pinned)",
"direct_query_id_optin_stale_risk": "Pinned — may predate an enabled feature",
"direct_query_id_optin_stale_risk": "Pinned — can't verify locally",
}


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "forward-netbox"
version = "2.4.2"
version = "2.4.3"
description = "NetBox plugin to sync Forward data into NetBox via built-in NQE queries"
authors = ["Craig Johnson <craigjohnson@forwardnetworks.com>"]
license = "MIT"
Expand Down
Loading