diff --git a/docs/release-control/v6/internal/subsystems/monitoring.md b/docs/release-control/v6/internal/subsystems/monitoring.md index b6d5ff16cd..28d198cc51 100644 --- a/docs/release-control/v6/internal/subsystems/monitoring.md +++ b/docs/release-control/v6/internal/subsystems/monitoring.md @@ -323,7 +323,9 @@ Verification: `internal/truenas/core_reporting_test.go` and its anonymised `testdata/core13_reporting.json` cover five source-bound native excerpts, row/timing/alias/zero/null/empty/finite controls, device totals, stale buckets, ARC alignment, current and canonical History projections, request validation, -catalogue limits and failure boundaries. The excerpt windows are deliberately +catalogue limits and failure boundaries. Unique overflow is rejected rather than +truncated, while duplicate identifiers consume only one selection entry. The +excerpt windows are deliberately shortened controls, not complete native windows. Extended `TestTrueNASPartialReportingPipeline` in `internal/monitoring/truenas_poller_test.go` crosses pinned-certificate HTTP, diff --git a/internal/truenas/client.go b/internal/truenas/client.go index 769c78e744..3c932617b1 100644 --- a/internal/truenas/client.go +++ b/internal/truenas/client.go @@ -426,7 +426,8 @@ func legacyRESTReportingGraphs() []map[string]any { // getLegacySystemReportingData keeps a rejected optional graph from discarding // usable CPU/memory readings. Keep the successful batch fast path; only split // graph-validation/server errors, never authentication, rate-limit, endpoint, -// transport or cancellation failures. The query and graph set remain unchanged. +// transport or cancellation failures. Bind the catalogue-selected graph set once +// for both the batch and split; the requested query window remains unchanged. func (c *Client) getLegacySystemReportingData(ctx context.Context, query map[string]any) ([]trueNASReportingGetDataResponse, error) { graphs, err := c.legacyReportingGraphs(ctx) if err != nil { diff --git a/internal/truenas/core_reporting_test.go b/internal/truenas/core_reporting_test.go index 07ee611c7e..f9cc2f5864 100644 --- a/internal/truenas/core_reporting_test.go +++ b/internal/truenas/core_reporting_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "fmt" "math" "net/http" "os" @@ -378,6 +379,22 @@ func TestCORE13CatalogueAndResponseSafety(t *testing.T) { client.Close() } +func TestCORE13CatalogueRejectsUniqueOverflow(t *testing.T) { + identifiers := make([]string, 253) + for i := range identifiers { + identifiers[i] = fmt.Sprintf("disk-%d", i) + } + raw, err := json.Marshal([]map[string]any{{"name": "disk", "identifiers": identifiers}}) + if err != nil { + t.Fatal(err) + } + client := newLegacyRESTReportingClient(t, alertArgsTransport{"/api/v2.0/reporting/graphs": {body: string(raw)}}) + defer client.Close() + if graphs, err := client.legacyReportingGraphs(context.Background()); err == nil || graphs != nil { + t.Fatal("oversized unique catalogue became a partial host total") + } +} + func TestCORE13ARCAlignedWithFreeMemory(t *testing.T) { replies := core13ReportingFixture(t) history := parseSystemMetricHistory(replies)