From 443ea9cbc65b9c1f4e8dd87045af107162f2a085 Mon Sep 17 00:00:00 2001 From: Roman Khavronenko Date: Thu, 16 Apr 2026 15:03:19 +0200 Subject: [PATCH] apptest: add support for specifying HTTP headers (#10830) This change allows specifying headers for provided API calls. This ability is required for proper testing of Tenant-via-Header feature in https://github.com/VictoriaMetrics/VictoriaMetrics/pull/10782 Signed-off-by: hagen1778 --- apptest/client.go | 40 ++++++++++++----------- apptest/model.go | 17 +++++----- apptest/vmagent.go | 6 ++-- apptest/vminsert.go | 42 ++++++++++++++++-------- apptest/vmselect.go | 64 ++++++++++++++++++------------------- apptest/vmsingle.go | 76 +++++++++++++++++++++++++------------------- apptest/vmstorage.go | 10 +++--- 7 files changed, 143 insertions(+), 112 deletions(-) diff --git a/apptest/client.go b/apptest/client.go index 2f1fbd69d0..9cb5c22231 100644 --- a/apptest/client.go +++ b/apptest/client.go @@ -33,37 +33,41 @@ func (c *Client) CloseConnections() { c.httpCli.CloseIdleConnections() } -// Get sends a HTTP GET request, returns +// Get sends an HTTP GET request, returns // the response body and status code to the caller. -func (c *Client) Get(t *testing.T, url string) (string, int) { +func (c *Client) Get(t *testing.T, url string, headers http.Header) (string, int) { t.Helper() - return c.do(t, http.MethodGet, url, "", nil) + return c.do(t, http.MethodGet, url, nil, headers) } -// Post sends a HTTP POST request, returns +// Post sends an HTTP POST request, returns // the response body and status code to the caller. -func (c *Client) Post(t *testing.T, url, contentType string, data []byte) (string, int) { +func (c *Client) Post(t *testing.T, url string, data []byte, headers http.Header) (string, int) { t.Helper() - return c.do(t, http.MethodPost, url, contentType, data) + return c.do(t, http.MethodPost, url, data, headers) } -// PostForm sends a HTTP POST request containing the POST-form data, returns +// PostForm sends an HTTP POST request containing the POST-form data with attached getHeaders, returns // the response body and status code to the caller. -func (c *Client) PostForm(t *testing.T, url string, data url.Values) (string, int) { +func (c *Client) PostForm(t *testing.T, url string, data url.Values, headers http.Header) (string, int) { t.Helper() - return c.Post(t, url, "application/x-www-form-urlencoded", []byte(data.Encode())) + if headers == nil { + headers = make(http.Header) + } + headers.Set("Content-Type", "application/x-www-form-urlencoded") + return c.Post(t, url, []byte(data.Encode()), headers) } -// Delete sends a HTTP DELETE request and returns the response body and status code +// Delete sends an HTTP DELETE request and returns the response body and status code // to the caller. func (c *Client) Delete(t *testing.T, url string) (string, int) { t.Helper() - return c.do(t, http.MethodDelete, url, "", nil) + return c.do(t, http.MethodDelete, url, nil, nil) } -// do prepares a HTTP request, sends it to the server, receives the response +// do prepares an HTTP request, sends it to the server, receives the response // from the server, returns the response body and status code to the caller. -func (c *Client) do(t *testing.T, method, url, contentType string, data []byte) (string, int) { +func (c *Client) do(t *testing.T, method, url string, data []byte, headers http.Header) (string, int) { t.Helper() req, err := http.NewRequest(method, url, bytes.NewReader(data)) @@ -71,9 +75,7 @@ func (c *Client) do(t *testing.T, method, url, contentType string, data []byte) t.Fatalf("could not create a HTTP request: %v", err) } - if len(contentType) > 0 { - req.Header.Add("Content-Type", contentType) - } + req.Header = headers res, err := c.httpCli.Do(req) if err != nil { t.Fatalf("could not send HTTP request: %v", err) @@ -135,7 +137,7 @@ func (app *ServesMetrics) GetIntMetric(t *testing.T, metricName string) int { func (app *ServesMetrics) GetMetric(t *testing.T, metricName string) float64 { t.Helper() - metrics, statusCode := app.cli.Get(t, app.metricsURL) + metrics, statusCode := app.cli.Get(t, app.metricsURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -161,7 +163,7 @@ func (app *ServesMetrics) GetMetricsByPrefix(t *testing.T, prefix string) []floa values := []float64{} - metrics, statusCode := app.cli.Get(t, app.metricsURL) + metrics, statusCode := app.cli.Get(t, app.metricsURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -190,7 +192,7 @@ func (app *ServesMetrics) GetMetricsByRegexp(t *testing.T, re *regexp.Regexp) [] values := []float64{} - metrics, statusCode := app.cli.Get(t, app.metricsURL) + metrics, statusCode := app.cli.Get(t, app.metricsURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } diff --git a/apptest/model.go b/apptest/model.go index d4b554684a..50f47baf01 100644 --- a/apptest/model.go +++ b/apptest/model.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "math" + "net/http" "net/url" "slices" "sort" @@ -89,6 +90,14 @@ type QueryOpts struct { LatencyOffset string Format string NoCache string + Headers http.Header +} + +func (qos *QueryOpts) getHeaders() http.Header { + if qos.Headers == nil { + qos.Headers = make(http.Header) + } + return qos.Headers } func (qos *QueryOpts) asURLValues() url.Values { @@ -118,14 +127,6 @@ func (qos *QueryOpts) asURLValues() url.Values { return uv } -// getTenant returns tenant with optional default value -func (qos *QueryOpts) getTenant() string { - if qos.Tenant == "" { - return "0" - } - return qos.Tenant -} - // PrometheusAPIV1QueryResponse is an inmemory representation of the // /prometheus/api/v1/query or /prometheus/api/v1/query_range response. type PrometheusAPIV1QueryResponse struct { diff --git a/apptest/vmagent.go b/apptest/vmagent.go index 19e859cf99..c3e2607465 100644 --- a/apptest/vmagent.go +++ b/apptest/vmagent.go @@ -76,11 +76,13 @@ func (app *Vmagent) APIV1ImportPrometheus(t *testing.T, records []string, opts Q // Flushing may still be in progress on the function return. // // See https://docs.victoriametrics.com/victoriametrics/url-examples/#apiv1importprometheus -func (app *Vmagent) APIV1ImportPrometheusNoWaitFlush(t *testing.T, records []string, _ QueryOpts) { +func (app *Vmagent) APIV1ImportPrometheusNoWaitFlush(t *testing.T, records []string, opts QueryOpts) { t.Helper() data := []byte(strings.Join(records, "\n")) - _, statusCode := app.cli.Post(t, app.apiV1ImportPrometheusURL, "text/plain", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") + _, statusCode := app.cli.Post(t, app.apiV1ImportPrometheusURL, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } diff --git a/apptest/vminsert.go b/apptest/vminsert.go index 772e97225e..c983bf4b75 100644 --- a/apptest/vminsert.go +++ b/apptest/vminsert.go @@ -106,7 +106,7 @@ func (app *Vminsert) HTTPAddr() string { func (app *Vminsert) InfluxWrite(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/influx/write", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/influx/write", app.httpListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { @@ -114,8 +114,10 @@ func (app *Vminsert) InfluxWrite(t *testing.T, records []string, opts QueryOpts) } data := []byte(strings.Join(records, "\n")) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") app.sendBlocking(t, len(records), func() { - _, statusCode := app.cli.Post(t, url, "text/plain", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -139,15 +141,17 @@ func (app *Vminsert) GraphiteWrite(t *testing.T, records []string, _ QueryOpts) func (app *Vminsert) PrometheusAPIV1ImportCSV(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/csv", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/csv", app.httpListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { url += "?" + uvs } data := []byte(strings.Join(records, "\n")) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") app.sendBlocking(t, len(records), func() { - _, statusCode := app.cli.Post(t, url, "text/plain", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -162,14 +166,16 @@ func (app *Vminsert) PrometheusAPIV1ImportCSV(t *testing.T, records []string, op func (app *Vminsert) PrometheusAPIV1ImportNative(t *testing.T, data []byte, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/native", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/native", app.httpListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { url += "?" + uvs } + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") app.sendBlocking(t, 1, func() { - _, statusCode := app.cli.Post(t, url, "text/plain", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -184,15 +190,17 @@ func (app *Vminsert) PrometheusAPIV1ImportNative(t *testing.T, data []byte, opts func (app *Vminsert) OpenTSDBAPIPut(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/opentsdb/api/put", app.openTSDBListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/opentsdb/api/put", app.openTSDBListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { url += "?" + uvs } data := []byte("[" + strings.Join(records, ",") + "]") + headers := opts.getHeaders() + headers.Set("Content-Type", "application/json") app.sendBlocking(t, len(records), func() { - _, statusCode := app.cli.Post(t, url, "application/json", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -205,14 +213,16 @@ func (app *Vminsert) OpenTSDBAPIPut(t *testing.T, records []string, opts QueryOp func (app *Vminsert) PrometheusAPIV1Write(t *testing.T, wr prompb.WriteRequest, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/write", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/write", app.httpListenAddr, opts.Tenant) data := snappy.Encode(nil, wr.MarshalProtobuf(nil)) recordsCount := len(wr.Timeseries) if prommetadata.IsEnabled() { recordsCount += len(wr.Metadata) } + headers := opts.getHeaders() + headers.Set("Content-Type", "application/x-protobuf") app.sendBlocking(t, recordsCount, func() { - _, statusCode := app.cli.Post(t, url, "application/x-protobuf", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -228,7 +238,7 @@ func (app *Vminsert) PrometheusAPIV1Write(t *testing.T, wr prompb.WriteRequest, func (app *Vminsert) PrometheusAPIV1ImportPrometheus(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/prometheus", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/prometheus/api/v1/import/prometheus", app.httpListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { @@ -261,8 +271,10 @@ func (app *Vminsert) PrometheusAPIV1ImportPrometheus(t *testing.T, records []str if prommetadata.IsEnabled() { recordsCount += metadataRecords } + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") app.sendBlocking(t, recordsCount, func() { - _, statusCode := app.cli.Post(t, url, "text/plain", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -275,15 +287,17 @@ func (app *Vminsert) PrometheusAPIV1ImportPrometheus(t *testing.T, records []str func (app *Vminsert) ZabbixConnectorHistory(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/insert/%s/zabbixconnector/api/v1/history", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/insert/%s/zabbixconnector/api/v1/history", app.httpListenAddr, opts.Tenant) uv := opts.asURLValues() uvs := uv.Encode() if len(uvs) > 0 { url += "?" + uvs } data := []byte(strings.Join(records, "\n")) + headers := opts.getHeaders() + headers.Set("Content-Type", "application/json") app.sendBlocking(t, len(records), func() { - _, statusCode := app.cli.Post(t, url, "application/json", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } diff --git a/apptest/vmselect.go b/apptest/vmselect.go index 652e3a5d8a..86c84c9c59 100644 --- a/apptest/vmselect.go +++ b/apptest/vmselect.go @@ -72,11 +72,11 @@ func (app *Vmselect) HTTPAddr() string { func (app *Vmselect) PrometheusAPIV1Export(t *testing.T, query string, opts QueryOpts) *PrometheusAPIV1QueryResponse { t.Helper() - exportURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/export", app.httpListenAddr, opts.getTenant()) + exportURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/export", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("match[]", query) values.Add("format", "promapi") - res, _ := app.cli.PostForm(t, exportURL, values) + res, _ := app.cli.PostForm(t, exportURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -88,11 +88,11 @@ func (app *Vmselect) PrometheusAPIV1Export(t *testing.T, query string, opts Quer func (app *Vmselect) PrometheusAPIV1ExportNative(t *testing.T, query string, opts QueryOpts) []byte { t.Helper() - exportURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/export/native", app.httpListenAddr, opts.getTenant()) + exportURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/export/native", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("match[]", query) values.Add("format", "promapi") - res, _ := app.cli.PostForm(t, exportURL, values) + res, _ := app.cli.PostForm(t, exportURL, values, opts.Headers) return []byte(res) } @@ -104,11 +104,11 @@ func (app *Vmselect) PrometheusAPIV1ExportNative(t *testing.T, query string, opt func (app *Vmselect) PrometheusAPIV1Query(t *testing.T, query string, opts QueryOpts) *PrometheusAPIV1QueryResponse { t.Helper() - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/query", app.httpListenAddr, opts.getTenant()) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/query", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("query", query) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -120,11 +120,11 @@ func (app *Vmselect) PrometheusAPIV1Query(t *testing.T, query string, opts Query func (app *Vmselect) PrometheusAPIV1QueryRange(t *testing.T, query string, opts QueryOpts) *PrometheusAPIV1QueryResponse { t.Helper() - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/query_range", app.httpListenAddr, opts.getTenant()) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/query_range", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("query", query) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -135,11 +135,11 @@ func (app *Vmselect) PrometheusAPIV1QueryRange(t *testing.T, query string, opts func (app *Vmselect) PrometheusAPIV1Series(t *testing.T, matchQuery string, opts QueryOpts) *PrometheusAPIV1SeriesResponse { t.Helper() - seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/series", app.httpListenAddr, opts.getTenant()) + seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/series", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("match[]", matchQuery) - res, _ := app.cli.PostForm(t, seriesURL, values) + res, _ := app.cli.PostForm(t, seriesURL, values, opts.Headers) return NewPrometheusAPIV1SeriesResponse(t, res) } @@ -150,10 +150,10 @@ func (app *Vmselect) PrometheusAPIV1Series(t *testing.T, matchQuery string, opts func (app *Vmselect) PrometheusAPIV1SeriesCount(t *testing.T, opts QueryOpts) *PrometheusAPIV1SeriesCountResponse { t.Helper() - seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/series/count", app.httpListenAddr, opts.getTenant()) + seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/series/count", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() - res, _ := app.cli.PostForm(t, seriesURL, values) + res, _ := app.cli.PostForm(t, seriesURL, values, opts.Headers) return NewPrometheusAPIV1SeriesCountResponse(t, res) } @@ -167,8 +167,8 @@ func (app *Vmselect) PrometheusAPIV1Labels(t *testing.T, matchQuery string, opts values := opts.asURLValues() values.Add("match[]", matchQuery) - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/labels", app.httpListenAddr, opts.getTenant()) - res, _ := app.cli.PostForm(t, queryURL, values) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/labels", app.httpListenAddr, opts.Tenant) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1LabelsResponse(t, res) } @@ -181,9 +181,9 @@ func (app *Vmselect) PrometheusAPIV1LabelValues(t *testing.T, labelName, matchQu values := opts.asURLValues() values.Add("match[]", matchQuery) - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/label/%s/values", app.httpListenAddr, opts.getTenant(), labelName) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/label/%s/values", app.httpListenAddr, opts.Tenant, labelName) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1LabelValuesResponse(t, res) } @@ -195,9 +195,9 @@ func (app *Vmselect) PrometheusAPIV1Metadata(t *testing.T, metric string, limit values := opts.asURLValues() values.Add("metric", metric) values.Add("limit", strconv.Itoa(limit)) - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/metadata", app.httpListenAddr, opts.getTenant()) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/metadata", app.httpListenAddr, opts.Tenant) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1Metadata(t, res) } @@ -208,11 +208,11 @@ func (app *Vmselect) PrometheusAPIV1Metadata(t *testing.T, metric string, limit func (app *Vmselect) APIV1AdminTSDBDeleteSeries(t *testing.T, matchQuery string, opts QueryOpts) { t.Helper() - queryURL := fmt.Sprintf("http://%s/delete/%s/prometheus/api/v1/admin/tsdb/delete_series", app.httpListenAddr, opts.getTenant()) + queryURL := fmt.Sprintf("http://%s/delete/%s/prometheus/api/v1/admin/tsdb/delete_series", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("match[]", matchQuery) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusNoContent, res) } @@ -229,9 +229,9 @@ func (app *Vmselect) MetricNamesStats(t *testing.T, limit, le, matchPattern stri values.Add("limit", limit) values.Add("le", le) values.Add("match_pattern", matchPattern) - queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/status/metric_names_stats", app.httpListenAddr, opts.getTenant()) + queryURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/status/metric_names_stats", app.httpListenAddr, opts.Tenant) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -251,7 +251,7 @@ func (app *Vmselect) MetricNamesStatsReset(t *testing.T, opts QueryOpts) { values := opts.asURLValues() queryURL := fmt.Sprintf("http://%s/admin/api/v1/admin/status/metric_names_stats/reset", app.httpListenAddr) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusNoContent, res) } @@ -263,7 +263,7 @@ func (app *Vmselect) MetricNamesStatsReset(t *testing.T, opts QueryOpts) { func (app *Vmselect) APIV1StatusTSDB(t *testing.T, matchQuery string, date string, topN string, opts QueryOpts) TSDBStatusResponse { t.Helper() - seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/status/tsdb", app.httpListenAddr, opts.getTenant()) + seriesURL := fmt.Sprintf("http://%s/select/%s/prometheus/api/v1/status/tsdb", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() addNonEmpty := func(name, value string) { if len(value) == 0 { @@ -275,7 +275,7 @@ func (app *Vmselect) APIV1StatusTSDB(t *testing.T, matchQuery string, date strin addNonEmpty("topN", topN) addNonEmpty("date", date) - res, statusCode := app.cli.PostForm(t, seriesURL, values) + res, statusCode := app.cli.PostForm(t, seriesURL, values, opts.Headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -294,8 +294,8 @@ func (app *Vmselect) APIV1StatusTSDB(t *testing.T, matchQuery string, date strin func (app *Vmselect) GraphiteMetricsIndex(t *testing.T, opts QueryOpts) GraphiteMetricsIndexResponse { t.Helper() - seriesURL := fmt.Sprintf("http://%s/select/%s/graphite/metrics/index.json", app.httpListenAddr, opts.getTenant()) - res, statusCode := app.cli.Get(t, seriesURL) + seriesURL := fmt.Sprintf("http://%s/select/%s/graphite/metrics/index.json", app.httpListenAddr, opts.Tenant) + res, statusCode := app.cli.Get(t, seriesURL, opts.Headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -313,11 +313,11 @@ func (app *Vmselect) GraphiteMetricsIndex(t *testing.T, opts QueryOpts) Graphite func (app *Vmselect) GraphiteTagsTagSeries(t *testing.T, record string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/select/%s/graphite/tags/tagSeries", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/select/%s/graphite/tags/tagSeries", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() values.Add("path", record) - _, statusCode := app.cli.PostForm(t, url, values) + _, statusCode := app.cli.PostForm(t, url, values, opts.Headers) if got, want := statusCode, http.StatusNotImplemented; got != want { t.Fatalf("unexpected status code: got %d, want %d", got, want) } @@ -326,13 +326,13 @@ func (app *Vmselect) GraphiteTagsTagSeries(t *testing.T, record string, opts Que func (app *Vmselect) GraphiteTagsTagMultiSeries(t *testing.T, records []string, opts QueryOpts) { t.Helper() - url := fmt.Sprintf("http://%s/select/%s/graphite/tags/tagMultiSeries", app.httpListenAddr, opts.getTenant()) + url := fmt.Sprintf("http://%s/select/%s/graphite/tags/tagMultiSeries", app.httpListenAddr, opts.Tenant) values := opts.asURLValues() for _, rec := range records { values.Add("path", rec) } - _, statusCode := app.cli.PostForm(t, url, values) + _, statusCode := app.cli.PostForm(t, url, values, opts.Headers) if got, want := statusCode, http.StatusNotImplemented; got != want { t.Fatalf("unexpected status code: got %d, want %d", got, want) } @@ -343,7 +343,7 @@ func (app *Vmselect) APIV1AdminTenants(t *testing.T) *AdminTenantsResponse { t.Helper() tenantsURL := fmt.Sprintf("http://%s/admin/tenants", app.httpListenAddr) - res, statusCode := app.cli.Get(t, tenantsURL) + res, statusCode := app.cli.Get(t, tenantsURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } diff --git a/apptest/vmsingle.go b/apptest/vmsingle.go index 38c3ff602c..a59d922d26 100644 --- a/apptest/vmsingle.go +++ b/apptest/vmsingle.go @@ -98,7 +98,7 @@ func StartVmsingleAt(instance, binary string, flags []string, cli *Client, outpu func (app *Vmsingle) ForceFlush(t *testing.T) { t.Helper() - _, statusCode := app.cli.Get(t, app.forceFlushURL) + _, statusCode := app.cli.Get(t, app.forceFlushURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -108,7 +108,7 @@ func (app *Vmsingle) ForceFlush(t *testing.T) { func (app *Vmsingle) ForceMerge(t *testing.T) { t.Helper() - _, statusCode := app.cli.Get(t, app.forceMergeURL) + _, statusCode := app.cli.Get(t, app.forceMergeURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -130,8 +130,9 @@ func (app *Vmsingle) InfluxWrite(t *testing.T, records []string, opts QueryOpts) if len(uvs) > 0 { url += "?" + uvs } - - _, statusCode := app.cli.Post(t, url, "text/plain", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -161,7 +162,9 @@ func (app *Vmsingle) PrometheusAPIV1ImportCSV(t *testing.T, records []string, op url += "?" + uvs } data := []byte(strings.Join(records, "\n")) - _, statusCode := app.cli.Post(t, url, "text/plain", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -181,7 +184,9 @@ func (app *Vmsingle) PrometheusAPIV1ImportNative(t *testing.T, data []byte, opts if len(uvs) > 0 { url += "?" + uvs } - _, statusCode := app.cli.Post(t, url, "text/plain", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -203,7 +208,9 @@ func (app *Vmsingle) OpenTSDBAPIPut(t *testing.T, records []string, opts QueryOp url += "?" + uvs } data := []byte("[" + strings.Join(records, ",") + "]") - _, statusCode := app.cli.Post(t, url, "text/plain", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -212,11 +219,13 @@ func (app *Vmsingle) OpenTSDBAPIPut(t *testing.T, records []string, opts QueryOp // PrometheusAPIV1Write is a test helper function that inserts a // collection of records in Prometheus remote-write format by sending a HTTP // POST request to /prometheus/api/v1/write vmsingle endpoint. -func (app *Vmsingle) PrometheusAPIV1Write(t *testing.T, wr prompb.WriteRequest, _ QueryOpts) { +func (app *Vmsingle) PrometheusAPIV1Write(t *testing.T, wr prompb.WriteRequest, opts QueryOpts) { t.Helper() data := snappy.Encode(nil, wr.MarshalProtobuf(nil)) - _, statusCode := app.cli.Post(t, app.prometheusAPIV1WriteURL, "application/x-protobuf", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "application/x-protobuf") + _, statusCode := app.cli.Post(t, app.prometheusAPIV1WriteURL, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -237,9 +246,10 @@ func (app *Vmsingle) PrometheusAPIV1ImportPrometheus(t *testing.T, records []str if len(uvs) > 0 { url += "?" + uvs } - + headers := opts.getHeaders() + headers.Set("Content-Type", "text/plain") data := []byte(strings.Join(records, "\n")) - _, statusCode := app.cli.Post(t, url, "text/plain", data) + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusNoContent) } @@ -256,7 +266,7 @@ func (app *Vmsingle) PrometheusAPIV1Export(t *testing.T, query string, opts Quer values.Add("match[]", query) values.Add("format", "promapi") - res, _ := app.cli.PostForm(t, app.prometheusAPIV1ExportURL, values) + res, _ := app.cli.PostForm(t, app.prometheusAPIV1ExportURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -273,7 +283,7 @@ func (app *Vmsingle) PrometheusAPIV1ExportNative(t *testing.T, query string, opt values.Add("match[]", query) values.Add("format", "promapi") - res, _ := app.cli.PostForm(t, app.prometheusAPIV1ExportNativeURL, values) + res, _ := app.cli.PostForm(t, app.prometheusAPIV1ExportNativeURL, values, opts.Headers) return []byte(res) } @@ -287,7 +297,7 @@ func (app *Vmsingle) PrometheusAPIV1Query(t *testing.T, query string, opts Query values := opts.asURLValues() values.Add("query", query) - res, _ := app.cli.PostForm(t, app.prometheusAPIV1QueryURL, values) + res, _ := app.cli.PostForm(t, app.prometheusAPIV1QueryURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -302,7 +312,7 @@ func (app *Vmsingle) PrometheusAPIV1QueryRange(t *testing.T, query string, opts values := opts.asURLValues() values.Add("query", query) - res, _ := app.cli.PostForm(t, app.prometheusAPIV1QueryRangeURL, values) + res, _ := app.cli.PostForm(t, app.prometheusAPIV1QueryRangeURL, values, opts.Headers) return NewPrometheusAPIV1QueryResponse(t, res) } @@ -316,7 +326,7 @@ func (app *Vmsingle) PrometheusAPIV1Series(t *testing.T, matchQuery string, opts values := opts.asURLValues() values.Add("match[]", matchQuery) - res, _ := app.cli.PostForm(t, app.prometheusAPIV1SeriesURL, values) + res, _ := app.cli.PostForm(t, app.prometheusAPIV1SeriesURL, values, opts.Headers) return NewPrometheusAPIV1SeriesResponse(t, res) } @@ -330,7 +340,7 @@ func (app *Vmsingle) PrometheusAPIV1SeriesCount(t *testing.T, opts QueryOpts) *P values := opts.asURLValues() queryURL := fmt.Sprintf("http://%s/prometheus/api/v1/series/count", app.httpListenAddr) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1SeriesCountResponse(t, res) } @@ -345,7 +355,7 @@ func (app *Vmsingle) PrometheusAPIV1Labels(t *testing.T, matchQuery string, opts values.Add("match[]", matchQuery) queryURL := fmt.Sprintf("http://%s/prometheus/api/v1/labels", app.httpListenAddr) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1LabelsResponse(t, res) } @@ -360,7 +370,7 @@ func (app *Vmsingle) PrometheusAPIV1LabelValues(t *testing.T, labelName, matchQu values.Add("match[]", matchQuery) queryURL := fmt.Sprintf("http://%s/prometheus/api/v1/label/%s/values", app.httpListenAddr, labelName) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1LabelValuesResponse(t, res) } @@ -374,7 +384,7 @@ func (app *Vmsingle) PrometheusAPIV1Metadata(t *testing.T, metric string, limit values.Add("limit", strconv.Itoa(limit)) queryURL := fmt.Sprintf("http://%s/prometheus/api/v1/metadata", app.httpListenAddr) - res, _ := app.cli.PostForm(t, queryURL, values) + res, _ := app.cli.PostForm(t, queryURL, values, opts.Headers) return NewPrometheusAPIV1Metadata(t, res) } @@ -389,7 +399,7 @@ func (app *Vmsingle) APIV1AdminTSDBDeleteSeries(t *testing.T, matchQuery string, values := opts.asURLValues() values.Add("match[]", matchQuery) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusNoContent, res) } @@ -402,7 +412,7 @@ func (app *Vmsingle) GraphiteMetricsIndex(t *testing.T, _ QueryOpts) GraphiteMet t.Helper() seriesURL := fmt.Sprintf("http://%s/metrics/index.json", app.httpListenAddr) - res, statusCode := app.cli.Get(t, seriesURL) + res, statusCode := app.cli.Get(t, seriesURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -424,7 +434,7 @@ func (app *Vmsingle) GraphiteTagsTagSeries(t *testing.T, record string, opts Que values := opts.asURLValues() values.Add("path", record) - _, statusCode := app.cli.PostForm(t, url, values) + _, statusCode := app.cli.PostForm(t, url, values, opts.Headers) if got, want := statusCode, http.StatusNotImplemented; got != want { t.Fatalf("unexpected status code: got %d, want %d", got, want) } @@ -439,7 +449,7 @@ func (app *Vmsingle) GraphiteTagsTagMultiSeries(t *testing.T, records []string, values.Add("path", rec) } - _, statusCode := app.cli.PostForm(t, url, values) + _, statusCode := app.cli.PostForm(t, url, values, opts.Headers) if got, want := statusCode, http.StatusNotImplemented; got != want { t.Fatalf("unexpected status code: got %d, want %d", got, want) } @@ -458,7 +468,7 @@ func (app *Vmsingle) APIV1StatusMetricNamesStats(t *testing.T, limit, le, matchP values.Add("match_pattern", matchPattern) queryURL := fmt.Sprintf("http://%s/api/v1/status/metric_names_stats", app.httpListenAddr) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -478,7 +488,7 @@ func (app *Vmsingle) APIV1AdminStatusMetricNamesStatsReset(t *testing.T, opts Qu values := opts.asURLValues() queryURL := fmt.Sprintf("http://%s/api/v1/admin/status/metric_names_stats/reset", app.httpListenAddr) - res, statusCode := app.cli.PostForm(t, queryURL, values) + res, statusCode := app.cli.PostForm(t, queryURL, values, opts.Headers) if statusCode != http.StatusNoContent { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusNoContent, res) } @@ -491,7 +501,7 @@ func (app *Vmsingle) APIV1AdminStatusMetricNamesStatsReset(t *testing.T, opts Qu func (app *Vmsingle) SnapshotCreate(t *testing.T) *SnapshotCreateResponse { t.Helper() - data, statusCode := app.cli.Post(t, app.SnapshotCreateURL(), "", nil) + data, statusCode := app.cli.Post(t, app.SnapshotCreateURL(), nil, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -517,7 +527,7 @@ func (app *Vmsingle) APIV1AdminTSDBSnapshot(t *testing.T) *APIV1AdminTSDBSnapsho t.Helper() queryURL := fmt.Sprintf("http://%s/api/v1/admin/tsdb/snapshot", app.httpListenAddr) - data, statusCode := app.cli.Post(t, queryURL, "", nil) + data, statusCode := app.cli.Post(t, queryURL, nil, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -538,7 +548,7 @@ func (app *Vmsingle) SnapshotList(t *testing.T) *SnapshotListResponse { t.Helper() queryURL := fmt.Sprintf("http://%s/snapshot/list", app.httpListenAddr) - data, statusCode := app.cli.Get(t, queryURL) + data, statusCode := app.cli.Get(t, queryURL, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -584,7 +594,7 @@ func (app *Vmsingle) SnapshotDeleteAll(t *testing.T) *SnapshotDeleteAllResponse t.Helper() queryURL := fmt.Sprintf("http://%s/snapshot/delete_all", app.httpListenAddr) - data, statusCode := app.cli.Get(t, queryURL) + data, statusCode := app.cli.Get(t, queryURL, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -615,7 +625,7 @@ func (app *Vmsingle) APIV1StatusTSDB(t *testing.T, matchQuery string, date strin addNonEmpty("topN", topN) addNonEmpty("date", date) - res, statusCode := app.cli.PostForm(t, seriesURL, values) + res, statusCode := app.cli.PostForm(t, seriesURL, values, opts.Headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", statusCode, http.StatusOK, res) } @@ -641,7 +651,9 @@ func (app *Vmsingle) ZabbixConnectorHistory(t *testing.T, records []string, opts url += "?" + uvs } data := []byte(strings.Join(records, "\n")) - _, statusCode := app.cli.Post(t, url, "application/json", data) + headers := opts.getHeaders() + headers.Set("Content-Type", "application/json") + _, statusCode := app.cli.Post(t, url, data, headers) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } diff --git a/apptest/vmstorage.go b/apptest/vmstorage.go index 7436602245..dc68a3ed4e 100644 --- a/apptest/vmstorage.go +++ b/apptest/vmstorage.go @@ -77,7 +77,7 @@ func (app *Vmstorage) ForceFlush(t *testing.T) { t.Helper() forceFlushURL := fmt.Sprintf("http://%s/internal/force_flush", app.httpListenAddr) - _, statusCode := app.cli.Get(t, forceFlushURL) + _, statusCode := app.cli.Get(t, forceFlushURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -88,7 +88,7 @@ func (app *Vmstorage) ForceMerge(t *testing.T) { t.Helper() forceMergeURL := fmt.Sprintf("http://%s/internal/force_merge", app.httpListenAddr) - _, statusCode := app.cli.Get(t, forceMergeURL) + _, statusCode := app.cli.Get(t, forceMergeURL, nil) if statusCode != http.StatusOK { t.Fatalf("unexpected status code: got %d, want %d", statusCode, http.StatusOK) } @@ -101,7 +101,7 @@ func (app *Vmstorage) ForceMerge(t *testing.T) { func (app *Vmstorage) SnapshotCreate(t *testing.T) *SnapshotCreateResponse { t.Helper() - data, statusCode := app.cli.Post(t, app.SnapshotCreateURL(), "", nil) + data, statusCode := app.cli.Post(t, app.SnapshotCreateURL(), nil, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -127,7 +127,7 @@ func (app *Vmstorage) SnapshotList(t *testing.T) *SnapshotListResponse { t.Helper() queryURL := fmt.Sprintf("http://%s/snapshot/list", app.httpListenAddr) - data, statusCode := app.cli.Get(t, queryURL) + data, statusCode := app.cli.Get(t, queryURL, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) } @@ -173,7 +173,7 @@ func (app *Vmstorage) SnapshotDeleteAll(t *testing.T) *SnapshotDeleteAllResponse t.Helper() queryURL := fmt.Sprintf("http://%s/snapshot/delete_all", app.httpListenAddr) - data, statusCode := app.cli.Post(t, queryURL, "", nil) + data, statusCode := app.cli.Post(t, queryURL, nil, nil) if got, want := statusCode, http.StatusOK; got != want { t.Fatalf("unexpected status code: got %d, want %d, resp text=%q", got, want, data) }