diff --git a/app/vmalert/web.go b/app/vmalert/web.go index 668a758b0c..a9d48a92df 100644 --- a/app/vmalert/web.go +++ b/app/vmalert/web.go @@ -211,7 +211,7 @@ func (rh *requestHandler) groups() []APIGroup { rh.m.groupsMu.RLock() defer rh.m.groupsMu.RUnlock() - var groups []APIGroup + groups := make([]APIGroup, 0) for _, g := range rh.m.groups { groups = append(groups, g.toAPI()) } @@ -276,6 +276,7 @@ func (rh *requestHandler) listAlerts() ([]byte, error) { defer rh.m.groupsMu.RUnlock() lr := listAlertsResponse{Status: "success"} + lr.Data.Alerts = make([]*APIAlert, 0) for _, g := range rh.m.groups { for _, r := range g.Rules { a, ok := r.(*AlertingRule) diff --git a/app/vmalert/web_test.go b/app/vmalert/web_test.go index 5648087c69..5b83a58f03 100644 --- a/app/vmalert/web_test.go +++ b/app/vmalert/web_test.go @@ -144,5 +144,59 @@ func TestHandler(t *testing.T) { t.Run("/api/v1/1/0/status", func(t *testing.T) { getResp(ts.URL+"/api/v1/1/0/status", nil, 404) }) - +} + +func TestEmptyResponse(t *testing.T) { + rh := &requestHandler{m: &manager{groups: make(map[uint64]*Group)}} + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { rh.handler(w, r) })) + defer ts.Close() + + getResp := func(url string, to interface{}, code int) { + t.Helper() + resp, err := http.Get(url) + if err != nil { + t.Fatalf("unexpected err %s", err) + } + if code != resp.StatusCode { + t.Errorf("unexpected status code %d want %d", resp.StatusCode, code) + } + defer func() { + if err := resp.Body.Close(); err != nil { + t.Errorf("err closing body %s", err) + } + }() + if to != nil { + if err = json.NewDecoder(resp.Body).Decode(to); err != nil { + t.Errorf("unexpected err %s", err) + } + } + } + + t.Run("/api/v1/alerts", func(t *testing.T) { + lr := listAlertsResponse{} + getResp(ts.URL+"/api/v1/alerts", &lr, 200) + if lr.Data.Alerts == nil { + t.Errorf("expected /api/v1/alerts response to have non-nil data") + } + + lr = listAlertsResponse{} + getResp(ts.URL+"/vmalert/api/v1/alerts", &lr, 200) + if lr.Data.Alerts == nil { + t.Errorf("expected /api/v1/alerts response to have non-nil data") + } + }) + + t.Run("/api/v1/rules", func(t *testing.T) { + lr := listGroupsResponse{} + getResp(ts.URL+"/api/v1/rules", &lr, 200) + if lr.Data.Groups == nil { + t.Errorf("expected /api/v1/rules response to have non-nil data") + } + + lr = listGroupsResponse{} + getResp(ts.URL+"/vmalert/api/v1/rules", &lr, 200) + if lr.Data.Groups == nil { + t.Errorf("expected /api/v1/rules response to have non-nil data") + } + }) } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5c54321330..4f320af788 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -21,6 +21,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): fix a panic when the duration in the query contains uppercase `M` suffix. Such a suffix isn't allowed to use in durations, since it clashes with `a million` suffix, e.g. it isn't clear whether `rate(metric[5M])` means rate over 5 minutes, 5 months or 5 million seconds. See [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3589) and [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4120) issues. * BUGFIX: [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): prevent from possible panic when the number of vmstorage nodes increases when [automatic vmstorage discovery](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery) is enabled. * BUGFIX: properly limit the number of [OpenTSDB HTTP](https://docs.victoriametrics.com/#sending-opentsdb-data-via-http-apiput-requests) concurrent requests specified via `-maxConcurrentInserts` command-line flag. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4204). Thanks to @zouxiang1993 for [the fix](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4208). +* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): properly return empty slices instead of nil for `/api/v1/rules` and `/api/v1/alerts` API handlers. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4221). * BUGFIX: [stream aggregation](https://docs.victoriametrics.com/stream-aggregation.html): suppress `series after dedup` error message in logs when `-remoteWrite.streamAggr.dedupInterval` command-line flag is set at [vmagent](https://docs.victoriametrics.com/vmgent.html) or when `-streamAggr.dedupInterval` command-line flag is set at [single-node VictoriaMetrics](https://docs.victoriametrics.com/). ## [v1.87.5](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.87.5)