From 033e1ac3d251917f7c375a726e33c53cab757a30 Mon Sep 17 00:00:00 2001 From: Roman Khavronenko Date: Thu, 25 May 2023 17:56:54 +0300 Subject: [PATCH] vmalert: do not return nil `rules` for /api/v1/rules (#4344) The fix addresses a case when vmalert is configured with a group which has `name`, but doesn't have `rules` configured. In this case it still returns a `nil` instead of `[]` slice. Fixing this via current commit. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4221 Signed-off-by: hagen1778 (cherry picked from commit 66ed6fe62f219cc5c5a142355bde80a05dec5c83) --- app/vmalert/manager.go | 1 + app/vmalert/web_test.go | 30 ++++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/app/vmalert/manager.go b/app/vmalert/manager.go index fa04f778a..25fdfbe92 100644 --- a/app/vmalert/manager.go +++ b/app/vmalert/manager.go @@ -188,6 +188,7 @@ func (g *Group) toAPI() APIGroup { Labels: g.Labels, } + ag.Rules = make([]APIRule, 0) for _, r := range g.Rules { ag.Rules = append(ag.Rules, r.ToAPI()) } diff --git a/app/vmalert/web_test.go b/app/vmalert/web_test.go index 3a70f6fef..a036a586f 100644 --- a/app/vmalert/web_test.go +++ b/app/vmalert/web_test.go @@ -165,8 +165,8 @@ func TestHandler(t *testing.T) { } 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) })) + rhWithNoGroups := &requestHandler{m: &manager{groups: make(map[uint64]*Group)}} + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { rhWithNoGroups.handler(w, r) })) defer ts.Close() getResp := func(url string, to interface{}, code int) { @@ -190,7 +190,7 @@ func TestEmptyResponse(t *testing.T) { } } - t.Run("/api/v1/alerts", func(t *testing.T) { + t.Run("no groups /api/v1/alerts", func(t *testing.T) { lr := listAlertsResponse{} getResp(ts.URL+"/api/v1/alerts", &lr, 200) if lr.Data.Alerts == nil { @@ -204,7 +204,7 @@ func TestEmptyResponse(t *testing.T) { } }) - t.Run("/api/v1/rules", func(t *testing.T) { + t.Run("no groups /api/v1/rules", func(t *testing.T) { lr := listGroupsResponse{} getResp(ts.URL+"/api/v1/rules", &lr, 200) if lr.Data.Groups == nil { @@ -217,4 +217,26 @@ func TestEmptyResponse(t *testing.T) { t.Errorf("expected /api/v1/rules response to have non-nil data") } }) + + rhWithEmptyGroup := &requestHandler{m: &manager{groups: map[uint64]*Group{0: {Name: "test"}}}} + ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { rhWithEmptyGroup.handler(w, r) }) + + t.Run("empty group /api/v1/rules", func(t *testing.T) { + lr := listGroupsResponse{} + getResp(ts.URL+"/api/v1/rules", &lr, 200) + if lr.Data.Groups == nil { + t.Fatalf("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.Fatalf("expected /api/v1/rules response to have non-nil data") + } + + group := lr.Data.Groups[0] + if group.Rules == nil { + t.Fatalf("expected /api/v1/rules response to have non-nil rules for group") + } + }) }