From 2e62754efcfb36fa998d53dc0d9ae1804e2398f8 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Thu, 5 Feb 2026 11:38:55 +0000 Subject: [PATCH] Extend report engine and cluster client coverage --- .../cluster_client_additional_api5_test.go | 63 +++++++++++++++++ pkg/reporting/engine_additional2_test.go | 67 +++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 pkg/proxmox/cluster_client_additional_api5_test.go create mode 100644 pkg/reporting/engine_additional2_test.go diff --git a/pkg/proxmox/cluster_client_additional_api5_test.go b/pkg/proxmox/cluster_client_additional_api5_test.go new file mode 100644 index 000000000..a85597991 --- /dev/null +++ b/pkg/proxmox/cluster_client_additional_api5_test.go @@ -0,0 +1,63 @@ +package proxmox + +import ( + "context" + "fmt" + "net/http" + "net/http/httptest" + "testing" +) + +func TestClusterClient_GetStorageContentFiltersBackup(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.URL.Path { + case "/api2/json/nodes": + fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`) + case "/api2/json/nodes/node1/storage/local/content": + fmt.Fprint(w, `{"data":[{"volid":"local:backup/ct-100.tar","content":"backup"},{"volid":"local:iso/ubuntu.iso","content":"iso"}]}`) + default: + w.WriteHeader(http.StatusNotFound) + } + })) + defer server.Close() + + cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"} + cc := NewClusterClient("test", cfg, []string{server.URL}, nil) + + content, err := cc.GetStorageContent(context.Background(), "node1", "local") + if err != nil { + t.Fatalf("GetStorageContent failed: %v", err) + } + if len(content) != 1 || content[0].Content != "backup" { + t.Fatalf("unexpected storage content: %+v", content) + } +} + +func TestClusterClient_GetNodePendingUpdates_PermissionDenied(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + if r.URL.Path == "/api2/json/nodes" { + fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`) + return + } + if r.URL.Path == "/api2/json/nodes/node1/apt/update" { + w.WriteHeader(http.StatusForbidden) + fmt.Fprint(w, "permission denied") + return + } + w.WriteHeader(http.StatusNotFound) + })) + defer server.Close() + + cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"} + cc := NewClusterClient("test", cfg, []string{server.URL}, nil) + + updates, err := cc.GetNodePendingUpdates(context.Background(), "node1") + if err != nil { + t.Fatalf("expected permission error to be swallowed, got %v", err) + } + if len(updates) != 0 { + t.Fatalf("expected empty updates on permission error, got %+v", updates) + } +} diff --git a/pkg/reporting/engine_additional2_test.go b/pkg/reporting/engine_additional2_test.go new file mode 100644 index 000000000..c2b69d04f --- /dev/null +++ b/pkg/reporting/engine_additional2_test.go @@ -0,0 +1,67 @@ +package reporting + +import ( + "strings" + "testing" + "time" +) + +func TestReportEngineGenerateMultiMissingStore(t *testing.T) { + engine := NewReportEngine(EngineConfig{}) + + _, _, err := engine.GenerateMulti(MultiReportRequest{ + Resources: []MetricReportRequest{{ResourceType: "node", ResourceID: "node-1"}}, + Start: time.Now().Add(-1 * time.Hour), + End: time.Now(), + Format: FormatCSV, + }) + if err == nil { + t.Fatal("expected error when metrics store is nil") + } + if !strings.Contains(err.Error(), "metrics store not initialized") { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestReportEngineGenerateMultiUnsupportedFormat(t *testing.T) { + store := newTestMetricsStore(t) + defer store.Close() + + engine := NewReportEngine(EngineConfig{MetricsStore: store}) + + _, _, err := engine.GenerateMulti(MultiReportRequest{ + Resources: []MetricReportRequest{{ResourceType: "node", ResourceID: "node-1"}}, + Start: time.Now().Add(-1 * time.Hour), + End: time.Now(), + Format: ReportFormat("xls"), + }) + if err == nil { + t.Fatal("expected unsupported format error") + } + if !strings.Contains(err.Error(), "unsupported format") { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestReportEngineGenerateMultiAllResourcesFail(t *testing.T) { + store := newTestMetricsStore(t) + store.Close() + + engine := NewReportEngine(EngineConfig{MetricsStore: store}) + + _, _, err := engine.GenerateMulti(MultiReportRequest{ + Resources: []MetricReportRequest{ + {ResourceType: "node", ResourceID: "node-1"}, + {ResourceType: "node", ResourceID: "node-2"}, + }, + Start: time.Now().Add(-1 * time.Hour), + End: time.Now(), + Format: FormatCSV, + }) + if err == nil { + t.Fatal("expected error when all resources fail") + } + if !strings.Contains(err.Error(), "all resources failed") { + t.Fatalf("unexpected error: %v", err) + } +}