Add complete TUI application for monitoring Kubernetes clusters and host systems. Features include: Core features: - Collector framework with concurrent scheduling - Host collectors: disk, memory, load, network - Kubernetes collectors: pods, nodes, workloads, events with informers - Issue deduplication, state management, and resolve-after logic - Bubble Tea TUI with table view, details pane, and filtering - JSON export functionality UX improvements: - Help overlay with keybindings - Priority/category filters with visual indicators - Direct priority jump (0/1/2/3) - Bulk acknowledge (Shift+A) - Clipboard copy (y) - Theme toggle (T) - Age format toggle (d) - Wide title toggle (t) - Vi-style navigation (j/k) - Home/End jump (g/G) - Rollup drill-down in details Robustness: - Grace period for unreachable clusters - Rollups for high-volume issues - Flap suppression - RBAC error handling Files: All core application code with tests for host collectors, engine, store, model, and export packages.
81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
package host
|
|
|
|
import (
|
|
"syscall"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseProcMounts_UnescapesAndParses(t *testing.T) {
|
|
in := "dev1 / ext4 rw 0 0\n" +
|
|
"dev2 /path\\040with\\040space xfs rw 0 0\n" +
|
|
"badline\n"
|
|
|
|
ms := parseProcMounts(in)
|
|
if len(ms) != 2 {
|
|
t.Fatalf("expected 2 mounts, got %d", len(ms))
|
|
}
|
|
if ms[0].MountPoint != "/" || ms[0].FSType != "ext4" {
|
|
t.Fatalf("unexpected first mount: %+v", ms[0])
|
|
}
|
|
if ms[1].MountPoint != "/path with space" {
|
|
t.Fatalf("expected unescaped mountpoint, got %q", ms[1].MountPoint)
|
|
}
|
|
}
|
|
|
|
func TestShouldSkipMount_FiltersPseudo(t *testing.T) {
|
|
cases := []procMount{
|
|
{MountPoint: "/proc", FSType: "proc"},
|
|
{MountPoint: "/sys", FSType: "sysfs"},
|
|
{MountPoint: "/dev", FSType: "tmpfs"},
|
|
{MountPoint: "/dev/shm", FSType: "tmpfs"},
|
|
}
|
|
for _, c := range cases {
|
|
if !shouldSkipMount(c) {
|
|
t.Fatalf("expected skip for %+v", c)
|
|
}
|
|
}
|
|
if shouldSkipMount(procMount{MountPoint: "/home", FSType: "ext4"}) {
|
|
t.Fatalf("did not expect skip for /home ext4")
|
|
}
|
|
}
|
|
|
|
func TestDiskPriority(t *testing.T) {
|
|
if p, ok := diskPriority(91.9, -1); ok {
|
|
t.Fatalf("expected no issue, got %v", p)
|
|
}
|
|
if p, ok := diskPriority(92.0, -1); !ok || p != "P1" {
|
|
t.Fatalf("expected P1 at 92%%, got %v ok=%v", p, ok)
|
|
}
|
|
if p, ok := diskPriority(97.9, 98.0); !ok || p != "P0" {
|
|
t.Fatalf("expected P0 if either crosses 98%%, got %v ok=%v", p, ok)
|
|
}
|
|
}
|
|
|
|
func TestStatfsCalculations(t *testing.T) {
|
|
st := syscall.Statfs_t{}
|
|
st.Bsize = 1
|
|
st.Blocks = 100
|
|
st.Bfree = 8
|
|
st.Bavail = 8
|
|
|
|
pct, free := statfsBlockUsedPct(st)
|
|
if free != 8 {
|
|
t.Fatalf("expected free=8 bytes, got %d", free)
|
|
}
|
|
if pct < 91.9 || pct > 92.1 {
|
|
t.Fatalf("expected ~92%% used, got %f", pct)
|
|
}
|
|
|
|
st.Files = 100
|
|
st.Ffree = 2
|
|
ipct := statfsInodeUsedPct(st)
|
|
if ipct < 97.9 || ipct > 98.1 {
|
|
t.Fatalf("expected ~98%% inode used, got %f", ipct)
|
|
}
|
|
|
|
st.Files = 0
|
|
if statfsInodeUsedPct(st) != -1 {
|
|
t.Fatalf("expected -1 when inode info unavailable")
|
|
}
|
|
}
|