feat: implement ControlTower TUI for cluster and host monitoring
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.
This commit is contained in:
47
internal/export/json_test.go
Normal file
47
internal/export/json_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package export
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Note: model.Issue fields are not validated here; this test ensures the writer
|
||||
// creates valid JSON and writes atomically into place.
|
||||
func TestWriteIssues_WritesIndentedJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("get working dir: %v", err)
|
||||
}
|
||||
testDir := filepath.Join(wd, "testdata", t.Name())
|
||||
if err := os.MkdirAll(testDir, 0o755); err != nil {
|
||||
t.Fatalf("create test dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(testDir)
|
||||
outPath := filepath.Join("testdata", t.Name(), "issues.json")
|
||||
|
||||
// Use an empty slice to avoid depending on model.Issue definition.
|
||||
if err := WriteIssues(outPath, nil); err != nil {
|
||||
t.Fatalf("WriteIssues error: %v", err)
|
||||
}
|
||||
|
||||
b, err := os.ReadFile(outPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read file: %v", err)
|
||||
}
|
||||
|
||||
// Ensure valid JSON.
|
||||
var v any
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
t.Fatalf("invalid json: %v\ncontent=%s", err, string(b))
|
||||
}
|
||||
|
||||
// encoding/json.Encoder.Encode adds a trailing newline; and SetIndent should
|
||||
// produce multi-line output for arrays/objects.
|
||||
if len(b) == 0 || b[len(b)-1] != '\n' {
|
||||
t.Fatalf("expected trailing newline")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user