mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
273 lines
6.6 KiB
Go
273 lines
6.6 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/agentbinaries"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/alerts"
|
|
)
|
|
|
|
func TestExtractBearerToken(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
header string
|
|
want string
|
|
}{
|
|
{
|
|
name: "empty",
|
|
header: "",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "basic auth",
|
|
header: "Basic abc123",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "bearer lower",
|
|
header: "bearer token-123",
|
|
want: "token-123",
|
|
},
|
|
{
|
|
name: "bearer upper",
|
|
header: "Bearer token-456",
|
|
want: "token-456",
|
|
},
|
|
{
|
|
name: "bearer extra whitespace",
|
|
header: " Bearer token-789 ",
|
|
want: "token-789",
|
|
},
|
|
{
|
|
name: "short header",
|
|
header: "bearer",
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := extractBearerToken(tt.header); got != tt.want {
|
|
t.Fatalf("extractBearerToken(%q) = %q, want %q", tt.header, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractSetupToken(t *testing.T) {
|
|
t.Run("prefers header token", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/setup?auth_token=query-token", nil)
|
|
req.Header.Set("X-Setup-Token", " header-token ")
|
|
req.Header.Set("Authorization", "Bearer auth-token")
|
|
|
|
if got := extractSetupToken(req); got != "header-token" {
|
|
t.Fatalf("expected header token, got %q", got)
|
|
}
|
|
})
|
|
|
|
t.Run("falls back to bearer", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/setup?auth_token=query-token", nil)
|
|
req.Header.Set("X-Setup-Token", " ")
|
|
req.Header.Set("Authorization", "Bearer auth-token")
|
|
|
|
if got := extractSetupToken(req); got != "auth-token" {
|
|
t.Fatalf("expected bearer token, got %q", got)
|
|
}
|
|
})
|
|
|
|
t.Run("falls back to query", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/setup?auth_token=query-token", nil)
|
|
|
|
if got := extractSetupToken(req); got != "query-token" {
|
|
t.Fatalf("expected query token, got %q", got)
|
|
}
|
|
})
|
|
|
|
t.Run("returns empty when missing", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/setup", nil)
|
|
if got := extractSetupToken(req); got != "" {
|
|
t.Fatalf("expected empty token, got %q", got)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestDedupeStrings(t *testing.T) {
|
|
input := []string{"alpha", "beta", "alpha", "", "gamma", "beta", " "}
|
|
want := []string{"alpha", "beta", "gamma", " "}
|
|
|
|
if got := dedupeStrings(input); !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("dedupeStrings() = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSortedHostAgentKeys(t *testing.T) {
|
|
if got := sortedHostAgentKeys(nil); got != nil {
|
|
t.Fatalf("expected nil result for nil map, got %v", got)
|
|
}
|
|
|
|
missing := map[string]agentbinaries.HostAgentBinary{
|
|
"zeta": {},
|
|
"alpha": {},
|
|
"beta": {},
|
|
}
|
|
|
|
want := []string{"alpha", "beta", "zeta"}
|
|
if got := sortedHostAgentKeys(missing); !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("sortedHostAgentKeys() = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestFileExists(t *testing.T) {
|
|
dir := t.TempDir()
|
|
filePath := filepath.Join(dir, "exists.txt")
|
|
if err := os.WriteFile(filePath, []byte("data"), 0o644); err != nil {
|
|
t.Fatalf("write temp file: %v", err)
|
|
}
|
|
|
|
if !fileExists(filePath) {
|
|
t.Fatalf("expected fileExists true for %s", filePath)
|
|
}
|
|
if fileExists(filepath.Join(dir, "missing.txt")) {
|
|
t.Fatalf("expected fileExists false for missing file")
|
|
}
|
|
}
|
|
|
|
func TestCachedSHA256(t *testing.T) {
|
|
router := &Router{}
|
|
if _, err := router.cachedSHA256("", nil); err == nil {
|
|
t.Fatalf("expected error for empty file path")
|
|
}
|
|
|
|
dir := t.TempDir()
|
|
filePath := filepath.Join(dir, "checksum.txt")
|
|
payload := []byte("checksum-data")
|
|
if err := os.WriteFile(filePath, payload, 0o644); err != nil {
|
|
t.Fatalf("write temp file: %v", err)
|
|
}
|
|
|
|
wantHash := sha256.Sum256(payload)
|
|
want := hex.EncodeToString(wantHash[:])
|
|
|
|
sum, err := router.cachedSHA256(filePath, nil)
|
|
if err != nil {
|
|
t.Fatalf("cachedSHA256 error: %v", err)
|
|
}
|
|
if sum != want {
|
|
t.Fatalf("cachedSHA256 = %q, want %q", sum, want)
|
|
}
|
|
|
|
info, err := os.Stat(filePath)
|
|
if err != nil {
|
|
t.Fatalf("stat file: %v", err)
|
|
}
|
|
|
|
sum, err = router.cachedSHA256(filePath, info)
|
|
if err != nil {
|
|
t.Fatalf("cachedSHA256 second call: %v", err)
|
|
}
|
|
if sum != want {
|
|
t.Fatalf("cachedSHA256 cached = %q, want %q", sum, want)
|
|
}
|
|
}
|
|
|
|
func TestServeChecksum(t *testing.T) {
|
|
dir := t.TempDir()
|
|
filePath := filepath.Join(dir, "checksum.txt")
|
|
payload := []byte("checksum-body")
|
|
if err := os.WriteFile(filePath, payload, 0o644); err != nil {
|
|
t.Fatalf("write temp file: %v", err)
|
|
}
|
|
|
|
wantHash := sha256.Sum256(payload)
|
|
want := hex.EncodeToString(wantHash[:])
|
|
|
|
router := &Router{}
|
|
rec := httptest.NewRecorder()
|
|
router.serveChecksum(rec, filePath)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("expected status %d, got %d", http.StatusOK, rec.Code)
|
|
}
|
|
if ct := rec.Header().Get("Content-Type"); ct != "text/plain" {
|
|
t.Fatalf("expected text/plain, got %q", ct)
|
|
}
|
|
if got := strings.TrimSpace(rec.Body.String()); got != want {
|
|
t.Fatalf("checksum body %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestDeriveResourceTypeFromAlert(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
alert *alerts.Alert
|
|
want string
|
|
}{
|
|
{
|
|
name: "nil alert",
|
|
alert: nil,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "node alert",
|
|
alert: &alerts.Alert{Type: "NodeDown", ResourceID: "node-1"},
|
|
want: "node",
|
|
},
|
|
{
|
|
name: "qemu alert",
|
|
alert: &alerts.Alert{Type: "qemu_cpu", ResourceID: "cluster/qemu/100"},
|
|
want: "vm",
|
|
},
|
|
{
|
|
name: "lxc alert",
|
|
alert: &alerts.Alert{Type: "lxc_disk", ResourceID: "cluster/lxc/200"},
|
|
want: "container",
|
|
},
|
|
{
|
|
name: "docker alert",
|
|
alert: &alerts.Alert{Type: "docker_health", ResourceID: "docker-1"},
|
|
want: "docker",
|
|
},
|
|
{
|
|
name: "storage alert",
|
|
alert: &alerts.Alert{Type: "storage_high", ResourceID: "storage-1"},
|
|
want: "storage",
|
|
},
|
|
{
|
|
name: "pbs alert",
|
|
alert: &alerts.Alert{Type: "pbs_backup", ResourceID: "pbs-1"},
|
|
want: "pbs",
|
|
},
|
|
{
|
|
name: "kubernetes alert",
|
|
alert: &alerts.Alert{Type: "kubernetes", ResourceID: "k8s-1"},
|
|
want: "kubernetes",
|
|
},
|
|
{
|
|
name: "fallback by resource id",
|
|
alert: &alerts.Alert{Type: "custom", ResourceID: "cluster/qemu/101"},
|
|
want: "vm",
|
|
},
|
|
{
|
|
name: "fallback default",
|
|
alert: &alerts.Alert{Type: "custom", ResourceID: "guest-1"},
|
|
want: "guest",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := deriveResourceTypeFromAlert(tt.alert); got != tt.want {
|
|
t.Fatalf("deriveResourceTypeFromAlert() = %q, want %q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|