From d81310dc4b3ed96ca02fd664a8695b0a30b254fd Mon Sep 17 00:00:00 2001 From: Cheese Cake Date: Tue, 7 Apr 2026 17:19:24 +0530 Subject: [PATCH] web/api: remove deprecated DELETE /api/v1/series endpoint (#18083) Signed-off-by: cheese-cakee --- web/api/v1/api.go | 5 -- web/api/v1/api_test.go | 21 ++++++-- web/api/v1/openapi_examples.go | 14 ----- web/api/v1/openapi_paths.go | 7 --- web/api/v1/openapi_schemas.go | 1 - web/api/v1/testdata/openapi_3.1_golden.yaml | 60 --------------------- web/api/v1/testdata/openapi_3.2_golden.yaml | 60 --------------------- web/web_test.go | 2 +- 8 files changed, 18 insertions(+), 152 deletions(-) diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 6e61fd19c6..c236f402d3 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -443,7 +443,6 @@ func (api *API) Register(r *route.Router) { r.Get("/series", wrapAgent(api.series)) r.Post("/series", wrapAgent(api.series)) - r.Del("/series", wrapAgent(api.dropSeries)) r.Get("/scrape_pools", wrap(api.scrapePools)) r.Get("/targets", wrap(api.targets)) @@ -1047,10 +1046,6 @@ func (api *API) series(r *http.Request) (result apiFuncResult) { return apiFuncResult{metrics, nil, warnings, closer} } -func (*API) dropSeries(*http.Request) apiFuncResult { - return apiFuncResult{nil, &apiError{errorInternal, errors.New("not implemented")}, nil, nil} -} - // Target has the information for one target. type Target struct { // Labels before any processing. diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 48fb3b57c1..1a053ddbc7 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -61,6 +61,7 @@ import ( "github.com/prometheus/prometheus/util/stats" "github.com/prometheus/prometheus/util/teststorage" "github.com/prometheus/prometheus/util/testutil" + "github.com/prometheus/prometheus/web/api/testhelpers" ) var testParser = parser.NewParser(parser.Options{}) @@ -1768,10 +1769,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI endpoint: api.series, errType: errorBadData, }, - { - endpoint: api.dropSeries, - errType: errorInternal, - }, { endpoint: api.targets, response: &TargetDiscovery{ @@ -4931,3 +4928,19 @@ func (*fakeQuery) Cancel() {} func (q *fakeQuery) String() string { return q.query } + +// TestDeleteSeriesEndpointRemoved verifies that the deprecated DELETE /api/v1/series +// endpoint is no longer registered and does not return HTTP 500 "not implemented". +func TestDeleteSeriesEndpointRemoved(t *testing.T) { + api := newTestAPI(t, testhelpers.APIConfig{}) + + req := httptest.NewRequest(http.MethodDelete, "/api/v1/series", nil) + recorder := httptest.NewRecorder() + api.Handler.ServeHTTP(recorder, req) + + // The endpoint previously returned HTTP 500 with "not implemented". + // After removal, the router should no longer match DELETE on /series, + // so we must not get the old 500 error. + require.NotEqual(t, http.StatusInternalServerError, recorder.Code, + "DELETE /api/v1/series should no longer return 500; the endpoint has been removed") +} diff --git a/web/api/v1/openapi_examples.go b/web/api/v1/openapi_examples.go index 50e155b184..a1db5d5f3b 100644 --- a/web/api/v1/openapi_examples.go +++ b/web/api/v1/openapi_examples.go @@ -914,20 +914,6 @@ func cleanTombstonesResponseExamples() *orderedmap.Map[string, *base.Example] { return examples } -// seriesDeleteResponseExamples returns examples for DELETE /series response. -func seriesDeleteResponseExamples() *orderedmap.Map[string, *base.Example] { - examples := orderedmap.New[string, *base.Example]() - - examples.Set("seriesDeleted", &base.Example{ - Summary: "Series marked for deletion", - Value: createYAMLNode(map[string]any{ - "status": "success", - }), - }) - - return examples -} - // snapshotResponseExamples returns examples for /admin/tsdb/snapshot response. func snapshotResponseExamples() *orderedmap.Map[string, *base.Example] { examples := orderedmap.New[string, *base.Example]() diff --git a/web/api/v1/openapi_paths.go b/web/api/v1/openapi_paths.go index 2f5ab592f7..b2622f4ff0 100644 --- a/web/api/v1/openapi_paths.go +++ b/web/api/v1/openapi_paths.go @@ -224,13 +224,6 @@ func (*OpenAPIBuilder) seriesPath() *v3.PathItem { RequestBody: formRequestBodyWithExamples("SeriesPostInputBody", seriesPostExamples(), "Submit a series query. This endpoint accepts the same parameters as the GET version."), Responses: responsesWithErrorExamples("SeriesOutputBody", seriesResponseExamples(), errorResponseExamples(), "Series returned matching the provided label matchers via POST.", "Error retrieving series via POST."), }, - Delete: &v3.Operation{ - OperationId: "delete-series", - Summary: "Delete series", - Description: "Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.", - Tags: []string{"series"}, - Responses: responsesWithErrorExamples("SeriesDeleteOutputBody", seriesDeleteResponseExamples(), errorResponseExamples(), "Series marked for deletion.", "Error deleting series."), - }, } } diff --git a/web/api/v1/openapi_schemas.go b/web/api/v1/openapi_schemas.go index de39b43e37..ac298ac0bd 100644 --- a/web/api/v1/openapi_schemas.go +++ b/web/api/v1/openapi_schemas.go @@ -58,7 +58,6 @@ func (b *OpenAPIBuilder) buildComponents() *v3.Components { // Series schemas. schemas.Set("SeriesOutputBody", b.labelsArrayResponseBodySchema()) schemas.Set("SeriesPostInputBody", b.seriesPostInputBodySchema()) - schemas.Set("SeriesDeleteOutputBody", b.simpleResponseBodySchema()) // Metadata schemas. schemas.Set("Metadata", b.metadataSchema()) diff --git a/web/api/v1/testdata/openapi_3.1_golden.yaml b/web/api/v1/testdata/openapi_3.1_golden.yaml index b1514f209d..47f3d06621 100644 --- a/web/api/v1/testdata/openapi_3.1_golden.yaml +++ b/web/api/v1/testdata/openapi_3.1_golden.yaml @@ -1182,37 +1182,6 @@ paths: error: TSDB not ready errorType: internal status: error - delete: - tags: - - series - summary: Delete series - description: 'Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.' - operationId: delete-series - responses: - "200": - description: Series marked for deletion. - content: - application/json: - schema: - $ref: '#/components/schemas/SeriesDeleteOutputBody' - examples: - seriesDeleted: - summary: Series marked for deletion - value: - status: success - default: - description: Error deleting series. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - tsdbNotReady: - summary: TSDB not ready - value: - error: TSDB not ready - errorType: internal - status: error /metadata: get: tags: @@ -3224,35 +3193,6 @@ components: - match[] additionalProperties: false description: POST request body for series query. - SeriesDeleteOutputBody: - type: object - properties: - status: - type: string - enum: - - success - - error - description: Response status. - example: success - data: - description: Response data (structure varies by endpoint). - example: - result: ok - warnings: - type: array - items: - type: string - description: Only set if there were warnings while executing the request. There will still be data in the data field. - infos: - type: array - items: - type: string - description: Only set if there were info-level annotations while executing the request. - required: - - status - - data - additionalProperties: false - description: Generic response body. Metadata: type: object properties: diff --git a/web/api/v1/testdata/openapi_3.2_golden.yaml b/web/api/v1/testdata/openapi_3.2_golden.yaml index fa79fffecc..7766f86f39 100644 --- a/web/api/v1/testdata/openapi_3.2_golden.yaml +++ b/web/api/v1/testdata/openapi_3.2_golden.yaml @@ -1182,37 +1182,6 @@ paths: error: TSDB not ready errorType: internal status: error - delete: - tags: - - series - summary: Delete series - description: 'Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.' - operationId: delete-series - responses: - "200": - description: Series marked for deletion. - content: - application/json: - schema: - $ref: '#/components/schemas/SeriesDeleteOutputBody' - examples: - seriesDeleted: - summary: Series marked for deletion - value: - status: success - default: - description: Error deleting series. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - tsdbNotReady: - summary: TSDB not ready - value: - error: TSDB not ready - errorType: internal - status: error /metadata: get: tags: @@ -3262,35 +3231,6 @@ components: - match[] additionalProperties: false description: POST request body for series query. - SeriesDeleteOutputBody: - type: object - properties: - status: - type: string - enum: - - success - - error - description: Response status. - example: success - data: - description: Response data (structure varies by endpoint). - example: - result: ok - warnings: - type: array - items: - type: string - description: Only set if there were warnings while executing the request. There will still be data in the data field. - infos: - type: array - items: - type: string - description: Only set if there were info-level annotations while executing the request. - required: - - status - - data - additionalProperties: false - description: Generic response body. Metadata: type: object properties: diff --git a/web/web_test.go b/web/web_test.go index ef5e966ed8..bb32d0e649 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -578,7 +578,7 @@ func TestAgentAPIEndPoints(t *testing.T) { for path, methods := range map[string][]string{ "/labels": {http.MethodGet, http.MethodPost}, "/label/:name/values": {http.MethodGet}, - "/series": {http.MethodGet, http.MethodPost, http.MethodDelete}, + "/series": {http.MethodGet, http.MethodPost}, "/alertmanagers": {http.MethodGet}, "/query": {http.MethodGet, http.MethodPost}, "/query_range": {http.MethodGet, http.MethodPost},