The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/tests/api/alerting/api_notification_channel_te...

1725 lines
50 KiB

package alerting
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"regexp"
"strings"
"sync"
"testing"
"time"
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels"
"github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/tests/testinfra"
)
func TestNotificationChannels(t *testing.T) {
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
EnableFeatureToggles: []string{"ngalert"},
DisableAnonymous: true,
})
s := testinfra.SetUpDatabase(t, dir)
s.Bus = bus.GetBus()
grafanaListedAddr := testinfra.StartGrafana(t, dir, path, s)
mockChannel := newMockNotificationChannel(t, grafanaListedAddr)
amConfig := getAlertmanagerConfig(mockChannel.server.Addr)
mockEmail := &mockEmailHandler{}
// Overriding some URLs to send to the mock channel.
os, opa, ot, opu, ogb, ol, oth := channels.SlackAPIEndpoint, channels.PagerdutyEventAPIURL,
channels.TelegramAPIURL, channels.PushoverEndpoint, channels.GetBoundary,
channels.LineNotifyURL, channels.ThreemaGwBaseURL
originalTemplate := channels.DefaultTemplateString
originalEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
t.Cleanup(func() {
channels.SlackAPIEndpoint, channels.PagerdutyEventAPIURL,
channels.TelegramAPIURL, channels.PushoverEndpoint, channels.GetBoundary,
channels.LineNotifyURL, channels.ThreemaGwBaseURL = os, opa, ot, opu, ogb, ol, oth
channels.DefaultTemplateString = originalTemplate
bus.AddHandlerCtx("", originalEmailBus)
})
channels.DefaultTemplateString = channels.TemplateForTestsString
channels.SlackAPIEndpoint = fmt.Sprintf("http://%s/slack_recvX/slack_testX", mockChannel.server.Addr)
channels.PagerdutyEventAPIURL = fmt.Sprintf("http://%s/pagerduty_recvX/pagerduty_testX", mockChannel.server.Addr)
channels.TelegramAPIURL = fmt.Sprintf("http://%s/telegram_recv/bot%%s", mockChannel.server.Addr)
channels.PushoverEndpoint = fmt.Sprintf("http://%s/pushover_recv/pushover_test", mockChannel.server.Addr)
channels.LineNotifyURL = fmt.Sprintf("http://%s/line_recv/line_test", mockChannel.server.Addr)
channels.ThreemaGwBaseURL = fmt.Sprintf("http://%s/threema_recv/threema_test", mockChannel.server.Addr)
channels.GetBoundary = func() string { return "abcd" }
bus.AddHandlerCtx("", mockEmail.sendEmailCommandHandlerSync)
// Create a user to make authenticated requests
require.NoError(t, createUser(t, s, models.ROLE_EDITOR, "grafana", "password"))
{
// There are no notification channel config initially - so it returns the default configuration.
alertsURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
resp := getRequest(t, alertsURL, http.StatusOK) // nolint
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.JSONEq(t, defaultAlertmanagerConfigJSON, string(b))
}
{
// Create the namespace we'll save our alerts to.
_, err := createFolder(t, s, 0, "default")
require.NoError(t, err)
// Post the alertmanager config.
u := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
_ = postRequest(t, u, amConfig, http.StatusAccepted) // nolint
// Verifying that all the receivers and routes have been registered.
alertsURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
resp := getRequest(t, alertsURL, http.StatusOK) // nolint
b := getBody(t, resp.Body)
re := regexp.MustCompile(`"uid":"([\w|-]*)"`)
e := getExpAlertmanagerConfigFromAPI(mockChannel.server.Addr)
require.JSONEq(t, e, string(re.ReplaceAll([]byte(b), []byte(`"uid":""`))))
}
{
// Create rules that will fire as quickly as possible
originalFunction := store.GenerateNewAlertRuleUID
t.Cleanup(func() {
store.GenerateNewAlertRuleUID = originalFunction
})
store.GenerateNewAlertRuleUID = func(_ *sqlstore.DBSession, _ int64, ruleTitle string) (string, error) {
return "UID_" + ruleTitle, nil
}
rulesConfig := getRulesConfig(t)
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
_ = postRequest(t, u, rulesConfig, http.StatusAccepted) // nolint
}
// Eventually, we'll get all the desired alerts.
// nolint:gosec
require.Eventually(t, func() bool {
return mockChannel.totalNotifications() >= len(nonEmailAlertNames) && len(mockEmail.emails) >= 1
}, 30*time.Second, 1*time.Second)
mockChannel.matchesExpNotifications(t, expNonEmailNotifications)
require.Equal(t, expEmailNotifications, mockEmail.emails)
require.NoError(t, mockChannel.Close())
{
// Delete the configuration; so it returns the default configuration.
u := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
req, err := http.NewRequest(http.MethodDelete, u, nil)
require.NoError(t, err)
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, 202, resp.StatusCode)
require.JSONEq(t, `{"message":"configuration deleted; the default is applied"}`, string(b))
alertsURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
resp = getRequest(t, alertsURL, http.StatusOK) // nolint
b, err = ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.JSONEq(t, defaultAlertmanagerConfigJSON, string(b))
}
}
func getAlertmanagerConfig(channelAddr string) string {
return strings.ReplaceAll(alertmanagerConfig, "CHANNEL_ADDR", channelAddr)
}
func getExpAlertmanagerConfigFromAPI(channelAddr string) string {
return strings.ReplaceAll(expAlertmanagerConfigFromAPI, "CHANNEL_ADDR", channelAddr)
}
// nonEmailAlertNames are name of alerts to be sent for non-email channels. This should be in sync with
// the routes that we define in Alertmanager config.
var nonEmailAlertNames = []string{
"AlertmanagerAlert",
"OpsGenieAlert",
"VictorOpsAlert",
"ThreemaAlert",
"LineAlert",
"DiscordAlert",
"KafkaAlert",
"GoogleChatAlert",
"PushoverAlert",
"SensuGoAlert",
"TelegramAlert",
"DingDingAlert",
"SlackAlert1",
"SlackAlert2",
"PagerdutyAlert",
"TeamsAlert",
"WebhookAlert",
}
// emailAlertNames are name of alerts to be sent via email. This should be in sync with
// the routes that we define in Alertmanager config.
var emailAlertNames = []string{
"EmailAlert",
}
func getRulesConfig(t *testing.T) string {
t.Helper()
interval, err := model.ParseDuration("10s")
require.NoError(t, err)
rules := apimodels.PostableRuleGroupConfig{
Name: "arulegroup",
Interval: interval,
}
// Create rules that will fire as quickly as possible for all the routes.
for _, alertName := range append(nonEmailAlertNames, emailAlertNames...) {
rules.Rules = append(rules.Rules, apimodels.PostableExtendedRuleNode{
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
Title: alertName,
Condition: "A",
Data: []ngmodels.AlertQuery{
{
RefID: "A",
RelativeTimeRange: ngmodels.RelativeTimeRange{
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
}`),
},
},
},
})
}
b, err := json.Marshal(rules)
require.NoError(t, err)
return string(b)
}
type mockNotificationChannel struct {
t *testing.T
server *http.Server
receivedNotifications map[string][]string
receivedNotificationsMtx sync.Mutex
}
func newMockNotificationChannel(t *testing.T, grafanaListedAddr string) *mockNotificationChannel {
lastDigit := grafanaListedAddr[len(grafanaListedAddr)-1] - 48
lastDigit = (lastDigit + 1) % 10
newAddr := fmt.Sprintf("%s%01d", grafanaListedAddr[:len(grafanaListedAddr)-1], lastDigit)
nc := &mockNotificationChannel{
server: &http.Server{
Addr: newAddr,
},
receivedNotifications: make(map[string][]string),
t: t,
}
nc.server.Handler = nc
go func() {
require.Equal(t, http.ErrServerClosed, nc.server.ListenAndServe())
}()
return nc
}
func (nc *mockNotificationChannel) ServeHTTP(res http.ResponseWriter, req *http.Request) {
nc.t.Helper()
nc.receivedNotificationsMtx.Lock()
defer nc.receivedNotificationsMtx.Unlock()
urlParts := strings.Split(req.URL.String(), "/")
key := fmt.Sprintf("%s/%s", urlParts[len(urlParts)-2], urlParts[len(urlParts)-1])
body := getBody(nc.t, req.Body)
nc.receivedNotifications[key] = append(nc.receivedNotifications[key], body)
res.WriteHeader(http.StatusOK)
}
func (nc *mockNotificationChannel) totalNotifications() int {
total := 0
nc.receivedNotificationsMtx.Lock()
defer nc.receivedNotificationsMtx.Unlock()
for _, v := range nc.receivedNotifications {
total += len(v)
}
return total
}
func (nc *mockNotificationChannel) matchesExpNotifications(t *testing.T, exp map[string][]string) {
t.Helper()
nc.receivedNotificationsMtx.Lock()
defer nc.receivedNotificationsMtx.Unlock()
require.Len(t, nc.receivedNotifications, len(exp))
for expKey, expVals := range exp {
actVals, ok := nc.receivedNotifications[expKey]
require.True(t, ok)
require.Len(t, actVals, len(expVals))
for i := range expVals {
expVal := expVals[i]
var r1, r2 *regexp.Regexp
switch expKey {
case "webhook_recv/webhook_test":
// It has a time component "startsAt".
r1 = regexp.MustCompile(`.*"startsAt"\s*:\s*"([^"]+)"`)
case "slack_recvX/slack_testX":
fallthrough
case "slack_recv1/slack_test_without_token":
// It has a time component "ts".
r1 = regexp.MustCompile(`.*"ts"\s*:\s*([0-9]+)`)
case "sensugo/events":
// It has a time component "ts".
r1 = regexp.MustCompile(`.*"issued"\s*:\s*([0-9]+)`)
case "pagerduty_recvX/pagerduty_testX":
// It has a changing "source".
r1 = regexp.MustCompile(`.*"source"\s*:\s*"([^"]+)"`)
case "googlechat_recv/googlechat_test":
// "Grafana v | 25 May 21 17:44 IST"
r1 = regexp.MustCompile(`.*"text"\s*:\s*"(Grafana v[^"]+)"`)
case "victorops_recv/victorops_test":
// It has a time component "timestamp".
r1 = regexp.MustCompile(`.*"timestamp"\s*:\s*([0-9]+)`)
case "v1/alerts":
// It has a changing time fields.
r1 = regexp.MustCompile(`.*"startsAt"\s*:\s*"([^"]+)"`)
r2 = regexp.MustCompile(`.*"UpdatedAt"\s*:\s*"([^"]+)"`)
}
if r1 != nil {
parts := r1.FindStringSubmatch(actVals[i])
require.Len(t, parts, 2)
if expKey == "v1/alerts" {
// 2 fields for Prometheus Alertmanager.
parts2 := r2.FindStringSubmatch(actVals[i])
require.Len(t, parts2, 2)
expVal = fmt.Sprintf(expVal, parts[1], parts2[1])
} else {
expVal = fmt.Sprintf(expVal, parts[1])
}
}
switch expKey {
case "line_recv/line_test", "threema_recv/threema_test":
// POST parameters.
require.Equal(t, expVal, actVals[i])
case "pushover_recv/pushover_test", "telegram_recv/bot6sh027hs034h":
// Multipart data.
multipartEqual(t, expVal, actVals[i])
default:
require.JSONEq(t, expVal, actVals[i])
}
}
}
}
func multipartEqual(t *testing.T, exp, act string) {
t.Helper()
fillMap := func(r *multipart.Reader, m map[string]string) {
for {
part, err := r.NextPart()
if part == nil || errors.Is(err, io.EOF) {
break
}
require.NoError(t, err)
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(part)
require.NoError(t, err)
m[part.FormName()] = buf.String()
}
}
expReader := multipart.NewReader(strings.NewReader(exp), channels.GetBoundary())
actReader := multipart.NewReader(strings.NewReader(act), channels.GetBoundary())
expMap, actMap := make(map[string]string), make(map[string]string)
fillMap(expReader, expMap)
fillMap(actReader, actMap)
require.Equal(t, expMap, actMap)
}
func (nc *mockNotificationChannel) Close() error {
return nc.server.Close()
}
type mockEmailHandler struct {
emails []*models.SendEmailCommandSync
}
func (e *mockEmailHandler) sendEmailCommandHandlerSync(_ context.Context, cmd *models.SendEmailCommandSync) error {
// We 0 out the start time since that is a variable that we cannot predict.
alerts := cmd.Data["Alerts"].(channels.ExtendedAlerts)
for i := range alerts {
alerts[i].StartsAt = time.Time{}
}
e.emails = append(e.emails, cmd)
return nil
}
// alertmanagerConfig has the config for all the notification channels
// that we want to test. It is recommended to use different URL for each
// channel and have 1 route per channel.
// group_wait 0s means the notification is sent as soon as it is received.
const alertmanagerConfig = `
{
"alertmanager_config": {
"route": {
"receiver": "slack_recv1",
"group_wait": "0s",
"group_by": [
"alertname"
],
"routes": [
{
"receiver": "email_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"EmailAlert\""
]
},
{
"receiver": "slack_recv1",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackAlert1\""
]
},
{
"receiver": "slack_recv2",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackAlert2\""
]
},
{
"receiver": "pagerduty_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"PagerdutyAlert\""
]
},
{
"receiver": "dingding_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"DingDingAlert\""
]
},
{
"receiver": "discord_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"DiscordAlert\""
]
},
{
"receiver": "sensugo_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SensuGoAlert\""
]
},
{
"receiver": "pushover_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"PushoverAlert\""
]
},
{
"receiver": "googlechat_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"GoogleChatAlert\""
]
},
{
"receiver": "kafka_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"KafkaAlert\""
]
},
{
"receiver": "line_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"LineAlert\""
]
},
{
"receiver": "threema_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"ThreemaAlert\""
]
},
{
"receiver": "opsgenie_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"OpsGenieAlert\""
]
},
{
"receiver": "alertmanager_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"AlertmanagerAlert\""
]
},
{
"receiver": "victorops_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"VictorOpsAlert\""
]
},
{
"receiver": "teams_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"TeamsAlert\""
]
},
{
"receiver": "webhook_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"WebhookAlert\""
]
},
{
"receiver": "telegram_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"TelegramAlert\""
]
}
]
},
"receivers": [
{
"name": "email_recv",
"grafana_managed_receiver_configs": [
{
"name": "email_test",
"type": "email",
"settings": {
"addresses": "test@email.com",
"singleEmail": true
}
}
]
},
{
"name": "dingding_recv",
"grafana_managed_receiver_configs": [
{
"name": "dingding_test",
"type": "dingding",
"settings": {
"url": "http://CHANNEL_ADDR/dingding_recv/dingding_test"
}
}
]
},
{
"name": "discord_recv",
"grafana_managed_receiver_configs": [
{
"name": "discord_test",
"type": "discord",
"settings": {
"url": "http://CHANNEL_ADDR/discord_recv/discord_test"
}
}
]
},
{
"name": "googlechat_recv",
"grafana_managed_receiver_configs": [
{
"name": "googlechat_test",
"type": "googlechat",
"settings": {
"url": "http://CHANNEL_ADDR/googlechat_recv/googlechat_test"
}
}
]
},
{
"name": "kafka_recv",
"grafana_managed_receiver_configs": [
{
"name": "kafka_test",
"type": "kafka",
"settings": {
"kafkaRestProxy": "http://CHANNEL_ADDR",
"kafkaTopic": "my_kafka_topic"
}
}
]
},
{
"name": "victorops_recv",
"grafana_managed_receiver_configs": [
{
"name": "victorops_test",
"type": "victorops",
"settings": {
"url": "http://CHANNEL_ADDR/victorops_recv/victorops_test"
}
}
]
},
{
"name": "teams_recv",
"grafana_managed_receiver_configs": [
{
"name": "teams_test",
"type": "teams",
"settings": {
"url": "http://CHANNEL_ADDR/teams_recv/teams_test"
}
}
]
},
{
"name": "webhook_recv",
"grafana_managed_receiver_configs": [
{
"name": "webhook_test",
"type": "webhook",
"settings": {
"url": "http://CHANNEL_ADDR/webhook_recv/webhook_test",
"username": "my_username",
"httpMethod": "POST",
"maxAlerts": "5"
},
"secureSettings": {
"password": "mysecretpassword"
}
}
]
},
{
"name": "sensugo_recv",
"grafana_managed_receiver_configs": [
{
"name": "sensugo_test",
"type": "sensugo",
"settings": {
"url": "http://CHANNEL_ADDR/sensugo_recv/sensugo_test",
"namespace": "sensugo"
},
"secureSettings": {
"apikey": "mysecretkey"
}
}
]
},
{
"name": "pushover_recv",
"grafana_managed_receiver_configs": [
{
"name": "pushover_test",
"type": "pushover",
"settings": {},
"secureSettings": {
"userKey": "mysecretkey",
"apiToken": "mysecrettoken"
}
}
]
},
{
"name": "line_recv",
"grafana_managed_receiver_configs": [
{
"name": "line_test",
"type": "line",
"settings": {},
"secureSettings": {
"token": "mysecrettoken"
}
}
]
},
{
"name": "threema_recv",
"grafana_managed_receiver_configs": [
{
"name": "threema_test",
"type": "threema",
"settings": {
"gateway_id": "*1234567",
"recipient_id": "abcdefgh"
},
"secureSettings": {
"api_secret": "myapisecret"
}
}
]
},
{
"name": "opsgenie_recv",
"grafana_managed_receiver_configs": [
{
"name": "opsgenie_test",
"type": "opsgenie",
"settings": {
"apiUrl": "http://CHANNEL_ADDR/opsgenie_recv/opsgenie_test"
},
"secureSettings": {
"apiKey": "mysecretkey"
}
}
]
},
{
"name": "alertmanager_recv",
"grafana_managed_receiver_configs": [
{
"name": "alertmanager_test",
"type": "prometheus-alertmanager",
"settings": {
"url": "http://CHANNEL_ADDR/alertmanager_recv/alertmanager_test"
},
"secureSettings": {}
}
]
},
{
"name": "telegram_recv",
"grafana_managed_receiver_configs": [
{
"name": "telegram_test",
"type": "telegram",
"settings": {
"chatid": "telegram_chat_id"
},
"secureSettings": {
"bottoken": "6sh027hs034h"
}
}
]
},
{
"name": "slack_recv1",
"grafana_managed_receiver_configs": [
{
"name": "slack_test_without_token",
"type": "slack",
"settings": {
"recipient": "#test-channel",
"mentionChannel": "here",
"mentionUsers": "user1, user2",
"mentionGroups": "group1, group2",
"username": "Integration Test",
"icon_emoji": "🚀",
"icon_url": "https://awesomeemoji.com/rocket",
"text": "Integration Test {{ template \"slack.default.text\" . }}",
"title": "Integration Test {{ template \"slack.default.title\" . }}",
"fallback": "Integration Test {{ template \"slack.default.title\" . }}"
},
"secureSettings": {
"url": "http://CHANNEL_ADDR/slack_recv1/slack_test_without_token"
}
}
]
},
{
"name": "slack_recv2",
"grafana_managed_receiver_configs": [
{
"name": "slack_test_with_token",
"type": "slack",
"settings": {
"recipient": "#test-channel",
"mentionUsers": "user1, user2",
"username": "Integration Test"
},
"secureSettings": {
"token": "myfullysecrettoken"
}
}
]
},
{
"name": "pagerduty_recv",
"grafana_managed_receiver_configs": [
{
"name": "pagerduty_test",
"type": "pagerduty",
"settings": {
"severity": "warning",
"class": "testclass",
"component": "Integration Test",
"group": "testgroup",
"summary": "Integration Test {{ template \"pagerduty.default.description\" . }}"
},
"secureSettings": {
"integrationKey": "pagerduty_recv/pagerduty_test"
}
}
]
}
]
}
}
`
var expAlertmanagerConfigFromAPI = `
{
"template_files": null,
"alertmanager_config": {
"route": {
"receiver": "slack_recv1",
"group_wait": "0s",
"group_by": [
"alertname"
],
"routes": [
{
"receiver": "email_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"EmailAlert\""
]
},
{
"receiver": "slack_recv1",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackAlert1\""
]
},
{
"receiver": "slack_recv2",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackAlert2\""
]
},
{
"receiver": "pagerduty_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"PagerdutyAlert\""
]
},
{
"receiver": "dingding_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"DingDingAlert\""
]
},
{
"receiver": "discord_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"DiscordAlert\""
]
},
{
"receiver": "sensugo_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SensuGoAlert\""
]
},
{
"receiver": "pushover_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"PushoverAlert\""
]
},
{
"receiver": "googlechat_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"GoogleChatAlert\""
]
},
{
"receiver": "kafka_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"KafkaAlert\""
]
},
{
"receiver": "line_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"LineAlert\""
]
},
{
"receiver": "threema_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"ThreemaAlert\""
]
},
{
"receiver": "opsgenie_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"OpsGenieAlert\""
]
},
{
"receiver": "alertmanager_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"AlertmanagerAlert\""
]
},
{
"receiver": "victorops_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"VictorOpsAlert\""
]
},
{
"receiver": "teams_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"TeamsAlert\""
]
},
{
"receiver": "webhook_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"WebhookAlert\""
]
},
{
"receiver": "telegram_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"TelegramAlert\""
]
}
]
},
"templates": null,
"receivers": [
{
"name": "email_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "email_test",
"type": "email",
"disableResolveMessage": false,
"settings": {
"addresses": "test@email.com",
"singleEmail": true
},
"secureFields": {}
}
]
},
{
"name": "dingding_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "dingding_test",
"type": "dingding",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/dingding_recv/dingding_test"
},
"secureFields": {}
}
]
},
{
"name": "discord_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "discord_test",
"type": "discord",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/discord_recv/discord_test"
},
"secureFields": {}
}
]
},
{
"name": "googlechat_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "googlechat_test",
"type": "googlechat",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/googlechat_recv/googlechat_test"
},
"secureFields": {}
}
]
},
{
"name": "kafka_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "kafka_test",
"type": "kafka",
"disableResolveMessage": false,
"settings": {
"kafkaRestProxy": "http://CHANNEL_ADDR",
"kafkaTopic": "my_kafka_topic"
},
"secureFields": {}
}
]
},
{
"name": "victorops_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "victorops_test",
"type": "victorops",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/victorops_recv/victorops_test"
},
"secureFields": {}
}
]
},
{
"name": "teams_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "teams_test",
"type": "teams",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/teams_recv/teams_test"
},
"secureFields": {}
}
]
},
{
"name": "webhook_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "webhook_test",
"type": "webhook",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/webhook_recv/webhook_test",
"username": "my_username",
"httpMethod": "POST",
"maxAlerts": "5"
},
"secureFields": {
"password": true
}
}
]
},
{
"name": "sensugo_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "sensugo_test",
"type": "sensugo",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/sensugo_recv/sensugo_test",
"namespace": "sensugo"
},
"secureFields": {
"apikey": true
}
}
]
},
{
"name": "pushover_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "pushover_test",
"type": "pushover",
"disableResolveMessage": false,
"settings": {},
"secureFields": {
"userKey": true,
"apiToken": true
}
}
]
},
{
"name": "line_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "line_test",
"type": "line",
"disableResolveMessage": false,
"settings": {},
"secureFields": {
"token": true
}
}
]
},
{
"name": "threema_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "threema_test",
"type": "threema",
"disableResolveMessage": false,
"settings": {
"gateway_id": "*1234567",
"recipient_id": "abcdefgh"
},
"secureFields": {
"api_secret": true
}
}
]
},
{
"name": "opsgenie_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "opsgenie_test",
"type": "opsgenie",
"disableResolveMessage": false,
"settings": {
"apiUrl": "http://CHANNEL_ADDR/opsgenie_recv/opsgenie_test"
},
"secureFields": {
"apiKey": true
}
}
]
},
{
"name": "alertmanager_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "alertmanager_test",
"type": "prometheus-alertmanager",
"disableResolveMessage": false,
"settings": {
"url": "http://CHANNEL_ADDR/alertmanager_recv/alertmanager_test"
},
"secureFields": {}
}
]
},
{
"name": "telegram_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "telegram_test",
"type": "telegram",
"disableResolveMessage": false,
"settings": {
"chatid": "telegram_chat_id"
},
"secureFields": {
"bottoken": true
}
}
]
},
{
"name": "slack_recv1",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "slack_test_without_token",
"type": "slack",
"disableResolveMessage": false,
"settings": {
"fallback": "Integration Test {{ template \"slack.default.title\" . }}",
"icon_emoji": "🚀",
"icon_url": "https://awesomeemoji.com/rocket",
"mentionChannel": "here",
"mentionGroups": "group1, group2",
"mentionUsers": "user1, user2",
"recipient": "#test-channel",
"text": "Integration Test {{ template \"slack.default.text\" . }}",
"title": "Integration Test {{ template \"slack.default.title\" . }}",
"username": "Integration Test"
},
"secureFields": {
"url": true
}
}
]
},
{
"name": "slack_recv2",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "slack_test_with_token",
"type": "slack",
"disableResolveMessage": false,
"settings": {
"mentionUsers": "user1, user2",
"recipient": "#test-channel",
"username": "Integration Test"
},
"secureFields": {
"token": true
}
}
]
},
{
"name": "pagerduty_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "pagerduty_test",
"type": "pagerduty",
"disableResolveMessage": false,
"settings": {
"class": "testclass",
"component": "Integration Test",
"group": "testgroup",
"severity": "warning",
"summary": "Integration Test {{ template \"pagerduty.default.description\" . }}"
},
"secureFields": {
"integrationKey": true
}
}
]
}
]
}
}
`
var expEmailNotifications = []*models.SendEmailCommandSync{
{
SendEmailCommand: models.SendEmailCommand{
To: []string{"test@email.com"},
SingleEmail: true,
Email: Allow configuration of content types for email notifications (#34530) * Alerting: Allow configuration of content types for email notifications * Fix lint error * Improves email templates * Improve configuration documentation Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve code comments Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve configuration documentation Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve email template * Remove unnecessary predeclaration Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Adds handling for unrecognized content type Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Move utility function outside of util package * Fixes syntax * Remove unused package * Fix lint error * improve email templates * Fix test * Alerting: Allow configuration of content types for email notifications * Fix lint error * Improves email templates * Improve configuration documentation Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve code comments Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve configuration documentation Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * Improve email template * Remove unnecessary predeclaration Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Adds handling for unrecognized content type Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Move utility function outside of util package * Fixes syntax * Remove unused package * Fix lint error * improve email templates * Fix test * Fix comment style Co-authored-by: Ganesh Vernekar <15064823+codesome@users.noreply.github.com> * Fix template formatting * Add test and improve error handling * Fix test * Fix formatting * Fix formatting * Improve documentation and regenerates txt template * Update docs/sources/administration/configuration.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: Djairho Geuens <djairho.geuens@ae.be> Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ganesh Vernekar <15064823+codesome@users.noreply.github.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
4 years ago
Template: "ng_alert_notification",
Subject: "[FIRING:1] EmailAlert ",
Data: map[string]interface{}{
"Title": "[FIRING:1] EmailAlert ",
"Message": "",
"Status": "firing",
"Alerts": channels.ExtendedAlerts{
{
Status: "firing",
Labels: template.KV{"alertname": "EmailAlert"},
Annotations: template.KV{},
StartsAt: time.Time{},
EndsAt: time.Time{},
GeneratorURL: "http://localhost:3000/alerting/UID_EmailAlert/edit",
Fingerprint: "08c220aa26cd0cf5",
SilenceURL: "http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DEmailAlert",
DashboardURL: "",
PanelURL: "",
ValueString: "[ var='A' labels={} value=1 ]",
},
},
"GroupLabels": template.KV{"alertname": "EmailAlert"},
"CommonLabels": template.KV{"alertname": "EmailAlert"},
"CommonAnnotations": template.KV{},
"ExternalURL": "http://localhost:3000/",
"RuleUrl": "http://localhost:3000/alerting/list",
"AlertPageUrl": "http://localhost:3000/alerting/list?alertState=firing&view=state",
},
},
},
}
// expNonEmailNotifications is all the expected notifications (except email).
// The key for the map is taken from the URL. The last 2 components of URL
// split with "/" forms the key for that route.
var expNonEmailNotifications = map[string][]string{
"slack_recv1/slack_test_without_token": {
`{
"channel": "#test-channel",
"username": "Integration Test",
"icon_emoji": "🚀",
"icon_url": "https://awesomeemoji.com/rocket",
"attachments": [
{
"title": "Integration Test [FIRING:1] SlackAlert1 ",
"title_link": "http://localhost:3000/alerting/list",
"text": "Integration Test ",
"fallback": "Integration Test [FIRING:1] SlackAlert1 ",
"footer": "Grafana v",
"footer_icon": "https://grafana.com/assets/img/fav32.png",
"color": "#D63232",
"ts": %s
}
],
"blocks": [
{
"text": {
"text": "<!here|here> <!subteam^group1><!subteam^group2> <@user1><@user2>",
"type": "mrkdwn"
},
"type": "section"
}
]
}`,
},
"slack_recvX/slack_testX": {
`{
"channel": "#test-channel",
"username": "Integration Test",
"attachments": [
{
"title": "[FIRING:1] SlackAlert2 ",
"title_link": "http://localhost:3000/alerting/list",
"text": "**Firing**\n\nLabels:\n - alertname = SlackAlert2\nAnnotations:\nSource: http://localhost:3000/alerting/UID_SlackAlert2/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DSlackAlert2\n",
"fallback": "[FIRING:1] SlackAlert2 ",
"footer": "Grafana v",
"footer_icon": "https://grafana.com/assets/img/fav32.png",
"color": "#D63232",
"ts": %s
}
],
"blocks": [
{
"text": {
"text": "<@user1><@user2>",
"type": "mrkdwn"
},
"type": "section"
}
]
}`,
},
"pagerduty_recvX/pagerduty_testX": {
`{
"routing_key": "pagerduty_recv/pagerduty_test",
"dedup_key": "234edb34441f942f713f3c2ccf58b1d719d921b4cbe34e57a1630f1dee847e3b",
"description": "[FIRING:1] PagerdutyAlert ",
"event_action": "trigger",
"payload": {
"summary": "Integration Test [FIRING:1] PagerdutyAlert ",
"source": "%s",
"severity": "warning",
"class": "testclass",
"component": "Integration Test",
"group": "testgroup",
"custom_details": {
"firing": "\nLabels:\n - alertname = PagerdutyAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_PagerdutyAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DPagerdutyAlert\n",
"num_firing": "1",
"num_resolved": "0",
"resolved": ""
}
},
"client": "Grafana",
"client_url": "http://localhost:3000/",
"links": [
{
"href": "http://localhost:3000/",
"text": "External URL"
}
]
}`,
},
"dingding_recv/dingding_test": {
`{
"link": {
"messageUrl": "dingtalk://dingtalkclient/page/link?pc_slide=false&url=http%3A%2F%2Flocalhost%3A3000%2Falerting%2Flist",
"text": "**Firing**\n\nLabels:\n - alertname = DingDingAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_DingDingAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DDingDingAlert\n",
"title": "[FIRING:1] DingDingAlert "
},
"msgtype": "link"
}`,
},
"teams_recv/teams_test": {
`{
"@context": "http://schema.org/extensions",
"@type": "MessageCard",
"potentialAction": [
{
"@context": "http://schema.org",
"@type": "OpenUri",
"name": "View Rule",
"targets": [
{
"os": "default",
"uri": "http://localhost:3000/alerting/list"
}
]
}
],
"sections": [
{
"text": "**Firing**\n\nLabels:\n - alertname = TeamsAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_TeamsAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DTeamsAlert\n",
"title": "Details"
}
],
"summary": "[FIRING:1] TeamsAlert ",
"themeColor": "#D63232",
"title": "[FIRING:1] TeamsAlert "
}`,
},
"webhook_recv/webhook_test": {
`{
"receiver": "webhook_recv",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "WebhookAlert"
},
"annotations": {},
"startsAt": "%s",
"valueString": "[ var='A' labels={} value=1 ]",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://localhost:3000/alerting/UID_WebhookAlert/edit",
"fingerprint": "929467973978d053",
"silenceURL": "http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DWebhookAlert",
"dashboardURL": "",
"panelURL": ""
}
],
"groupLabels": {
"alertname": "WebhookAlert"
},
"commonLabels": {
"alertname": "WebhookAlert"
},
"commonAnnotations": {},
"externalURL": "http://localhost:3000/",
"version": "1",
"groupKey": "{}/{alertname=\"WebhookAlert\"}:{alertname=\"WebhookAlert\"}",
"truncatedAlerts": 0,
"title": "[FIRING:1] WebhookAlert ",
"state": "alerting",
"message": "**Firing**\n\nLabels:\n - alertname = WebhookAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_WebhookAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DWebhookAlert\n"
}`,
},
"discord_recv/discord_test": {
`{
"content": "**Firing**\n\nLabels:\n - alertname = DiscordAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_DiscordAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DDiscordAlert\n",
"embeds": [
{
"color": 14037554,
"footer": {
"icon_url": "https://grafana.com/assets/img/fav32.png",
"text": "Grafana v"
},
"title": "[FIRING:1] DiscordAlert ",
"type": "rich",
"url": "http://localhost:3000/alerting/list"
}
],
"username": "Grafana"
}`,
},
"sensugo/events": {
`{
"check": {
"handlers": null,
"interval": 86400,
"issued": %s,
"metadata": {
"labels": {
"ruleURL": "http://localhost:3000/alerting/list"
},
"name": "default"
},
"output": "**Firing**\n\nLabels:\n - alertname = SensuGoAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_SensuGoAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DSensuGoAlert\n",
"status": 2
},
"entity": {
"metadata": {
"name": "default",
"namespace": "sensugo"
}
},
"ruleUrl": "http://localhost:3000/alerting/list"
}`,
},
"pushover_recv/pushover_test": {
"--abcd\r\nContent-Disposition: form-data; name=\"user\"\r\n\r\nmysecretkey\r\n--abcd\r\nContent-Disposition: form-data; name=\"token\"\r\n\r\nmysecrettoken\r\n--abcd\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n0\r\n--abcd\r\nContent-Disposition: form-data; name=\"sound\"\r\n\r\n\r\n--abcd\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\n[FIRING:1] PushoverAlert \r\n--abcd\r\nContent-Disposition: form-data; name=\"url\"\r\n\r\nhttp://localhost:3000/alerting/list\r\n--abcd\r\nContent-Disposition: form-data; name=\"url_title\"\r\n\r\nShow alert rule\r\n--abcd\r\nContent-Disposition: form-data; name=\"message\"\r\n\r\n**Firing**\n\nLabels:\n - alertname = PushoverAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_PushoverAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DPushoverAlert\n\r\n--abcd\r\nContent-Disposition: form-data; name=\"html\"\r\n\r\n1\r\n--abcd--\r\n",
},
"telegram_recv/bot6sh027hs034h": {
"--abcd\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\ntelegram_chat_id\r\n--abcd\r\nContent-Disposition: form-data; name=\"parse_mode\"\r\n\r\nhtml\r\n--abcd\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\n**Firing**\n\nLabels:\n - alertname = TelegramAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_TelegramAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DTelegramAlert\n\r\n--abcd--\r\n",
},
"googlechat_recv/googlechat_test": {
`{
"previewText": "[FIRING:1] GoogleChatAlert ",
"fallbackText": "[FIRING:1] GoogleChatAlert ",
"cards": [
{
"header": {
"title": "[FIRING:1] GoogleChatAlert "
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": "**Firing**\n\nLabels:\n - alertname = GoogleChatAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_GoogleChatAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DGoogleChatAlert\n"
}
},
{
"buttons": [
{
"textButton": {
"text": "OPEN IN GRAFANA",
"onClick": {
"openLink": {
"url": "http://localhost:3000/alerting/list"
}
}
}
}
]
},
{
"textParagraph": {
"text": "%s"
}
}
]
}
]
}
]
}`,
},
"topics/my_kafka_topic": {
`{
"records": [
{
"value": {
"alert_state": "alerting",
"client": "Grafana",
"client_url": "http://localhost:3000/alerting/list",
"description": "[FIRING:1] KafkaAlert ",
"details": "**Firing**\n\nLabels:\n - alertname = KafkaAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_KafkaAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DKafkaAlert\n",
"incident_key": "35c0bdb1715f9162a20d7b2a01cb2e3a4c5b1dc663571701e3f67212b696332f"
}
}
]
}`,
},
"line_recv/line_test": {
`message=%5BFIRING%3A1%5D+LineAlert+%0Ahttp%3A%2Flocalhost%3A3000%2Falerting%2Flist%0A%0A%2A%2AFiring%2A%2A%0A%0ALabels%3A%0A+-+alertname+%3D+LineAlert%0AAnnotations%3A%0ASource%3A+http%3A%2F%2Flocalhost%3A3000%2Falerting%2FUID_LineAlert%2Fedit%0ASilence%3A+http%3A%2F%2Flocalhost%3A3000%2Falerting%2Fsilence%2Fnew%3Falertmanager%3Dgrafana%26matchers%3Dalertname%253DLineAlert%0A`,
},
"threema_recv/threema_test": {
`from=%2A1234567&secret=myapisecret&text=%E2%9A%A0%EF%B8%8F+%5BFIRING%3A1%5D+ThreemaAlert+%0A%0A%2AMessage%3A%2A%0A%2A%2AFiring%2A%2A%0A%0ALabels%3A%0A+-+alertname+%3D+ThreemaAlert%0AAnnotations%3A%0ASource%3A+http%3A%2F%2Flocalhost%3A3000%2Falerting%2FUID_ThreemaAlert%2Fedit%0ASilence%3A+http%3A%2F%2Flocalhost%3A3000%2Falerting%2Fsilence%2Fnew%3Falertmanager%3Dgrafana%26matchers%3Dalertname%253DThreemaAlert%0A%0A%2AURL%3A%2A+http%3A%2Flocalhost%3A3000%2Falerting%2Flist%0A&to=abcdefgh`,
},
"victorops_recv/victorops_test": {
`{
"alert_url": "http://localhost:3000/alerting/list",
"entity_display_name": "[FIRING:1] VictorOpsAlert ",
"entity_id": "633ae988fa7074bcb51f3d1c5fef2ba1c5c4ccb45b3ecbf681f7d507b078b1ae",
"message_type": "CRITICAL",
"monitoring_tool": "Grafana v",
"state_message": "**Firing**\n\nLabels:\n - alertname = VictorOpsAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_VictorOpsAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%%3DVictorOpsAlert\n",
"timestamp": %s
}`,
},
"opsgenie_recv/opsgenie_test": {
`{
"alias": "47e92f0f6ef9fe99f3954e0d6155f8d09c4b9a038d8c3105e82c0cee4c62956e",
"description": "[FIRING:1] OpsGenieAlert \nhttp://localhost:3000/alerting/list\n\n**Firing**\n\nLabels:\n - alertname = OpsGenieAlert\nAnnotations:\nSource: http://localhost:3000/alerting/UID_OpsGenieAlert/edit\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DOpsGenieAlert\n",
"details": {
"url": "http://localhost:3000/alerting/list"
},
"message": "[FIRING:1] OpsGenieAlert ",
"source": "Grafana",
"tags": ["alertname:OpsGenieAlert"]
}`,
},
// Prometheus Alertmanager.
"v1/alerts": {
`[
{
"labels": {
"__alert_rule_uid__": "UID_AlertmanagerAlert",
"alertname": "AlertmanagerAlert"
},
"annotations": {
"__value_string__": "[ var='A' labels={} value=1 ]"
},
"startsAt": "%s",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://localhost:3000/alerting/UID_AlertmanagerAlert/edit",
"UpdatedAt": "%s",
"Timeout": false
}
]`,
},
}