78 lines
2.9 KiB
Go
78 lines
2.9 KiB
Go
package operator_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"felis.lolicon.best/internal/apis/felis/v1alpha1"
|
|
"felis.lolicon.best/internal/metrics"
|
|
"felis.lolicon.best/internal/operator"
|
|
"github.com/prometheus/client_golang/prometheus/testutil"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
|
)
|
|
|
|
func gaugeServer(name string, state v1alpha1.DesiredState) *v1alpha1.MinecraftServer {
|
|
return &v1alpha1.MinecraftServer{
|
|
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "minecraft"},
|
|
Spec: v1alpha1.MinecraftServerSpec{Subdomain: name, DesiredState: state},
|
|
}
|
|
}
|
|
|
|
// TestGaugeSyncerPublishesFleetStateFromCluster drives SyncOnce against a fake
|
|
// client to verify the whole production path bar the ticker: List the fleet,
|
|
// translate each server to its desiredState (an unset state defaulting to
|
|
// Stopped), and republish felis_servers_total partitioned by that state.
|
|
func TestGaugeSyncerPublishesFleetStateFromCluster(t *testing.T) {
|
|
scheme := newScheme(t)
|
|
c := fake.NewClientBuilder().
|
|
WithScheme(scheme).
|
|
WithObjects(
|
|
gaugeServer("a", v1alpha1.DesiredRunning),
|
|
gaugeServer("b", v1alpha1.DesiredRunning),
|
|
gaugeServer("c", v1alpha1.DesiredStopped),
|
|
gaugeServer("d", ""), // unset desiredState must be counted as Stopped
|
|
).
|
|
Build()
|
|
|
|
g := &operator.GaugeSyncer{Client: c}
|
|
if err := g.SyncOnce(context.Background()); err != nil {
|
|
t.Fatalf("SyncOnce: %v", err)
|
|
}
|
|
|
|
if got := testutil.ToFloat64(metrics.ServersTotal.WithLabelValues("Running")); got != 2 {
|
|
t.Errorf("servers_total{state=Running} = %v, want 2", got)
|
|
}
|
|
// One explicit Stopped plus one unset (defaulted to Stopped) = 2.
|
|
if got := testutil.ToFloat64(metrics.ServersTotal.WithLabelValues("Stopped")); got != 2 {
|
|
t.Errorf("servers_total{state=Stopped} = %v, want 2", got)
|
|
}
|
|
}
|
|
|
|
// TestGaugeSyncerPublishesServerPhases: every server gets one felis_server_phase
|
|
// series carrying its system role, observed phase (Unknown before the first
|
|
// report) and desired state.
|
|
func TestGaugeSyncerPublishesServerPhases(t *testing.T) {
|
|
login := gaugeServer("login", v1alpha1.DesiredRunning)
|
|
login.Labels = map[string]string{v1alpha1.LabelSystemRole: "login"}
|
|
login.Status.Phase = v1alpha1.PhaseFailed
|
|
fresh := gaugeServer("fresh", "")
|
|
c := fake.NewClientBuilder().WithScheme(newScheme(t)).WithObjects(login, fresh).Build()
|
|
|
|
if err := (&operator.GaugeSyncer{Client: c}).SyncOnce(context.Background()); err != nil {
|
|
t.Fatalf("SyncOnce: %v", err)
|
|
}
|
|
defer metrics.ServerPhase.Reset()
|
|
if n := testutil.CollectAndCount(metrics.ServerPhase); n != 2 {
|
|
t.Fatalf("felis_server_phase series = %d, want 2", n)
|
|
}
|
|
for _, labels := range [][]string{
|
|
{"login", "login", "Failed", "Running"},
|
|
{"fresh", "", "Unknown", "Stopped"},
|
|
} {
|
|
if got := testutil.ToFloat64(metrics.ServerPhase.WithLabelValues(labels...)); got != 1 {
|
|
t.Errorf("felis_server_phase%v = %v, want 1", labels, got)
|
|
}
|
|
}
|
|
}
|