mirror of
https://github.com/prometheus/alertmanager
synced 2025-04-11 03:31:55 +00:00
Check silence matching with Protobuf models
Signed-off-by: Koki Kato <koki.kato1994@gmail.com> To support negative matchers.
This commit is contained in:
parent
72ce7fd71f
commit
b9aae07a73
@ -584,14 +584,14 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew
|
|||||||
|
|
||||||
sils := open_api_models.GettableSilences{}
|
sils := open_api_models.GettableSilences{}
|
||||||
for _, ps := range psils {
|
for _, ps := range psils {
|
||||||
|
if !checkSilenceMatchesFilterLabels(ps, matchers) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
silence, err := gettableSilenceFromProto(ps)
|
silence, err := gettableSilenceFromProto(ps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
level.Error(logger).Log("msg", "Failed to unmarshal silence from proto", "err", err)
|
level.Error(logger).Log("msg", "Failed to unmarshal silence from proto", "err", err)
|
||||||
return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error())
|
return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error())
|
||||||
}
|
}
|
||||||
if !gettableSilenceMatchesFilterLabels(silence, matchers) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sils = append(sils, &silence)
|
sils = append(sils, &silence)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,18 +638,21 @@ func sortSilences(sils open_api_models.GettableSilences) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// gettableSilenceMatchesFilterLabels returns true if
|
// checkSilenceMatchesFilterLabels returns true if
|
||||||
// a given silence matches a list of matchers.
|
// a given silence matches a list of matchers.
|
||||||
// A silence matches a filter (list of matchers) if
|
// A silence matches a filter (list of matchers) if
|
||||||
// for all matchers in the filter, there exists a matcher in the silence
|
// for all matchers in the filter, there exists a matcher in the silence
|
||||||
// such that their names, types, and values are equivalent.
|
// such that their names, types, and values are equivalent.
|
||||||
func gettableSilenceMatchesFilterLabels(s open_api_models.GettableSilence, matchers []*labels.Matcher) bool {
|
func checkSilenceMatchesFilterLabels(s *silencepb.Silence, matchers []*labels.Matcher) bool {
|
||||||
for _, matcher := range matchers {
|
for _, matcher := range matchers {
|
||||||
found := false
|
found := false
|
||||||
for _, m := range s.Matchers {
|
for _, m := range s.Matchers {
|
||||||
if matcher.Name == *m.Name &&
|
if matcher.Name == m.Name &&
|
||||||
(matcher.Type == labels.MatchEqual && !*m.IsRegex || matcher.Type == labels.MatchRegexp && *m.IsRegex) &&
|
(matcher.Type == labels.MatchEqual && m.Type == silencepb.Matcher_EQUAL ||
|
||||||
matcher.Value == *m.Value {
|
matcher.Type == labels.MatchRegexp && m.Type == silencepb.Matcher_REGEXP ||
|
||||||
|
matcher.Type == labels.MatchNotEqual && m.Type == silencepb.Matcher_NOT_EQUAL ||
|
||||||
|
matcher.Type == labels.MatchNotRegexp && m.Type == silencepb.Matcher_NOT_REGEXP) &&
|
||||||
|
matcher.Value == m.Pattern {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
general_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/general"
|
general_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/general"
|
||||||
"github.com/prometheus/alertmanager/config"
|
"github.com/prometheus/alertmanager/config"
|
||||||
"github.com/prometheus/alertmanager/pkg/labels"
|
"github.com/prometheus/alertmanager/pkg/labels"
|
||||||
|
"github.com/prometheus/alertmanager/silence/silencepb"
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -130,11 +131,11 @@ func TestGetSilencesHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createModelMatcher(name string, value string, isRegex bool) *open_api_models.Matcher {
|
func createSilenceMatcher(name string, pattern string, matcherType silencepb.Matcher_Type) *silencepb.Matcher {
|
||||||
return &open_api_models.Matcher{
|
return &silencepb.Matcher{
|
||||||
Name: &name,
|
Name: name,
|
||||||
Value: &value,
|
Pattern: pattern,
|
||||||
IsRegex: &isRegex,
|
Type: matcherType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,50 +144,50 @@ func createLabelMatcher(name string, value string, matchType labels.MatchType) *
|
|||||||
return matcher
|
return matcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGettableSilenceMatchesFilterLabels(t *testing.T) {
|
func TestCheckSilenceMatchesFilterLabels(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
silenceMatchers []*open_api_models.Matcher
|
silenceMatchers []*silencepb.Matcher
|
||||||
filterMatchers []*labels.Matcher
|
filterMatchers []*labels.Matcher
|
||||||
expected bool
|
expected bool
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []test{
|
tests := []test{
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "value", false)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "value", silencepb.Matcher_EQUAL)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchEqual)},
|
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchEqual)},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "value", false)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "value", silencepb.Matcher_EQUAL)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "novalue", labels.MatchEqual)},
|
[]*labels.Matcher{createLabelMatcher("label", "novalue", labels.MatchEqual)},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "(foo|bar)", true)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "(foo|bar)", silencepb.Matcher_REGEXP)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "foo", true)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "foo", silencepb.Matcher_REGEXP)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "value", false)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "value", silencepb.Matcher_EQUAL)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchRegexp)},
|
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchRegexp)},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{createModelMatcher("label", "value", true)},
|
[]*silencepb.Matcher{createSilenceMatcher("label", "value", silencepb.Matcher_REGEXP)},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchEqual)},
|
[]*labels.Matcher{createLabelMatcher("label", "value", labels.MatchEqual)},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
[]*open_api_models.Matcher{
|
[]*silencepb.Matcher{
|
||||||
createModelMatcher("label", "(foo|bar)", true),
|
createSilenceMatcher("label", "(foo|bar)", silencepb.Matcher_REGEXP),
|
||||||
createModelMatcher("label", "value", false),
|
createSilenceMatcher("label", "value", silencepb.Matcher_EQUAL),
|
||||||
},
|
},
|
||||||
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
[]*labels.Matcher{createLabelMatcher("label", "(foo|bar)", labels.MatchRegexp)},
|
||||||
true,
|
true,
|
||||||
@ -194,12 +195,10 @@ func TestGettableSilenceMatchesFilterLabels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
silence := open_api_models.GettableSilence{
|
silence := silencepb.Silence{
|
||||||
Silence: open_api_models.Silence{
|
|
||||||
Matchers: test.silenceMatchers,
|
Matchers: test.silenceMatchers,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
actual := gettableSilenceMatchesFilterLabels(silence, test.filterMatchers)
|
actual := checkSilenceMatchesFilterLabels(&silence, test.filterMatchers)
|
||||||
if test.expected != actual {
|
if test.expected != actual {
|
||||||
t.Fatal("unexpected match result between silence and filter. expected:", test.expected, ", actual:", actual)
|
t.Fatal("unexpected match result between silence and filter. expected:", test.expected, ", actual:", actual)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user