Skip to content

NMS-19876: Topology (Preview) REST API for operator info-panel templates (node and edge scoped)#8564

Open
marshallmassengill wants to merge 10 commits into
release-36.xfrom
NMS-19876-topology-infopanel-smoke
Open

NMS-19876: Topology (Preview) REST API for operator info-panel templates (node and edge scoped)#8564
marshallmassengill wants to merge 10 commits into
release-36.xfrom
NMS-19876-topology-infopanel-smoke

Conversation

@marshallmassengill

@marshallmassengill marshallmassengill commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Carries the etc/infopanel/ Jinjava template investment over to the new Vue topology map without the Vaadin dependency. A new read-only resource renders the operator's templates server-side and returns [{title, order, html}] for the UI's Inspector:

  • GET /api/v2/topology/infopanel?nodeId={id} — node-scoped panels. Context matches the legacy GenericInfoPanelItemProvider (node, nodeResource, read-only nodeDao/resourceDao wrappers, measurements), so existing node-scoped templates render unchanged.
  • GET /api/v2/topology/infopanel/edge?sourceNodeId=&targetNodeId=[&sourcePort=&targetPort=&protocol=] — edge-scoped panels. Templates receive an edge variable mirroring the legacy LinkdEdge surface (edge.discoveredBy, edge.sourcePort/targetPort with the node, port name, and the port's resolved OnmsSnmpInterface/ifIndex, matched by ifName then ifDescr). Legacy edge templates need one rename: edge.sourcePort.vertex →edge.sourcePort.node. The interface resolution is deliberate groundwork for planned link status/metrics work, which will key on the same identity.

Implementation: a Vaadin-free InfoPanelRenderer (jinjava + transitive deps packaged into the webapp); templates re-read per request so operators iterate without restarts; template errors skip that template rather than fail the request; missing template directory returns an empty list. Covered by renderer unit tests (node and edge contexts, visibility/order contract) and a REST integration test.

Assisted-by: Claude Code:Opus 4.8/Fable 5

Jira: https://opennms.atlassian.net/browse/NMS-19876

…node

A Vaadin-free, REST-exposed counterpart of the legacy topology map's
GenericInfoPanelItemProvider, so operators' existing etc/infopanel Jinjava
templates surface in the new Vue topology Inspector. GET
/api/v2/topology/infopanel?nodeId= returns [{title, order, html}] for the
node: each etc/infopanel/*.html template is rendered with an equivalent
context (node, nodeResource, nodeDao, resourceDao, measurements,
System:currentTimeMillis), and the visible, error-free results are sorted
by order.

- InfoPanelRenderer: the jinjava rendering (node-backed; vertex/edge are not
  populated, so vertex-only templates are simply not shown).
- NodeDaoWrapper / ResourceDaoWrapper / MeasurementsWrapper: read-only
  context wrappers mirroring the legacy ones so templates render unchanged.
- TopologyInfopanelRestService: read-only, @transactional so templates can
  traverse lazy node/resource associations; measurements optional.

The returned HTML is operator-authored; the client must sanitize before
injecting into the DOM.
opennms-webapp enumerates the 3rd-party libs that belong in WEB-INF/lib;
add jinjava (compile) so it and its runtime closure (JUEL shaded in,
plus javassist/re2j/big-math/hubspot-immutables/java-ipv6) ship in the
webapp and are visible -- via the shared webapp classloader -- to the
opennms-webapp-rest /api/v2/topology/infopanel renderer. Verified live:
the endpoint renders etc/infopanel templates for a node (context, visible
filter, and order all honored).
Exercises the endpoint through the full REST stack: 400 without a nodeId,
404 for an unknown node, and a 200 JSON array for a real node (empty in a
stock test environment with no etc/infopanel templates). Confirms the
resource and its autowired NodeDao/ResourceDao/MeasurementsService wire up.
Template rendering itself is covered by InfoPanelRendererTest.
Edge-scoped etc/infopanel/ templates (legacy createEdgeContext put the
selected edge into the Jinjava context) now have a counterpart:
GET /api/v2/topology/infopanel/edge?sourceNodeId=&targetNodeId=
[&sourcePort=&targetPort=&protocol=] renders templates with an 'edge'
variable mirroring the legacy LinkdEdge surface (discoveredBy,
sourcePort/targetPort with node, ifName, ifIndex). Port names resolve
to the node's OnmsSnmpInterface by ifName/ifDescr when they match;
that resolved interface is also the identity future link status and
metrics work will key on.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new REST surface for rendering operator-authored etc/infopanel/ Jinjava templates for the (Vue) Topology “Inspector” panel, removing the Vaadin dependency while preserving legacy template context compatibility (node- and edge-scoped).

Changes:

  • Added /api/v2/topology/infopanel (node-scoped) and /api/v2/topology/infopanel/edge (edge-scoped) REST endpoints that return rendered panels as [{title, order, html}].
  • Implemented a Vaadin-free Jinjava-based InfoPanelRenderer with legacy-parity context wrappers (NodeDaoWrapper, ResourceDaoWrapper, optional MeasurementsWrapper) plus an EdgeInfo model for edge-scoped rendering.
  • Added unit tests for the renderer and an integration test for the REST wiring; added Jinjava (+ measurements API) dependencies to the relevant web modules.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
opennms-webapp/pom.xml Adds Jinjava to ensure runtime availability for template rendering in the webapp packaging.
opennms-webapp-rest/pom.xml Adds Jinjava + measurements API dependency needed by the new REST infopanel implementation.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/TopologyInfopanelRestService.java New REST resource exposing node- and edge-scoped infopanel rendering.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/InfoPanelRenderer.java Core renderer: loads templates per request, renders via Jinjava, filters/sorts visible panels.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/InfoPanelItem.java DTO for returning {title, order, html} items as JSON.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/EdgeInfo.java Edge-scoped context model mirroring legacy LinkdEdge template surface.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/NodeDaoWrapper.java Read-only DAO wrapper for template context (limits reachable methods).
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/ResourceDaoWrapper.java Read-only ResourceDao wrapper for template context.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/infopanel/MeasurementsWrapper.java Measurements helper surface for templates (last values, queries, utilization).
opennms-webapp-rest/src/test/java/org/opennms/web/rest/v2/infopanel/InfoPanelRendererTest.java Unit tests for node/edge context rendering and visibility/order behavior.
opennms-webapp-rest/src/test/java/org/opennms/web/rest/v2/infopanel/TopologyInfopanelRestServiceIT.java Integration test verifying REST wiring, validation, and basic response shape.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@marshallmassengill marshallmassengill changed the base branch from develop to release-36.x June 11, 2026 18:20
- computeUtilization no longer builds JEXL expressions (the legacy
  expressions this was ported from reference misspelled variables and
  lean on engine quirks): the in/out rates are queried as plain columns
  and the percentages computed in Java from the interface's ifHighSpeed
  constant in the query response. Missing speed or columns degrade to
  NaN, matching the method's existing contract.
- The renderer skips a template on any per-template failure
  (IOException or RuntimeException) instead of letting e.g. a
  ClassCastException from a non-numeric 'order' fail the whole request;
  the order value itself is also extracted defensively.
- IT now exercises the edge endpoint: parameter validation (400),
  unknown node (404), and a rendered (empty) result for a real node.
The tarball assembly's license-maven-plugin add-third-party check
requires every aggregated dependency to declare a license. Four of
jinjava's transitives (com.hubspot:algebra and the three
com.hubspot.immutables support jars) ship no license metadata in their
poms; all are HubSpot OSS under the Apache License 2.0, same as jinjava
itself. Map them in THIRD-PARTY.properties.
Same four HubSpot Apache-2.0 mappings as the xsds assembly: the
license check walks each assembly module in turn, and the full
assembly aggregates the webapp closure as well.
jinjava transitively pulls the jackson stack, javassist, and
commons-net into the webapp. All of these already ship (same versions)
in $OPENNMS_HOME/lib on the webapp's parent classloader, and the
duplicate copies broke webapp startup in the smoke environment with
  LinkageError: loader constraint violation ... ObjectMapper
while initializing the cxf-rest-v2 bean, taking the whole container
down. Exclude them from the jinjava dependency so only jinjava's
genuinely new closure (re2j, java-ipv6, big-math, the HubSpot jars)
lands in WEB-INF/lib.
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.

2 participants