Files
nmon/internal/notify/sample.go
Vibe Coder f31fb3712a
Some checks failed
ci / lint (push) Successful in 4m19s
ci / openapi (push) Successful in 29s
ci / postgres (push) Successful in 4m55s
ci / test (push) Failing after 19m48s
Add settings forms, first-install wizard, webhook presets, help and poll tools
Make nmon easier to install and run without editing YAML by hand:

- Settings: point-and-click forms over config.yaml (GET/PUT
  /api/v1/settings/form); the YAML editor moves to /settings/yaml.
- First install: with no sign-in configured nmon starts in install
  mode, serves only the setup wizard (sign-in, basics, devices,
  alerting) and closes it for good once sign-in is saved. A
  self-signed certificate is generated when no TLS source is given.
  poller.interval becomes a config setting.
- Reverse proxies: opt-in --http-listen plain-HTTP listener beside
  HTTPS; sign-in stays required.
- Webhooks: Generic, Teams Adaptive Card, Slack and Discord presets,
  template preview and test send.
- Help: the operations, coverage and profile docs served at /help.
- Polling: per-device "Poll now", a dry-run test poll returning an
  SNMP trace, and time-limited in-memory SNMP debug recording, in the
  UI and as `nmon device poll`.
- Ansible: deploys into install mode when no sign-in is set, and no
  longer overwrites the config.yaml the wizard wrote.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017TuKgyKve2XLFtrrXWMi2w
2026-10-25 06:31:12 +00:00

54 lines
1.9 KiB
Go

package notify
import (
"fmt"
"slices"
"time"
)
// States lists every Notification state a template can see, in the order the UI offers them.
func States() []string {
return []string{StateFiring, StateResolved, StateFlapping, StateStale, StateSuppressedSummary}
}
// ValidState reports whether s is a Notification state.
func ValidState(s string) bool { return slices.Contains(States(), s) }
// SampleNotification is a realistic notification in the given state for previews and test sends. It never
// reads the clock: now is the "cleared" instant and the fired instant is 12 minutes earlier.
func SampleNotification(state string, now time.Time) Notification {
fired := now.Add(-12 * time.Minute).UTC()
var n Notification
n.AlertID = 4242
n.IncidentID = IncidentID(n.AlertID, fired)
n.Rule = "interface_down"
n.State = state
n.Severity = "critical"
n.Device.Slug, n.Device.Name = "core-sw1", "Core switch 1"
n.Interface.ID, n.Interface.Name, n.Interface.Alias = "01J9ZXAMPLE0000000000000", "ge-0/0/1", "Uplink to Edge-A"
n.Summary = "Interface ge-0/0/1 on core-sw1 is down"
n.Description = "Operational status has been down for 3 consecutive polls."
n.FiredAt = fired
n.Labels = map[string]string{"site": "dc1", "role": "core"}
n.URL = "https://nmon.example.net/devices/core-sw1"
switch state {
case StateResolved:
c := now.UTC()
n.ClearedAt = &c
n.Summary = "Interface ge-0/0/1 on core-sw1 recovered"
n.Severity = "info"
case StateFlapping:
n.Severity = "warning"
n.Summary = "Interface ge-0/0/1 on core-sw1 is flapping"
case StateStale:
n.Severity = "warning"
n.Summary = "No data from core-sw1 for 15 minutes"
case StateSuppressedSummary:
n.Interface.ID, n.Interface.Name, n.Interface.Alias = "", "", ""
n.Parents = []string{"edge-a"}
n.SuppressedChildren = 12
n.Summary = fmt.Sprintf("%d alerts suppressed behind edge-a", n.SuppressedChildren)
}
return n
}