Fix silences negative filtering (#1095)

* Fix silence negative filtering

* Refactor extract filtering labels func
This commit is contained in:
Jose Donizetti 2017-11-15 17:29:06 -02:00 committed by stuart nelson
parent e303646b80
commit 10ed60361d
2 changed files with 159 additions and 19 deletions

View File

@ -400,21 +400,11 @@ func receiversMatchFilter(receivers []string, filter *regexp.Regexp) bool {
}
func alertMatchesFilterLabels(a *model.Alert, matchers []*labels.Matcher) bool {
for _, m := range matchers {
v, prs := a.Labels[model.LabelName(m.Name)]
switch m.Type {
case labels.MatchNotEqual, labels.MatchNotRegexp:
if !m.Matches(string(v)) {
return false
}
default:
if !prs || !m.Matches(string(v)) {
return false
}
}
sms := make(map[string]string)
for name, value := range a.Labels {
sms[string(name)] = string(value)
}
return true
return matchFilterLabels(matchers, sms)
}
func (api *API) legacyAddAlerts(w http.ResponseWriter, r *http.Request) {
@ -618,7 +608,7 @@ func (api *API) listSilences(w http.ResponseWriter, r *http.Request) {
return
}
if !matchesFilterLabels(s, matchers) {
if !silenceMatchesFilterLabels(s, matchers) {
continue
}
sils = append(sils, s)
@ -657,14 +647,27 @@ func (api *API) listSilences(w http.ResponseWriter, r *http.Request) {
api.respond(w, silences)
}
func matchesFilterLabels(s *types.Silence, matchers []*labels.Matcher) bool {
sms := map[string]string{}
func silenceMatchesFilterLabels(s *types.Silence, matchers []*labels.Matcher) bool {
sms := make(map[string]string)
for _, m := range s.Matchers {
sms[m.Name] = m.Value
}
return matchFilterLabels(matchers, sms)
}
func matchFilterLabels(matchers []*labels.Matcher, sms map[string]string) bool {
for _, m := range matchers {
if v, prs := sms[m.Name]; !prs || !m.Matches(v) {
return false
v, prs := sms[m.Name]
switch m.Type {
case labels.MatchNotEqual, labels.MatchNotRegexp:
if !m.Matches(string(v)) {
return false
}
default:
if !prs || !m.Matches(string(v)) {
return false
}
}
}

View File

@ -5,6 +5,7 @@ import (
"regexp"
"testing"
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/stretchr/testify/require"
@ -90,6 +91,134 @@ func TestAlertFiltering(t *testing.T) {
}
}
func TestSilenceFiltering(t *testing.T) {
type test struct {
silence *types.Silence
msg string
expected bool
}
// Equal
equal, err := labels.NewMatcher(labels.MatchEqual, "label1", "test1")
if err != nil {
t.Error("Unexpected error %v", err)
}
tests := []test{
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
"label1=test1",
true,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
"label1=test2",
false,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
"label2=test2",
false,
},
}
for _, test := range tests {
actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{equal})
msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
require.Equal(t, test.expected, actual, msg)
}
// Not Equal
notEqual, err := labels.NewMatcher(labels.MatchNotEqual, "label1", "test1")
if err != nil {
t.Error("Unexpected error %v", err)
}
tests = []test{
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
"label1!=test1",
false,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
"label1!=test2",
true,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
"label2!=test2",
true,
},
}
for _, test := range tests {
actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{notEqual})
msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
require.Equal(t, test.expected, actual, msg)
}
// Regexp Equal
regexpEqual, err := labels.NewMatcher(labels.MatchRegexp, "label1", "tes.*")
if err != nil {
t.Error("Unexpected error %v", err)
}
tests = []test{
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
"label1=~test1",
true,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
"label1=~test2",
true,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
"label2=~test2",
false,
},
}
for _, test := range tests {
actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{regexpEqual})
msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
require.Equal(t, test.expected, actual, msg)
}
// Regexp Not Equal
regexpNotEqual, err := labels.NewMatcher(labels.MatchNotRegexp, "label1", "tes.*")
if err != nil {
t.Error("Unexpected error %v", err)
}
tests = []test{
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
"label1!~test1",
false,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
"label1!~test2",
false,
},
{
&types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
"label2!~test2",
true,
},
}
for _, test := range tests {
actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{regexpNotEqual})
msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
require.Equal(t, test.expected, actual, msg)
}
}
func TestReceiversMatchFilter(t *testing.T) {
receivers := []string{"pagerduty", "slack", "hipchat"}
@ -105,3 +234,11 @@ func TestReceiversMatchFilter(t *testing.T) {
}
require.False(t, receiversMatchFilter(receivers, filter))
}
func newMatcher(labelSet model.LabelSet) types.Matchers {
matchers := make([]*types.Matcher, 0, len(labelSet))
for key, val := range labelSet {
matchers = append(matchers, types.NewMatcher(key, string(val)))
}
return matchers
}