blob: 89d5b5eb2daf25730d43e92a9ccaabc3f0929452 [file] [log] [blame] [edit]
package scruffy
import (
"context"
"fmt"
"sort"
"strings"
"testing"
"github.com/prometheus/client_golang/prometheus"
"source.monogon.dev/cloud/bmaas/bmdb"
"source.monogon.dev/cloud/bmaas/bmdb/model"
"source.monogon.dev/cloud/lib/component"
)
func TestBMDBStats(t *testing.T) {
s := Server{
Config: Config{
BMDB: bmdb.BMDB{
Config: bmdb.Config{
Database: component.CockroachConfig{
InMemory: true,
},
},
},
},
}
registry := prometheus.NewRegistry()
runner := newBMDBStatsRunner(&s, registry)
ctx, ctxC := context.WithCancel(context.Background())
defer ctxC()
expect := func(wantValues map[string]int64) {
t.Helper()
res, err := registry.Gather()
if err != nil {
t.Fatalf("Gather: %v", err)
}
gotValues := make(map[string]bool)
for _, mf := range res {
if len(mf.Metric) != 1 {
for _, m := range mf.Metric {
var lvs []string
for _, lp := range m.Label {
lvs = append(lvs, fmt.Sprintf("%s=%s", *lp.Name, *lp.Value))
}
sort.Strings(lvs)
name := fmt.Sprintf("%s[%s]", *mf.Name, strings.Join(lvs, ","))
gotValues[name] = true
if _, ok := wantValues[name]; !ok {
t.Errorf("MetricFamily %s: unexpected", name)
}
if want, got := wantValues[name], int64(*m.Gauge.Value); want != got {
t.Errorf("MetricFamily %s: wanted %d, got %d", *mf.Name, want, got)
}
}
} else {
m := mf.Metric[0]
gotValues[*mf.Name] = true
if want, got := wantValues[*mf.Name], int64(*m.Gauge.Value); want != got {
t.Errorf("MetricFamily %s: wanted %d, got %d", *mf.Name, want, got)
}
if _, ok := wantValues[*mf.Name]; !ok {
t.Errorf("MetricFamily %s: unexpected", *mf.Name)
}
}
}
for mf, _ := range wantValues {
if !gotValues[mf] {
t.Errorf("MetricFamily %s: missing", mf)
}
}
}
expect(map[string]int64{
"bmdb_stats_machines": 0,
"bmdb_stats_machines_provided": 0,
"bmdb_stats_machines_heartbeating": 0,
"bmdb_stats_machines_pending_installation": 0,
"bmdb_stats_machines_installed": 0,
"bmdb_stats_machines_pending_agent_start": 0,
"bmdb_stats_machines_pending_agent_recovery": 0,
"bmdb_stats_active_backoffs[process=ShepherdAccess]": 0,
"bmdb_stats_active_backoffs[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_backoffs[process=ShepherdRecovery]": 0,
"bmdb_stats_active_work[process=ShepherdAccess]": 0,
"bmdb_stats_active_work[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_work[process=ShepherdRecovery]": 0,
})
conn, err := s.Config.BMDB.Open(true)
if err != nil {
t.Fatalf("Open: %v", err)
}
sess, err := conn.StartSession(ctx)
if err != nil {
t.Fatalf("StartSession: %v", err)
}
s.bmdb = conn
s.sessionC = make(chan *bmdb.Session)
go s.sessionWorker(ctx)
if err := runner.runOnce(ctx); err != nil {
t.Fatal(err)
}
expect(map[string]int64{
"bmdb_stats_machines": 0,
"bmdb_stats_machines_provided": 0,
"bmdb_stats_machines_heartbeating": 0,
"bmdb_stats_machines_pending_installation": 0,
"bmdb_stats_machines_installed": 0,
"bmdb_stats_machines_pending_agent_start": 0,
"bmdb_stats_machines_pending_agent_recovery": 0,
"bmdb_stats_active_backoffs[process=ShepherdAccess]": 0,
"bmdb_stats_active_backoffs[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_backoffs[process=ShepherdRecovery]": 0,
"bmdb_stats_active_work[process=ShepherdAccess]": 0,
"bmdb_stats_active_work[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_work[process=ShepherdRecovery]": 0,
})
f := fill().
// Provided, needs installation.
machine().providedE("1").build().
// Three machines needing recovery.
machine().providedE("2").agentNeverHeartbeat().build().
machine().providedE("3").agentNeverHeartbeat().build().
machine().providedE("4").agentNeverHeartbeat().build().
// One machine correctly heartbeating.
machine().providedE("5").agentHealthy().build().
// Two machines heartbeating and pending installation.
machine().providedE("6").agentHealthy().installRequested(10).build().
machine().providedE("7").agentHealthy().installRequested(10).installReported(9).build().
// Machine which is pending installation _and_ recovery.
machine().providedE("8").agentNeverHeartbeat().installRequested(10).build().
// Machine which has been successfully installed.
machine().providedE("9").agentStoppedHeartbeating().installRequested(10).installReported(10).build()
err = sess.Transact(ctx, func(q *model.Queries) error {
return f(ctx, q)
})
if err != nil {
t.Fatal(err)
}
if err := runner.runOnce(ctx); err != nil {
t.Fatal(err)
}
expect(map[string]int64{
"bmdb_stats_machines": 9,
"bmdb_stats_machines_provided": 9,
"bmdb_stats_machines_heartbeating": 3,
"bmdb_stats_machines_pending_installation": 3,
"bmdb_stats_machines_installed": 1,
"bmdb_stats_machines_pending_agent_start": 1,
"bmdb_stats_machines_pending_agent_recovery": 4,
"bmdb_stats_active_backoffs[process=ShepherdAccess]": 0,
"bmdb_stats_active_backoffs[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_backoffs[process=ShepherdRecovery]": 0,
"bmdb_stats_active_work[process=ShepherdAccess]": 0,
"bmdb_stats_active_work[process=ShepherdAgentStart]": 0,
"bmdb_stats_active_work[process=ShepherdRecovery]": 0,
})
}