From 3a1f6905e05fd3807f1a147f50e76c738bd0a593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Fri, 28 Apr 2017 12:38:47 -0700 Subject: [PATCH] Add basic support for Alertmanager 0.6.1 This makes unsee work with 0.6.1, but the new status means that we should refactor unsee data model and pull inhibited and silenced into it, with a single filter --- alertmanager/alertmanager.go | 2 + mapper/v05/alerts.go | 2 +- mapper/v061/alerts.go | 101 +++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 mapper/v061/alerts.go diff --git a/alertmanager/alertmanager.go b/alertmanager/alertmanager.go index 87d229049..e9cff4adc 100644 --- a/alertmanager/alertmanager.go +++ b/alertmanager/alertmanager.go @@ -6,6 +6,7 @@ import ( "github.com/cloudflare/unsee/mapper" "github.com/cloudflare/unsee/mapper/v04" "github.com/cloudflare/unsee/mapper/v05" + "github.com/cloudflare/unsee/mapper/v061" "github.com/cloudflare/unsee/models" log "github.com/Sirupsen/logrus" @@ -15,6 +16,7 @@ import ( func init() { mapper.RegisterAlertMapper(v04.AlertMapper{}) mapper.RegisterAlertMapper(v05.AlertMapper{}) + mapper.RegisterAlertMapper(v061.AlertMapper{}) mapper.RegisterSilenceMapper(v04.SilenceMapper{}) mapper.RegisterSilenceMapper(v05.SilenceMapper{}) } diff --git a/mapper/v05/alerts.go b/mapper/v05/alerts.go index 9308adcde..fbcad099c 100644 --- a/mapper/v05/alerts.go +++ b/mapper/v05/alerts.go @@ -45,7 +45,7 @@ type AlertMapper struct { // IsSupported returns true if given version string is supported func (m AlertMapper) IsSupported(version string) bool { - versionRange := semver.MustParseRange(">=0.5.0") + versionRange := semver.MustParseRange(">=0.5.0 <=0.6.0") return versionRange(semver.MustParse(version)) } diff --git a/mapper/v061/alerts.go b/mapper/v061/alerts.go new file mode 100644 index 000000000..dad9bbd41 --- /dev/null +++ b/mapper/v061/alerts.go @@ -0,0 +1,101 @@ +// Package v061 package implements support for interacting with +// Alertmanager 0.6.1 +// Collected data will be mapped to unsee internal schema defined the +// unsee/models package +// This file defines Alertmanager alerts mapping +package v061 + +import ( + "errors" + "time" + + "github.com/blang/semver" + "github.com/cloudflare/unsee/config" + "github.com/cloudflare/unsee/mapper" + "github.com/cloudflare/unsee/models" + "github.com/cloudflare/unsee/transport" +) + +type alert struct { + Annotations map[string]string `json:"annotations"` + Labels map[string]string `json:"labels"` + StartsAt time.Time `json:"startsAt"` + EndsAt time.Time `json:"endsAt"` + GeneratorURL string `json:"generatorURL"` + Status string `json:"Status"` + SilencedBy []string `json:"silencedBy"` + InhibitedBy []string `json:"inhibitedBy"` +} + +type alertsGroups struct { + Labels map[string]string `json:"labels"` + Blocks []struct { + Alerts []alert `json:"alerts"` + } `json:"blocks"` +} + +type alertsGroupsAPISchema struct { + Status string `json:"status"` + Groups []alertsGroups `json:"data"` + Error string `json:"error"` +} + +// AlertMapper implements Alertmanager API schema +type AlertMapper struct { + mapper.AlertMapper +} + +// IsSupported returns true if given version string is supported +func (m AlertMapper) IsSupported(version string) bool { + versionRange := semver.MustParseRange(">=0.6.1") + return versionRange(semver.MustParse(version)) +} + +// GetAlerts will make a request to Alertmanager API and parse the response +// It will only return alerts or error (if any) +func (m AlertMapper) GetAlerts() ([]models.AlertGroup, error) { + groups := []models.AlertGroup{} + resp := alertsGroupsAPISchema{} + + url, err := transport.JoinURL(config.Config.AlertmanagerURI, "api/v1/alerts/groups") + if err != nil { + return groups, err + } + + err = transport.ReadJSON(url, config.Config.AlertmanagerTimeout, &resp) + if err != nil { + return groups, err + } + + if resp.Status != "success" { + return groups, errors.New(resp.Error) + } + + for _, g := range resp.Groups { + alertList := models.AlertList{} + for _, b := range g.Blocks { + for _, a := range b.Alerts { + silenceID := "" + if len(a.SilencedBy) > 0 { + silenceID = a.SilencedBy[0] + } + us := models.Alert{ + Annotations: a.Annotations, + Labels: a.Labels, + StartsAt: a.StartsAt, + EndsAt: a.EndsAt, + GeneratorURL: a.GeneratorURL, + Inhibited: len(a.InhibitedBy) > 0, + Silenced: silenceID, + } + alertList = append(alertList, us) + } + } + ug := models.AlertGroup{ + Labels: g.Labels, + Alerts: alertList, + } + groups = append(groups, ug) + } + return groups, nil +}