From 8b5862d44b057384f1656ac63c9f32b7dffc0dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Fri, 30 Nov 2018 23:14:59 +0000 Subject: [PATCH] chore(api): store cluster as a dict This will allow silences to be grouped by cluster rather than by alertmanager instance --- alerts.go | 15 +++++++++------ internal/models/alertmanager.go | 2 +- internal/slices/slices.go | 21 +++++++++++++++++++++ internal/slices/slices_test.go | 19 +++++++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/alerts.go b/alerts.go index 267c7f189..404d78886 100644 --- a/alerts.go +++ b/alerts.go @@ -2,11 +2,13 @@ package main import ( "sort" - "strings" "github.com/prymitive/karma/internal/alertmanager" "github.com/prymitive/karma/internal/filters" "github.com/prymitive/karma/internal/models" + "github.com/prymitive/karma/internal/slices" + + log "github.com/sirupsen/logrus" ) func getFiltersFromQuery(filterStrings []string) ([]filters.FilterT, bool) { @@ -41,7 +43,11 @@ func getUpstreams() models.AlertmanagerAPISummary { for _, upstream := range upstreams { members := upstream.ClusterMemberNames() sort.Strings(members) - key := strings.Join(members[:], "\n") + key, err := slices.StringSliceToSHA1(members) + if err != nil { + log.Errorf("slices.StringSliceToSHA1 error: %s", err) + continue + } if _, found := clusters[key]; !found { clusters[key] = members } @@ -63,10 +69,7 @@ func getUpstreams() models.AlertmanagerAPISummary { summary.Counters.Failed++ } } - - for _, cluster := range clusters { - summary.Clusters = append(summary.Clusters, cluster) - } + summary.Clusters = clusters return summary } diff --git a/internal/models/alertmanager.go b/internal/models/alertmanager.go index 718322822..6c7596d44 100644 --- a/internal/models/alertmanager.go +++ b/internal/models/alertmanager.go @@ -47,5 +47,5 @@ type AlertmanagerAPICounters struct { type AlertmanagerAPISummary struct { Counters AlertmanagerAPICounters `json:"counters"` Instances []AlertmanagerAPIStatus `json:"instances"` - Clusters [][]string `json:"clusters"` + Clusters map[string][]string `json:"clusters"` } diff --git a/internal/slices/slices.go b/internal/slices/slices.go index a18d400e3..47cddf4fb 100644 --- a/internal/slices/slices.go +++ b/internal/slices/slices.go @@ -1,5 +1,10 @@ package slices +import ( + "crypto/sha1" + "fmt" +) + // BoolInSlice returns true if given bool is found in a slice of bools func BoolInSlice(boolArray []bool, value bool) bool { for _, s := range boolArray { @@ -19,3 +24,19 @@ func StringInSlice(stringArray []string, value string) bool { } return false } + +// StringSliceToSHA1 returns a SHA1 hash computed from a slice of strings +func StringSliceToSHA1(stringArray []string) (string, error) { + h := sha1.New() + for _, s := range stringArray { + _, err := h.Write([]byte(s)) + if err != nil { + return "", err + } + _, err = h.Write([]byte("\n")) + if err != nil { + return "", err + } + } + return fmt.Sprintf("%x", h.Sum(nil)), nil +} diff --git a/internal/slices/slices_test.go b/internal/slices/slices_test.go index dee989619..2e5fc01d1 100644 --- a/internal/slices/slices_test.go +++ b/internal/slices/slices_test.go @@ -111,3 +111,22 @@ func TestBoolInSlice(t *testing.T) { } } } + +func TestStringSliceToSHA1(t *testing.T) { + s, err := slices.StringSliceToSHA1([]string{"a", "b", "c"}) + if err != nil { + t.Errorf("StringSliceToSHA1() returned error: %s", err) + } + if s == "" { + t.Errorf("StringSliceToSHA1() returned empty string") + } +} + +func BenchmarkStringSliceToSHA1(b *testing.B) { + for _, stringSliceTest := range stringSliceTests { + _, err := slices.StringSliceToSHA1(stringSliceTest.array) + if err != nil { + b.Errorf("StringSliceToSHA1() returned error: %s", err) + } + } +}