Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lx9FNLG2CqeBbVGGd9bFsP
103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
// Package testutil builds the fixtures WP5 tests share: a migrated SQLite
|
|
// store, simagent devices and inventory rows seeded by discovery.
|
|
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/v10networks/nmon/internal/clock"
|
|
"github.com/v10networks/nmon/internal/discovery"
|
|
"github.com/v10networks/nmon/internal/secrets"
|
|
"github.com/v10networks/nmon/internal/simagent"
|
|
"github.com/v10networks/nmon/internal/snmp"
|
|
"github.com/v10networks/nmon/internal/snmptarget"
|
|
"github.com/v10networks/nmon/internal/store"
|
|
)
|
|
|
|
// OpenStore returns a migrated SQLite store in a temp dir, closed at test end.
|
|
func OpenStore(t testing.TB, clk clock.Clock) store.Store {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
key := filepath.Join(dir, "secret.key")
|
|
if err := secrets.GenerateKeyFile(key); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
kr, err := secrets.LoadKeyring(key)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := context.Background()
|
|
st, err := store.Open(ctx, store.DriverSQLite, filepath.Join(dir, "inventory.db"), kr, clk)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() {
|
|
if err := st.Close(); err != nil {
|
|
t.Errorf("close store: %v", err)
|
|
}
|
|
})
|
|
if err := st.Migrate(ctx); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return st
|
|
}
|
|
|
|
// StartAgent serves cfg on [::1] (unless cfg.Addr says otherwise) until the test ends.
|
|
func StartAgent(t testing.TB, cfg simagent.Config) *simagent.Agent {
|
|
t.Helper()
|
|
a, err := simagent.Start(context.Background(), cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() {
|
|
if err := a.Close(); err != nil {
|
|
t.Errorf("close agent: %v", err)
|
|
}
|
|
})
|
|
return a
|
|
}
|
|
|
|
// AddDevice creates a v2c credential with the given community and a network
|
|
// device pointing at ::1, and seeds its interfaces from agent a.
|
|
func AddDevice(t testing.TB, st store.Store, a *simagent.Agent, name, community string, clk clock.Clock) *store.Device {
|
|
t.Helper()
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
defer cancel()
|
|
cred := &store.SNMPCredential{Name: name + "-cred", Version: "v2c", Community: community}
|
|
if err := st.CreateCredential(ctx, cred); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dev := &store.Device{Name: name, Kind: store.KindNetwork, SNMPCredentialID: &cred.ID, Enabled: true, Profile: "generic"}
|
|
if err := st.CreateDevice(ctx, dev); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.SetAddresses(ctx, dev.ID, []string{"::1"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
Seed(t, st, a, dev, cred, clk)
|
|
got, err := st.GetDeviceByID(ctx, dev.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return got
|
|
}
|
|
|
|
// Seed runs discovery.Seed for dev against agent a.
|
|
func Seed(t testing.TB, st store.Store, a *simagent.Agent, dev *store.Device, cred *store.SNMPCredential, clk clock.Clock) {
|
|
t.Helper()
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
defer cancel()
|
|
tg := snmptarget.For(a.Addr().Addr(), int(a.Addr().Port()), cred, clk)
|
|
sess, err := snmp.Dial(ctx, tg, "discovery")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer func() { _ = sess.Close() }() // read-only discovery session
|
|
if err := discovery.Seed(ctx, st, sess, dev, clk); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|