Files
nmon/.golangci.yml
Vibe Coder 7173360346 Add the MAC/ARP/FDB table job, the lookup API, BGP peer collection and bgp_peer_down
Owner request: finding where a host is plugged in from a MAC or IP is a must,
and BGP peer monitoring is wanted.

L2 job (internal/l2): a job of its own, off the 60 s poll path (its sessions
are path "l2"), walks BRIDGE-MIB, Q-BRIDGE-MIB, CISCO-VTP-MIB (a per-VLAN
context walk, enabled by the cisco-ios profile flag l2.per_vlan_context, not by
detection) and the IP-MIB neighbour tables (IPv4 ARP and IPv6 ND, IPv4-only
fallback) every l2.interval, with its own concurrency cap and a per-device
deadline. It yields to the poller like the rollup job, and a device that times
out is skipped for the cycle, counted and named on /poller/health. Migration 14
adds fdb_entries, arp_entries, vlans and l2_walks with first/last-seen history,
batched upserts, daily pruning by last_seen (l2.keep) and backup coverage.

API (additive): /l2/search ranks edge ports first (a port is an uplink above
l2.edge_max_macs MACs, with an LLDP neighbour, or as a LAG), plus the device
fdb/arp/l2/l2-ports tables and /interfaces/{id}/macs; vendor and mac_kind are
computed at query time from the optional registry.

BGP: profiles label peer rows by decoding the table index (index_label.layout),
so each peer, IPv4 or IPv6, is one component whatever MIB feeds it; AS, local
AS, router id and description are component attributes, never labels.
CISCO-BGP4 (cisco-ios, cisco-nxos), Juniper BGP4-V2 and Arista BGP4V2 replace
the optional generic BGP4-MIB metrics, which edgeos, fortigate, pfsense and vyos
switch on. /bgp/peers lists sessions down first. The built-in rule
bgp_peer_down (critical, not established for 2 minutes) fires only where a
policy binds it; its notification names the peer's AS and description.

Fixtures are generated (Q-BRIDGE with IPv4/IPv6 neighbours, BRIDGE-MIB only,
Cisco per-VLAN contexts via a new simagent contexts feature) and checked
against real LibreNMS recordings. DEVIATIONS 50-55 record the departures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4PdJUPrakM8fHvN8jYv2x
2026-10-24 01:30:32 +00:00

162 lines
5.3 KiB
YAML

# Enforces docs/MAINTAINABILITY.md. A hard rule: `make lint` must be clean for any gate to pass.
version: "2"
run:
timeout: 10m
tests: true
# Report every finding: funlen and gocognit flag the same line and must both show.
issues:
max-issues-per-linter: 0
max-same-issues: 0
uniq-by-line: false
linters:
default: none
enable:
- govet
- errcheck
- staticcheck
- unused
- ineffassign
- funlen
- cyclop
- gocognit
- nestif
- dupl
- lll
- errorlint
- usestdlibvars
- misspell
- revive
- depguard
- forbidigo
- nolintlint
- unconvert
- bodyclose
- copyloopvar
settings:
funlen:
lines: 80
statements: 50
ignore-comments: true
cyclop:
max-complexity: 15
gocognit:
min-complexity: 20
nestif:
min-complexity: 4
dupl:
threshold: 150
lll:
line-length: 140
misspell:
# MikroTik's OS name and a profile name, not a typo of "routers".
ignore-rules: [routeros]
nolintlint:
require-explanation: true
require-specific: true
revive:
rules:
- name: exported
arguments: ["disableStutteringCheck"]
- name: package-comments
- name: var-naming
- name: indent-error-flow
- name: error-strings
- name: receiver-naming
- name: unexported-return
forbidigo:
analyze-types: true
forbid:
- pattern: '^time\.(Now|Sleep|After|Tick|NewTicker|NewTimer)$'
msg: "use internal/clock so tests control time (docs/MAINTAINABILITY.md)"
depguard:
rules:
orm-only-in-store:
files: ["$all", "!**/internal/store/**"]
deny:
- pkg: github.com/uptrace/bun
desc: SQL and the ORM live only in internal/store
- pkg: database/sql
desc: SQL lives only in internal/store
app-only-from-cmd:
files: ["$all", "!**/cmd/**"]
deny:
- pkg: github.com/v10networks/nmon/internal/app
desc: only cmd/* wires the application
api-only-from-app:
files: ["$all", "!**/internal/app/**", "!**/internal/api/**", "!$test"]
deny:
- pkg: github.com/v10networks/nmon/internal/api
desc: only internal/app mounts the API
collection-paths-independent:
files:
- "**/internal/poller/**"
- "**/internal/discovery/**"
- "**/internal/traps/**"
- "**/internal/ingest/**"
- "**/internal/checks/**"
- "**/internal/rollup/**"
- "**/internal/alert/**"
- "**/internal/l2/**"
deny:
- pkg: github.com/v10networks/nmon/internal/poller
desc: collection paths share code via a lower package, not each other
- pkg: github.com/v10networks/nmon/internal/discovery
desc: collection paths share code via a lower package, not each other
- pkg: github.com/v10networks/nmon/internal/traps
desc: collection paths share code via a lower package, not each other
- pkg: github.com/v10networks/nmon/internal/l2
desc: collection paths share code via a lower package, not each other
devtools-not-in-nmon:
# The product binary never links dev/test machinery. `nmon profile record` needs only the
# .snmprec format, which lives in internal/snmprec.
files: ["**/cmd/nmon/**", "!$test"]
deny:
- pkg: github.com/v10networks/nmon/internal/simagent
desc: the simulator belongs to cmd/nmon-devtools and tests, never the shipped binary
- pkg: github.com/v10networks/nmon/internal/fixturegen
desc: the fixture generator belongs to cmd/nmon-devtools and tests, never the shipped binary
- pkg: github.com/v10networks/nmon/internal/fixtures
desc: fixtures are test data, never the shipped binary
- pkg: github.com/v10networks/nmon/internal/testutil
desc: test helpers are never in the shipped binary
devtools-no-core:
files: ["**/cmd/nmon-devtools/**"]
deny:
- pkg: github.com/v10networks/nmon/internal/app
desc: nmon-devtools talks to a running nmon over HTTP
- pkg: github.com/v10networks/nmon/internal/api
desc: nmon-devtools talks to a running nmon over HTTP
importer-not-in-nmon:
files: ["**/cmd/nmon/**"]
deny:
- pkg: github.com/v10networks/nmon/internal/librenms
desc: the LibreNMS importer is a separate tool (DEVIATIONS 9)
exclusions:
paths:
- web/node_modules
rules:
# Table-driven tests are long by nature; every other linter still applies.
- path: _test\.go
linters: [funlen, cyclop, gocognit, nestif, dupl, lll, forbidigo]
# The clock package wraps time; cmd/ and the test-only simulator may use real time.
- path: internal/clock/
linters: [forbidigo]
- path: cmd/
linters: [forbidigo]
# A package is allowed to import itself's own test helpers and itself.
- path: internal/(poller|discovery|traps)/.*_test\.go
linters: [depguard]
formatters:
enable:
- gofmt
- goimports
exclusions:
paths:
- web/node_modules