Files
nmon/internal/testutil/testutil.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)
}
}