From df9b7491844d454ac025ae1345be9e064cb4160a Mon Sep 17 00:00:00 2001 From: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> Date: Mon, 23 Mar 2026 20:07:36 +0100 Subject: [PATCH] Use 202 Accepted for SetOverrides and buffer GetOverrides response SetOverrides writes to the object storage bucket like the ruler API, so it should return 202 Accepted to indicate the change has been stored Also buffer the GetOverrides JSON response so http.Error works correctly if encoding fails. Signed-off-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> --- docs/guides/overrides.md | 2 +- pkg/overrides/api.go | 12 +++++++++--- pkg/overrides/overrides_test.go | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/guides/overrides.md b/docs/guides/overrides.md index 0c7d78df13..c022a5415d 100644 --- a/docs/guides/overrides.md +++ b/docs/guides/overrides.md @@ -197,7 +197,7 @@ Result: } ``` -**Response (200 OK):** +**Response (202 Accepted):** Returns success with no body. **Response (400 Bad Request):** diff --git a/pkg/overrides/api.go b/pkg/overrides/api.go index bbbea84dd5..2ff3eba890 100644 --- a/pkg/overrides/api.go +++ b/pkg/overrides/api.go @@ -71,12 +71,18 @@ func (a *API) GetOverrides(w http.ResponseWriter, r *http.Request) { http.Error(w, "not found", http.StatusNotFound) return } - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(overrides); err != nil { + + // Buffer the response before writing headers so http.Error works if encoding fails + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(overrides); err != nil { level.Error(a.logger).Log("msg", "failed to encode overrides response", "err", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } + w.Header().Set("Content-Type", "application/json") + if _, err := w.Write(buf.Bytes()); err != nil { + level.Error(a.logger).Log("msg", "failed to write overrides response", "err", err) + } } // SetOverrides updates overrides for a specific tenant @@ -122,7 +128,7 @@ func (a *API) SetOverrides(w http.ResponseWriter, r *http.Request) { return } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusAccepted) } // DeleteOverrides removes tenant-specific overrides diff --git a/pkg/overrides/overrides_test.go b/pkg/overrides/overrides_test.go index 3cc505855c..50421f6a05 100644 --- a/pkg/overrides/overrides_test.go +++ b/pkg/overrides/overrides_test.go @@ -234,7 +234,7 @@ func TestAPIEndpoints(t *testing.T) { path: "/api/v1/user-overrides", tenantID: "user789", requestBody: map[string]any{"ingestion_rate": 5000, "ruler_max_rules_per_rule_group": 10}, - expectedStatus: http.StatusOK, + expectedStatus: http.StatusAccepted, setupMock: func(mock *bucket.ClientMock) { // Mock runtime config with allowed limits runtimeConfig := `overrides: @@ -288,7 +288,7 @@ api_allowed_limits: path: "/api/v1/user-overrides", tenantID: "user888", requestBody: map[string]any{"ingestion_rate": 8000}, // Only update ingestion_rate - expectedStatus: http.StatusOK, + expectedStatus: http.StatusAccepted, setupMock: func(m *bucket.ClientMock) { // Mock runtime config with existing overrides for user888 initialConfig := `overrides: