mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
refactor(backend): add support for OpenAPI based client for alertmanager
This commit is contained in:
1
go.mod
1
go.mod
@@ -31,6 +31,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.3.2
|
||||
github.com/terinjokes/bakelite v0.2.0
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c // indirect
|
||||
gopkg.in/go-playground/colors.v1 v1.2.0
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
||||
|
||||
3
go.sum
3
go.sum
@@ -283,6 +283,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
|
||||
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4=
|
||||
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c h1:Rx/HTKi09myZ25t1SOlDHmHOy/mKxNAcu0hP1oPX9qM=
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -348,6 +350,7 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34 h1:B1LAOfRqg2QUyCdzfjf46quTSYUTAK5OCwbh6pljHbM=
|
||||
mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.1-0.20190210232911-dee78e514455 h1:qoQ5Kt+Zm+GXBtz49YwD3juBhr/E0U25jO6bBzxW6NI=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.1-0.20190210232911-dee78e514455/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=
|
||||
|
||||
@@ -2,10 +2,11 @@ package alertmanager
|
||||
|
||||
import (
|
||||
"github.com/prymitive/karma/internal/mapper"
|
||||
"github.com/prymitive/karma/internal/mapper/v04"
|
||||
"github.com/prymitive/karma/internal/mapper/v05"
|
||||
"github.com/prymitive/karma/internal/mapper/v061"
|
||||
"github.com/prymitive/karma/internal/mapper/v062"
|
||||
v016 "github.com/prymitive/karma/internal/mapper/v016"
|
||||
v04 "github.com/prymitive/karma/internal/mapper/v04"
|
||||
v05 "github.com/prymitive/karma/internal/mapper/v05"
|
||||
v061 "github.com/prymitive/karma/internal/mapper/v061"
|
||||
v062 "github.com/prymitive/karma/internal/mapper/v062"
|
||||
)
|
||||
|
||||
// initialize all mappers
|
||||
@@ -16,4 +17,6 @@ func init() {
|
||||
mapper.RegisterAlertMapper(v062.AlertMapper{})
|
||||
mapper.RegisterSilenceMapper(v04.SilenceMapper{})
|
||||
mapper.RegisterSilenceMapper(v05.SilenceMapper{})
|
||||
mapper.RegisterAlertMapper(v016.AlertMapper{})
|
||||
mapper.RegisterSilenceMapper(v016.SilenceMapper{})
|
||||
}
|
||||
|
||||
@@ -170,31 +170,40 @@ func (am *Alertmanager) pullSilences(version string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// generate full URL to collect silences from
|
||||
url, err := mapper.AbsoluteURL(am.URI)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] Failed to generate silences endpoint URL: %s", am.Name, err)
|
||||
return err
|
||||
}
|
||||
// append query args if mapper needs those
|
||||
queryArgs := mapper.QueryArgs()
|
||||
if queryArgs != "" {
|
||||
url = fmt.Sprintf("%s?%s", url, queryArgs)
|
||||
}
|
||||
var silences []models.Silence
|
||||
|
||||
start := time.Now()
|
||||
// read raw body from the source
|
||||
source, err := am.reader.Read(url, am.HTTPHeaders)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] %s request failed: %s", am.Name, uri.SanitizeURI(url), err)
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
if mapper.IsOpenAPI() {
|
||||
silences, err = mapper.Collect(am.URI, am.HTTPHeaders, am.RequestTimeout, am.HTTPTransport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// generate full URL to collect silences from
|
||||
url, err := mapper.AbsoluteURL(am.URI)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] Failed to generate silences endpoint URL: %s", am.Name, err)
|
||||
return err
|
||||
}
|
||||
// append query args if mapper needs those
|
||||
queryArgs := mapper.QueryArgs()
|
||||
if queryArgs != "" {
|
||||
url = fmt.Sprintf("%s?%s", url, queryArgs)
|
||||
}
|
||||
|
||||
// decode body text
|
||||
silences, err := mapper.Decode(source)
|
||||
if err != nil {
|
||||
return err
|
||||
// read raw body from the source
|
||||
source, err := am.reader.Read(url, am.HTTPHeaders)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] %s request failed: %s", am.Name, uri.SanitizeURI(url), err)
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
// decode body text
|
||||
silences, err = mapper.Decode(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Infof("[%s] Got %d silences(s) in %s", am.Name, len(silences), time.Since(start))
|
||||
|
||||
@@ -234,32 +243,42 @@ func (am *Alertmanager) pullAlerts(version string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// generate full URL to collect alerts from
|
||||
url, err := mapper.AbsoluteURL(am.URI)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] Failed to generate alerts endpoint URL: %s", am.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// append query args if mapper needs those
|
||||
queryArgs := mapper.QueryArgs()
|
||||
if queryArgs != "" {
|
||||
url = fmt.Sprintf("%s?%s", url, queryArgs)
|
||||
}
|
||||
var groups []models.AlertGroup
|
||||
|
||||
start := time.Now()
|
||||
// read raw body from the source
|
||||
source, err := am.reader.Read(url, am.HTTPHeaders)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] %s request failed: %s", am.Name, uri.SanitizeURI(url), err)
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
if mapper.IsOpenAPI() {
|
||||
groups, err = mapper.Collect(am.URI, am.HTTPHeaders, am.RequestTimeout, am.HTTPTransport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
// decode body text
|
||||
groups, err := mapper.Decode(source)
|
||||
if err != nil {
|
||||
return err
|
||||
// generate full URL to collect alerts from
|
||||
url, err := mapper.AbsoluteURL(am.URI)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] Failed to generate alerts endpoint URL: %s", am.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// append query args if mapper needs those
|
||||
queryArgs := mapper.QueryArgs()
|
||||
if queryArgs != "" {
|
||||
url = fmt.Sprintf("%s?%s", url, queryArgs)
|
||||
}
|
||||
|
||||
// read raw body from the source
|
||||
source, err := am.reader.Read(url, am.HTTPHeaders)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] %s request failed: %s", am.Name, uri.SanitizeURI(url), err)
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
// decode body text
|
||||
groups, err = mapper.Decode(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Infof("[%s] Got %d alert group(s) in %s", am.Name, len(groups), time.Since(start))
|
||||
|
||||
|
||||
22
internal/mapper/headers.go
Normal file
22
internal/mapper/headers.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package mapper
|
||||
|
||||
import "net/http"
|
||||
|
||||
func SetHeaders(inner http.RoundTripper, headers map[string]string) http.RoundTripper {
|
||||
return &headersRoundTripper{
|
||||
inner: inner,
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
|
||||
type headersRoundTripper struct {
|
||||
inner http.RoundTripper
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
func (hrt *headersRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
for k, v := range hrt.Headers {
|
||||
r.Header.Set(k, v)
|
||||
}
|
||||
return hrt.inner.RoundTrip(r)
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package mapper
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/prymitive/karma/internal/models"
|
||||
)
|
||||
@@ -17,18 +19,21 @@ type Mapper interface {
|
||||
IsSupported(version string) bool
|
||||
AbsoluteURL(baseURI string) (string, error)
|
||||
QueryArgs() string
|
||||
IsOpenAPI() bool
|
||||
}
|
||||
|
||||
// AlertMapper handles mapping of Alertmanager alert information to karma AlertGroup models
|
||||
type AlertMapper interface {
|
||||
Mapper
|
||||
Decode(io.ReadCloser) ([]models.AlertGroup, error)
|
||||
Collect(string, map[string]string, time.Duration, http.RoundTripper) ([]models.AlertGroup, error)
|
||||
}
|
||||
|
||||
// SilenceMapper handles mapping of Alertmanager silence information to karma Silence models
|
||||
type SilenceMapper interface {
|
||||
Mapper
|
||||
Decode(io.ReadCloser) ([]models.Silence, error)
|
||||
Collect(string, map[string]string, time.Duration, http.RoundTripper) ([]models.Silence, error)
|
||||
}
|
||||
|
||||
// RegisterAlertMapper allows to register mapper implementing alert data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM quay.io/goswagger/swagger:v0.18.0
|
||||
FROM quay.io/goswagger/swagger:v0.19.0
|
||||
|
||||
RUN apk add --update curl
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package v016
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver"
|
||||
|
||||
"github.com/prymitive/karma/internal/mapper"
|
||||
"github.com/prymitive/karma/internal/models"
|
||||
"github.com/prymitive/karma/internal/uri"
|
||||
@@ -30,8 +32,12 @@ func (m AlertMapper) IsSupported(version string) bool {
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m AlertMapper) Decode(source io.ReadCloser) ([]models.AlertGroup, error) {
|
||||
defer source.Close()
|
||||
return Groups()
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m AlertMapper) IsOpenAPI() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m AlertMapper) Collect(uri string, headers map[string]string, timeout time.Duration, httpTransport http.RoundTripper) ([]models.AlertGroup, error) {
|
||||
c := newClient(uri, headers, httpTransport)
|
||||
return groups(c, timeout)
|
||||
}
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
package v016
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
|
||||
"github.com/prymitive/karma/internal/mapper"
|
||||
"github.com/prymitive/karma/internal/mapper/v016/client"
|
||||
"github.com/prymitive/karma/internal/mapper/v016/client/alertgroup"
|
||||
"github.com/prymitive/karma/internal/mapper/v016/client/silence"
|
||||
"github.com/prymitive/karma/internal/models"
|
||||
)
|
||||
|
||||
func newClient(uri string, headers map[string]string, httpTransport http.RoundTripper) *client.Alertmanager {
|
||||
u, _ := url.Parse(uri)
|
||||
transport := httptransport.New(u.Host, path.Join(u.Path, "/api/v2"), []string{u.Scheme})
|
||||
if httpTransport != nil {
|
||||
transport.Transport = mapper.SetHeaders(httpTransport, headers)
|
||||
} else {
|
||||
transport.Transport = mapper.SetHeaders(transport.Transport, headers)
|
||||
}
|
||||
c := client.New(transport, nil)
|
||||
return c
|
||||
}
|
||||
|
||||
// Alerts will fetch all alert groups from the API
|
||||
func Groups() ([]models.AlertGroup, error) {
|
||||
func groups(c *client.Alertmanager, timeout time.Duration) ([]models.AlertGroup, error) {
|
||||
ret := []models.AlertGroup{}
|
||||
|
||||
transport := client.TransportConfig{
|
||||
Host: "localhost:9093",
|
||||
BasePath: "/api/v2",
|
||||
Schemes: []string{"http"},
|
||||
}
|
||||
cli := client.NewHTTPClientWithConfig(nil, &transport)
|
||||
|
||||
timeout := time.Second * 30
|
||||
|
||||
groups, err := cli.Alertgroup.GetAlertGroups(alertgroup.NewGetAlertGroupsParamsWithTimeout(timeout))
|
||||
groups, err := c.Alertgroup.GetAlertGroups(alertgroup.NewGetAlertGroupsParamsWithTimeout(timeout))
|
||||
if err != nil {
|
||||
return []models.AlertGroup{}, err
|
||||
}
|
||||
@@ -53,3 +63,33 @@ func Groups() ([]models.AlertGroup, error) {
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func silences(c *client.Alertmanager, timeout time.Duration) ([]models.Silence, error) {
|
||||
ret := []models.Silence{}
|
||||
|
||||
silences, err := c.Silence.GetSilences(silence.NewGetSilencesParamsWithTimeout(timeout))
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, s := range silences.Payload {
|
||||
us := models.Silence{
|
||||
ID: *s.ID,
|
||||
StartsAt: time.Time(*s.StartsAt),
|
||||
EndsAt: time.Time(*s.EndsAt),
|
||||
CreatedBy: *s.CreatedBy,
|
||||
Comment: *s.Comment,
|
||||
}
|
||||
for _, m := range s.Matchers {
|
||||
sm := models.SilenceMatcher{
|
||||
Name: *m.Name,
|
||||
Value: *m.Value,
|
||||
IsRegex: *m.IsRegex,
|
||||
}
|
||||
us.Matchers = append(us.Matchers, sm)
|
||||
}
|
||||
ret = append(ret, us)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
42
internal/mapper/v016/silences.go
Normal file
42
internal/mapper/v016/silences.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package v016
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/prymitive/karma/internal/mapper"
|
||||
"github.com/prymitive/karma/internal/models"
|
||||
"github.com/prymitive/karma/internal/uri"
|
||||
)
|
||||
|
||||
// SilenceMapper implements Alertmanager 0.4 API schema
|
||||
type SilenceMapper struct {
|
||||
mapper.SilenceMapper
|
||||
}
|
||||
|
||||
// AbsoluteURL for silences API endpoint this mapper supports
|
||||
func (m SilenceMapper) AbsoluteURL(baseURI string) (string, error) {
|
||||
return uri.JoinURL(baseURI, "api/v2/silences")
|
||||
}
|
||||
|
||||
// QueryArgs for HTTP requests send to the Alertmanager API endpoint
|
||||
func (m SilenceMapper) QueryArgs() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsSupported returns true if given version string is supported
|
||||
func (m SilenceMapper) IsSupported(version string) bool {
|
||||
versionRange := semver.MustParseRange(">=0.16.0")
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m SilenceMapper) IsOpenAPI() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m SilenceMapper) Collect(uri string, headers map[string]string, timeout time.Duration, httpTransport http.RoundTripper) ([]models.Silence, error) {
|
||||
c := newClient(uri, headers, httpTransport)
|
||||
return silences(c, timeout)
|
||||
}
|
||||
@@ -70,6 +70,11 @@ func (m AlertMapper) IsSupported(version string) bool {
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m AlertMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m AlertMapper) Decode(source io.ReadCloser) ([]models.AlertGroup, error) {
|
||||
groups := []models.AlertGroup{}
|
||||
|
||||
@@ -67,6 +67,11 @@ func (m SilenceMapper) IsSupported(version string) bool {
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m SilenceMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m SilenceMapper) Decode(source io.ReadCloser) ([]models.Silence, error) {
|
||||
silences := []models.Silence{}
|
||||
@@ -85,13 +90,20 @@ func (m SilenceMapper) Decode(source io.ReadCloser) ([]models.Silence, error) {
|
||||
for _, s := range resp.Data.Silences {
|
||||
us := models.Silence{
|
||||
ID: strconv.Itoa(s.ID),
|
||||
Matchers: s.Matchers,
|
||||
StartsAt: s.StartsAt,
|
||||
EndsAt: s.EndsAt,
|
||||
CreatedAt: s.CreatedAt,
|
||||
CreatedBy: s.CreatedBy,
|
||||
Comment: s.Comment,
|
||||
}
|
||||
for _, m := range s.Matchers {
|
||||
sm := models.SilenceMatcher{
|
||||
Name: m.Name,
|
||||
Value: m.Value,
|
||||
IsRegex: m.IsRegex,
|
||||
}
|
||||
us.Matchers = append(us.Matchers, sm)
|
||||
}
|
||||
silences = append(silences, us)
|
||||
}
|
||||
return silences, nil
|
||||
|
||||
@@ -69,6 +69,11 @@ func (m AlertMapper) IsSupported(version string) bool {
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m AlertMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m AlertMapper) Decode(source io.ReadCloser) ([]models.AlertGroup, error) {
|
||||
groups := []models.AlertGroup{}
|
||||
|
||||
@@ -53,10 +53,15 @@ func (m SilenceMapper) QueryArgs() string {
|
||||
|
||||
// IsSupported returns true if given version string is supported
|
||||
func (m SilenceMapper) IsSupported(version string) bool {
|
||||
versionRange := semver.MustParseRange(">=0.5.0")
|
||||
versionRange := semver.MustParseRange(">=0.5.0 <0.16.0")
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m SilenceMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m SilenceMapper) Decode(source io.ReadCloser) ([]models.Silence, error) {
|
||||
silences := []models.Silence{}
|
||||
@@ -75,13 +80,20 @@ func (m SilenceMapper) Decode(source io.ReadCloser) ([]models.Silence, error) {
|
||||
for _, s := range resp.Data {
|
||||
us := models.Silence{
|
||||
ID: s.ID,
|
||||
Matchers: s.Matchers,
|
||||
StartsAt: s.StartsAt,
|
||||
EndsAt: s.EndsAt,
|
||||
CreatedAt: s.CreatedAt,
|
||||
CreatedBy: s.CreatedBy,
|
||||
Comment: s.Comment,
|
||||
}
|
||||
for _, m := range s.Matchers {
|
||||
sm := models.SilenceMatcher{
|
||||
Name: m.Name,
|
||||
Value: m.Value,
|
||||
IsRegex: m.IsRegex,
|
||||
}
|
||||
us.Matchers = append(us.Matchers, sm)
|
||||
}
|
||||
silences = append(silences, us)
|
||||
}
|
||||
return silences, nil
|
||||
|
||||
@@ -71,6 +71,11 @@ func (m AlertMapper) IsSupported(version string) bool {
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m AlertMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m AlertMapper) Decode(source io.ReadCloser) ([]models.AlertGroup, error) {
|
||||
groups := []models.AlertGroup{}
|
||||
|
||||
@@ -71,10 +71,15 @@ func (m AlertMapper) QueryArgs() string {
|
||||
|
||||
// IsSupported returns true if given version string is supported
|
||||
func (m AlertMapper) IsSupported(version string) bool {
|
||||
versionRange := semver.MustParseRange(">=0.6.2")
|
||||
versionRange := semver.MustParseRange(">=0.6.2 <0.16.0")
|
||||
return versionRange(semver.MustParse(version))
|
||||
}
|
||||
|
||||
// IsOpenAPI returns true is remote Alertmanager uses OpenAPI
|
||||
func (m AlertMapper) IsOpenAPI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Decode Alertmanager API response body and return karma model instances
|
||||
func (m AlertMapper) Decode(source io.ReadCloser) ([]models.AlertGroup, error) {
|
||||
groups := []models.AlertGroup{}
|
||||
|
||||
@@ -2,22 +2,24 @@ package models
|
||||
|
||||
import "time"
|
||||
|
||||
type SilenceMatcher struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
IsRegex bool `json:"isRegex"`
|
||||
}
|
||||
|
||||
// Silence is vanilla silence + some additional attributes
|
||||
// karma adds JIRA support, it can extract JIRA IDs from comments
|
||||
// extracted ID is used to generate link to JIRA issue
|
||||
// this means karma needs to store additional fields for each silence
|
||||
type Silence struct {
|
||||
ID string `json:"id"`
|
||||
Matchers []struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
IsRegex bool `json:"isRegex"`
|
||||
} `json:"matchers"`
|
||||
StartsAt time.Time `json:"startsAt"`
|
||||
EndsAt time.Time `json:"endsAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Comment string `json:"comment"`
|
||||
ID string `json:"id"`
|
||||
Matchers []SilenceMatcher `json:"matchers"`
|
||||
StartsAt time.Time `json:"startsAt"`
|
||||
EndsAt time.Time `json:"endsAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Comment string `json:"comment"`
|
||||
// karma fields
|
||||
JiraID string `json:"jiraID"`
|
||||
JiraURL string `json:"jiraURL"`
|
||||
|
||||
Reference in New Issue
Block a user