From 9390bbccc063c166c076a1c8356fbca544eec24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Fri, 12 Jun 2020 10:34:42 +0100 Subject: [PATCH] feat(api): add @cluster filter --- internal/filters/autocomplete_test.go | 11 +++-- internal/filters/filter_cluster.go | 61 +++++++++++++++++++++++++++ internal/filters/filter_test.go | 25 ++++++++++- internal/filters/registry.go | 7 +++ 4 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 internal/filters/filter_cluster.go diff --git a/internal/filters/autocomplete_test.go b/internal/filters/autocomplete_test.go index 734b94d94..518bf8d93 100644 --- a/internal/filters/autocomplete_test.go +++ b/internal/filters/autocomplete_test.go @@ -38,8 +38,8 @@ var acTests = []acTest{ }, Receiver: "default", Alertmanager: []models.AlertmanagerInstance{ - {Name: "am1"}, - {Name: "am2"}, + {Cluster: "cluster", Name: "am1"}, + {Cluster: "cluster", Name: "am2"}, }, }, { @@ -50,9 +50,10 @@ var acTests = []acTest{ }, Receiver: "not default", Alertmanager: []models.AlertmanagerInstance{ - {Name: "am1"}, + {Cluster: "cluster", Name: "am1"}, { - Name: "am2", + Cluster: "cluster", + Name: "am2", Silences: map[string]*models.Silence{ "1234567890": { ID: "1234567890", @@ -73,6 +74,8 @@ var acTests = []acTest{ "@alertmanager!=am2", "@alertmanager=am1", "@alertmanager=am2", + "@cluster!=cluster", + "@cluster=cluster", "@limit=10", "@limit=50", "@receiver!=default", diff --git a/internal/filters/filter_cluster.go b/internal/filters/filter_cluster.go new file mode 100644 index 000000000..b09346025 --- /dev/null +++ b/internal/filters/filter_cluster.go @@ -0,0 +1,61 @@ +package filters + +import ( + "fmt" + "strings" + + "github.com/prymitive/karma/internal/models" +) + +type alertmanagerClusterFilter struct { + alertFilter +} + +func (filter *alertmanagerClusterFilter) Match(alert *models.Alert, matches int) bool { + if filter.IsValid { + var isMatch bool + for _, am := range alert.Alertmanager { + if filter.Matcher.Compare(am.Cluster, filter.Value) { + isMatch = true + } + } + if isMatch { + filter.Hits++ + } + return isMatch + } + e := fmt.Sprintf("Match() called on invalid filter %#v", filter) + panic(e) +} + +func newAlertmanagerClusterFilter() FilterT { + f := alertmanagerClusterFilter{} + return &f +} + +func alertmanagerClusterAutocomplete(name string, operators []string, alerts []models.Alert) []models.Autocomplete { + tokens := map[string]models.Autocomplete{} + for _, alert := range alerts { + for _, am := range alert.Alertmanager { + for _, operator := range operators { + switch operator { + case equalOperator, notEqualOperator: + token := fmt.Sprintf("%s%s%s", name, operator, am.Cluster) + tokens[token] = makeAC( + token, + []string{ + name, + strings.TrimPrefix(name, "@"), + name + operator, + }, + ) + } + } + } + } + acData := make([]models.Autocomplete, 0, len(tokens)) + for _, token := range tokens { + acData = append(acData, token) + } + return acData +} diff --git a/internal/filters/filter_test.go b/internal/filters/filter_test.go index a74561965..ef05ce909 100644 --- a/internal/filters/filter_test.go +++ b/internal/filters/filter_test.go @@ -587,6 +587,28 @@ var tests = []filterTest{ }, IsMatch: true, }, + { + Expression: "@cluster=foo", + IsValid: true, + Alert: models.Alert{}, + IsMatch: false, + }, + { + Expression: "@cluster=HA", + IsValid: true, + Alert: models.Alert{ + Receiver: "by-name", + }, + IsMatch: true, + }, + { + Expression: "@cluster!=foo", + IsValid: true, + Alert: models.Alert{ + Receiver: "by-name", + }, + IsMatch: true, + }, { Expression: "@receiver=by-name", IsValid: true, @@ -608,7 +630,7 @@ var tests = []filterTest{ func TestFilters(t *testing.T) { log.SetLevel(log.ErrorLevel) - am, err := alertmanager.NewAlertmanager("test", "http://localhost", alertmanager.WithRequestTimeout(time.Second)) + am, err := alertmanager.NewAlertmanager("HA", "test", "http://localhost", alertmanager.WithRequestTimeout(time.Second)) if err != nil { t.Error(err) } @@ -616,6 +638,7 @@ func TestFilters(t *testing.T) { alert := models.Alert(ft.Alert) alert.Alertmanager = []models.AlertmanagerInstance{ { + Cluster: "HA", Name: am.Name, Silences: map[string]*models.Silence{}, SilencedBy: []string{}, diff --git a/internal/filters/registry.go b/internal/filters/registry.go index 4fffdfece..95418136b 100644 --- a/internal/filters/registry.go +++ b/internal/filters/registry.go @@ -47,6 +47,13 @@ var AllFilters = []filterConfig{ Factory: newAlertmanagerInstanceFilter, Autocomplete: alertmanagerInstanceAutocomplete, }, + { + Label: "@cluster", + LabelRe: regexp.MustCompile("^@cluster$"), + SupportedOperators: []string{regexpOperator, negativeRegexOperator, equalOperator, notEqualOperator}, + Factory: newAlertmanagerClusterFilter, + Autocomplete: alertmanagerClusterAutocomplete, + }, { Label: "@state", LabelRe: regexp.MustCompile("^@state$"),