From 6a072dbae377ca9605c7dc4655c976b46aa519c7 Mon Sep 17 00:00:00 2001 From: sinkingpoint Date: Thu, 27 May 2021 19:04:28 +1000 Subject: [PATCH] Default the isEqual flag to true in alertmanager Solves #2602 - the new version of alertmanager introduces an isEqual flag to support != matchers in alertmanager silences. Clients set this to true in the JSON blob sent to the api to indicate a foo=bar matcher, and to false to indicate foo!=bar. Due to gos unmarshalling, anything that _doesn't_ include this flag will default to false (i.e. a != matcher), so any clients that aren't aware of this flag (such as amtools before negative matchers and the new api) will not send it, and when you think you are making a foo=bar matcher, alertmanager will interpret that as a not equals. This commit changes the Unmarshaling of the v1matcher struct to default the IsEqual flag to true, to keep the old behaviour for clients not setting the flag Signed-off-by: sinkingpoint --- pkg/labels/matcher.go | 5 ++- pkg/labels/matcher_test.go | 62 +++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/pkg/labels/matcher.go b/pkg/labels/matcher.go index 308ed9d4..445c9056 100644 --- a/pkg/labels/matcher.go +++ b/pkg/labels/matcher.go @@ -110,7 +110,10 @@ func (m Matcher) MarshalJSON() ([]byte, error) { } func (m *Matcher) UnmarshalJSON(data []byte) error { - var v1m apiV1Matcher + v1m := apiV1Matcher{ + IsEqual: true, + } + if err := json.Unmarshal(data, &v1m); err != nil { return err } diff --git a/pkg/labels/matcher_test.go b/pkg/labels/matcher_test.go index a645f9d6..bd89a2b7 100644 --- a/pkg/labels/matcher_test.go +++ b/pkg/labels/matcher_test.go @@ -195,7 +195,7 @@ line`, } } -func TestMatcherJSON(t *testing.T) { +func TestMatcherJSONMarshal(t *testing.T) { tests := []struct { name string op MatchType @@ -255,3 +255,63 @@ func TestMatcherJSON(t *testing.T) { } } } + +func TestMatcherJSONUnmarshal(t *testing.T) { + tests := []struct { + name string + op MatchType + value string + want string + }{ + { + name: "foo", + op: MatchEqual, + value: "bar", + want: `{"name":"foo","value":"bar","isRegex":false}`, + }, + { + name: `foo`, + op: MatchEqual, + value: `bar`, + want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":true}`, + }, + { + name: `foo`, + op: MatchNotEqual, + value: `bar`, + want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":false}`, + }, + { + name: `foo`, + op: MatchRegexp, + value: `bar`, + want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":true}`, + }, + { + name: `foo`, + op: MatchNotRegexp, + value: `bar`, + want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":false}`, + }, + } + + cmp := func(m1, m2 Matcher) bool { + return m1.Name == m2.Name && m1.Value == m2.Value && m1.Type == m2.Type + } + + for _, test := range tests { + var m Matcher + if err := json.Unmarshal([]byte(test.want), &m); err != nil { + t.Fatal(err) + } + + m2, err := NewMatcher(test.op, test.name, test.value) + if err != nil { + t.Fatal(err) + } + + if !cmp(m, *m2) { + t.Errorf("Unmarshaling seems to be producing unexpected matchers; got %#v, expected %#v", m, m2) + } + } +}