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 <colin@quirl.co.nz>
This commit is contained in:
sinkingpoint 2021-05-27 19:04:28 +10:00
parent 5ad7a105d7
commit 6a072dbae3
2 changed files with 65 additions and 2 deletions

View File

@ -110,7 +110,10 @@ func (m Matcher) MarshalJSON() ([]byte, error) {
} }
func (m *Matcher) UnmarshalJSON(data []byte) error { func (m *Matcher) UnmarshalJSON(data []byte) error {
var v1m apiV1Matcher v1m := apiV1Matcher{
IsEqual: true,
}
if err := json.Unmarshal(data, &v1m); err != nil { if err := json.Unmarshal(data, &v1m); err != nil {
return err return err
} }

View File

@ -195,7 +195,7 @@ line`,
} }
} }
func TestMatcherJSON(t *testing.T) { func TestMatcherJSONMarshal(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
op MatchType 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)
}
}
}