Files
ProxmoxDash/agent_test.go
2026-08-07 21:23:05 +03:00

147 lines
5.4 KiB
Go

package main
import (
"os"
"testing"
"time"
)
func TestAgentEnrollmentTokenIsSingleUse(t *testing.T) {
store, err := openStore(":memory:")
if err != nil {
t.Fatal(err)
}
defer store.Close()
token, err := store.CreateAgentEnrollmentToken()
if err != nil {
t.Fatal(err)
}
credentials, err := store.EnrollAgent(agentEnrollmentRequest{Token: token, Name: "docker-01", Hostname: "vm105", VMID: 105})
if err != nil {
t.Fatal(err)
}
if credentials.ID == "" || credentials.Secret == "" {
t.Fatal("credentials were not generated")
}
if _, err = store.EnrollAgent(agentEnrollmentRequest{Token: token, Hostname: "duplicate"}); err == nil {
t.Fatal("token was accepted twice")
}
}
func TestCurrentAgentUpdateManifestMatchesExecutable(t *testing.T) {
manifest, path, err := currentAgentUpdate()
if err != nil {
t.Fatal(err)
}
if manifest.URL != "/api/agent/binary" || len(manifest.SHA256) != 64 {
t.Fatalf("unexpected manifest: %#v", manifest)
}
if _, err = os.Stat(path); err != nil {
t.Fatal(err)
}
}
func TestAgentOnlyInstallsNewerVersion(t *testing.T) {
if !newerAgentVersion("v0.14.0", "v0.13.0") {
t.Fatal("new version was not detected")
}
if newerAgentVersion("v0.12.0", "v0.13.0") {
t.Fatal("downgrade was allowed")
}
if newerAgentVersion("v0.13.0", "v0.13.0") {
t.Fatal("same version was offered")
}
}
func TestParseAgentIssues(t *testing.T) {
issues := parseAgentIssues(`{"MESSAGE":"disk error","_SYSTEMD_UNIT":"worker.service","__REALTIME_TIMESTAMP":"1722960000000000"}` + "\n" + `{"MESSAGE":"network error","__REALTIME_TIMESTAMP":"1722960001000000"}`)
if len(issues) != 2 || issues[0].Unit != "worker.service" || issues[1].Unit != "system" || issues[0].Time != 1722960000 {
t.Fatalf("unexpected issues: %#v", issues)
}
}
func TestClassifyAgentService(t *testing.T) {
cases := []struct{ path, pkg, priority, want string }{{"/lib/systemd/system/cron.service", "cron", "important", "system"}, {"/lib/systemd/system/jellyfin.service", "jellyfin", "optional", "added"}, {"/etc/systemd/system/my.service", "", "", "local"}, {"/run/systemd/system/transient.service", "", "", "runtime"}}
for _, tc := range cases {
if got := classifyAgentService(tc.path, tc.pkg, tc.priority); got != tc.want {
t.Errorf("%s: got %s want %s", tc.path, got, tc.want)
}
}
}
func TestAgentServiceDiagnosticsHelpers(t *testing.T) {
if got := compactSystemdExec(`{ path=/usr/bin/example ; argv[]=/usr/bin/example --serve ; }`); got != "/usr/bin/example" {
t.Fatalf("unexpected executable: %q", got)
}
fields := limitedFields("a b c d", 2)
if len(fields) != 2 || fields[0] != "a" || fields[1] != "b" {
t.Fatalf("unexpected limited fields: %#v", fields)
}
ports := appendUniqueInt([]int{80}, 80)
ports = appendUniqueInt(ports, 443)
if len(ports) != 2 || ports[1] != 443 {
t.Fatalf("unexpected ports: %#v", ports)
}
}
func TestAgentReportAuthenticationAndOfflineState(t *testing.T) {
store, err := openStore(":memory:")
if err != nil {
t.Fatal(err)
}
defer store.Close()
token, _ := store.CreateAgentEnrollmentToken()
credentials, _ := store.EnrollAgent(agentEnrollmentRequest{Token: token, Name: "docker", Hostname: "vm", VMID: 101})
report := AgentReport{Hostname: "vm", Version: "test", DockerAvailable: true, Containers: []AgentContainer{{ID: "abc", Name: "web", State: "running"}}}
if err = store.SaveAgentReport(credentials.ID, "wrong", "127.0.0.1", report); err == nil {
t.Fatal("invalid secret accepted")
}
if err = store.SaveAgentReport(credentials.ID, credentials.Secret, "127.0.0.1", report); err != nil {
t.Fatal(err)
}
agents, err := store.Agents()
if err != nil {
t.Fatal(err)
}
if len(agents) != 1 || !agents[0].Online || len(agents[0].Report.Containers) != 1 {
t.Fatalf("unexpected agents: %#v", agents)
}
_, _ = store.db.Exec(`UPDATE agents SET last_seen=? WHERE id=?`, time.Now().Add(-time.Minute).Unix(), credentials.ID)
agents, _ = store.Agents()
if agents[0].Online {
t.Fatal("stale agent is online")
}
}
func TestAgentProblemsBecomeMaintenanceAwareAlerts(t *testing.T) {
metrics := dashboardMetrics{Agents: []ManagedAgent{{ID: "node", Name: "app", VMID: 105, Online: true, Report: AgentReport{
Services: []AgentService{{Name: "postgres.service", State: "failed", SubState: "failed"}},
Containers: []AgentContainer{{ID: "dead", Name: "web", State: "exited", Status: "Exited (1)"}}, DockerAvailable: true,
}}}}
alerts := evaluateAlerts(metrics, defaultThresholds())
window := MaintenanceWindow{Active: true, VMIDs: []int{105}}
active, planned := splitMaintenanceAlerts(alerts, window)
if len(planned) != 2 || len(active) != 0 {
t.Fatalf("active=%d planned=%d alerts=%#v", len(active), len(planned), alerts)
}
}
func TestAgentDiagnosticsBecomeAlerts(t *testing.T) {
metrics := dashboardMetrics{Agents: []ManagedAgent{{ID: "node", Name: "app", VMID: 105, Online: true, Report: AgentReport{
Services: []AgentService{{Name: "web.service", State: "active", Flapping: true, Restarts: 8, StartedAt: time.Now().Unix()}},
Filesystems: []AgentFilesystem{{Mountpoint: "/data", TotalBytes: 1000, UsedBytes: 950, UsedPercent: 95}},
}}}}
alerts := evaluateAlerts(metrics, defaultThresholds())
wanted := map[string]bool{"agent-flapping-node-web.service-105": false, "agent-filesystem-node-/data-105": false}
for _, alert := range alerts {
if _, ok := wanted[alert.ID]; ok {
wanted[alert.ID] = true
}
}
for id, found := range wanted {
if !found {
t.Fatalf("missing alert %s in %#v", id, alerts)
}
}
}