Alerting: Support custom annotations and labels when testing contact points

Support custom annotations and labels when testing contact points
This commit is contained in:
George Robinson 2021-10-21 13:47:06 +01:00 committed by GitHub
parent 3abb355364
commit 967721068e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 591 additions and 130 deletions

View File

@ -444,8 +444,12 @@ func contextWithTimeoutFromRequest(ctx context.Context, r *http.Request, default
func newTestReceiversResult(r *notifier.TestReceiversResult) apimodels.TestReceiversResult {
v := apimodels.TestReceiversResult{
Receivers: make([]apimodels.TestReceiverResult, len(r.Receivers)),
NotifedAt: r.NotifedAt,
Alert: apimodels.TestReceiversConfigAlertParams{
Annotations: r.Alert.Annotations,
Labels: r.Alert.Labels,
},
Receivers: make([]apimodels.TestReceiverResult, len(r.Receivers)),
NotifiedAt: r.NotifedAt,
}
for ix, next := range r.Receivers {
configs := make([]apimodels.TestReceiverConfigResult, len(next.Configs))

View File

@ -137,6 +137,8 @@ type MultiStatus struct{}
// swagger:parameters RoutePostTestReceivers
type TestReceiversConfigParams struct {
// in:body
Alert *TestReceiversConfigAlertParams `yaml:"alert,omitempty" json:"alert,omitempty"`
// in:body
Receivers []*PostableApiReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
}
@ -145,10 +147,16 @@ func (c *TestReceiversConfigParams) ProcessConfig(encrypt EncryptFn) error {
return processReceiverConfigs(c.Receivers, encrypt)
}
type TestReceiversConfigAlertParams struct {
Annotations model.LabelSet `yaml:"annotations,omitempty" json:"annotations,omitempty"`
Labels model.LabelSet `yaml:"labels,omitempty" json:"labels,omitempty"`
}
// swagger:model
type TestReceiversResult struct {
Receivers []TestReceiverResult `json:"receivers"`
NotifedAt time.Time `json:"notified_at"`
Alert TestReceiversConfigAlertParams `json:"alert"`
Receivers []TestReceiverResult `json:"receivers"`
NotifiedAt time.Time `json:"notified_at"`
}
// swagger:model

View File

@ -1065,6 +1065,19 @@
"type": "array",
"x-go-package": "github.com/prometheus/common/model"
},
"LabelSet": {
"additionalProperties": {
"$ref": "#/definitions/LabelValue"
},
"description": "A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet\nmay be fully-qualified down to the point where it may resolve to a single\nMetric in the data store or not. All operations that occur within the realm\nof a LabelSet can emit a vector of Metric entities to which the LabelSet may\nmatch.",
"type": "object",
"x-go-package": "github.com/prometheus/common/model"
},
"LabelValue": {
"title": "A LabelValue is an associated value for a LabelName.",
"type": "string",
"x-go-package": "github.com/prometheus/common/model"
},
"Labels": {
"description": "Labels is a sorted set of labels. Order has to be guaranteed upon\ninstantiation.",
"items": {
@ -2403,12 +2416,27 @@
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"TestReceiversConfigAlertParams": {
"properties": {
"annotations": {
"$ref": "#/definitions/LabelSet"
},
"labels": {
"$ref": "#/definitions/LabelSet"
}
},
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"TestReceiversResult": {
"properties": {
"alert": {
"$ref": "#/definitions/TestReceiversConfigAlertParams"
},
"notified_at": {
"format": "date-time",
"type": "string",
"x-go-name": "NotifedAt"
"x-go-name": "NotifiedAt"
},
"receivers": {
"items": {
@ -2649,6 +2677,7 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@ -2670,9 +2699,7 @@
"labels",
"receiver"
],
"type": "object",
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
"type": "object"
},
"alertGroups": {
"items": {
@ -2869,7 +2896,6 @@
"type": "array"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"properties": {
"comment": {
"description": "comment",
@ -2921,14 +2947,17 @@
"status",
"updatedAt"
],
"type": "object"
"type": "object",
"x-go-name": "GettableSilence",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"type": "array"
"type": "array",
"x-go-name": "GettableSilences",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"labelSet": {
"additionalProperties": {
@ -3101,7 +3130,6 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"receiver": {
"description": "Receiver receiver",
"properties": {
"name": {
"description": "name",
@ -3112,7 +3140,9 @@
"required": [
"name"
],
"type": "object"
"type": "object",
"x-go-name": "Receiver",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"silence": {
"description": "Silence silence",
@ -3699,6 +3729,14 @@
"post": {
"operationId": "RoutePostTestReceivers",
"parameters": [
{
"in": "body",
"name": "alert",
"schema": {
"$ref": "#/definitions/TestReceiversConfigAlertParams"
},
"x-go-name": "Alert"
},
{
"in": "body",
"name": "receivers",

View File

@ -493,6 +493,14 @@
"summary": "Test Grafana managed receivers without saving them.",
"operationId": "RoutePostTestReceivers",
"parameters": [
{
"x-go-name": "Alert",
"name": "alert",
"in": "body",
"schema": {
"$ref": "#/definitions/TestReceiversConfigAlertParams"
}
},
{
"x-go-name": "Receivers",
"name": "receivers",
@ -2090,6 +2098,19 @@
},
"x-go-package": "github.com/prometheus/common/model"
},
"LabelSet": {
"description": "A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet\nmay be fully-qualified down to the point where it may resolve to a single\nMetric in the data store or not. All operations that occur within the realm\nof a LabelSet can emit a vector of Metric entities to which the LabelSet may\nmatch.",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/LabelValue"
},
"x-go-package": "github.com/prometheus/common/model"
},
"LabelValue": {
"type": "string",
"title": "A LabelValue is an associated value for a LabelName.",
"x-go-package": "github.com/prometheus/common/model"
},
"Labels": {
"description": "Labels is a sorted set of labels. Order has to be guaranteed upon\ninstantiation.",
"type": "array",
@ -3429,13 +3450,28 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"TestReceiversConfigAlertParams": {
"type": "object",
"properties": {
"annotations": {
"$ref": "#/definitions/LabelSet"
},
"labels": {
"$ref": "#/definitions/LabelSet"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"TestReceiversResult": {
"type": "object",
"properties": {
"alert": {
"$ref": "#/definitions/TestReceiversConfigAlertParams"
},
"notified_at": {
"type": "string",
"format": "date-time",
"x-go-name": "NotifedAt"
"x-go-name": "NotifiedAt"
},
"receivers": {
"type": "array",
@ -3675,6 +3711,7 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"type": "object",
"required": [
"alerts",
@ -3697,8 +3734,6 @@
"$ref": "#/definitions/receiver"
}
},
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/alertGroup"
},
"alertGroups": {
@ -3899,7 +3934,6 @@
"$ref": "#/definitions/gettableAlerts"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"type": "object",
"required": [
"comment",
@ -3952,14 +3986,17 @@
"x-go-name": "UpdatedAt"
}
},
"x-go-name": "GettableSilence",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/gettableSilence"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"x-go-name": "GettableSilences",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/gettableSilences"
},
"labelSet": {
@ -4134,7 +4171,6 @@
"$ref": "#/definitions/postableSilence"
},
"receiver": {
"description": "Receiver receiver",
"type": "object",
"required": [
"name"
@ -4146,6 +4182,8 @@
"x-go-name": "Name"
}
},
"x-go-name": "Receiver",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/receiver"
},
"silence": {

View File

@ -24,6 +24,7 @@ var (
)
type TestReceiversResult struct {
Alert types.Alert
Receivers []TestReceiverResult
NotifedAt time.Time
}
@ -61,19 +62,7 @@ func (e ReceiverTimeoutError) Error() string {
func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigParams) (*TestReceiversResult, error) {
// now represents the start time of the test
now := time.Now()
testAlert := &types.Alert{
Alert: model.Alert{
Labels: model.LabelSet{
model.LabelName("alertname"): "TestAlert",
model.LabelName("instance"): "Grafana",
},
Annotations: model.LabelSet{
model.LabelName("summary"): "Notification test",
},
StartsAt: now,
},
UpdatedAt: now,
}
testAlert := newTestAlert(c, now, now)
// we must set a group key that is unique per test as some receivers use this key to deduplicate alerts
ctx = notify.WithGroupKey(ctx, testAlert.Labels.String()+now.String())
@ -97,7 +86,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
Error error
}
newTestReceiversResult := func(results []result, notifiedAt time.Time) *TestReceiversResult {
newTestReceiversResult := func(alert types.Alert, results []result, notifiedAt time.Time) *TestReceiversResult {
m := make(map[string]TestReceiverResult)
for _, receiver := range c.Receivers {
// set up the result for this receiver
@ -122,6 +111,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
m[next.ReceiverName] = tmp
}
v := new(TestReceiversResult)
v.Alert = alert
v.Receivers = make([]TestReceiverResult, 0, len(c.Receivers))
v.NotifedAt = notifiedAt
for _, next := range m {
@ -165,7 +155,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
}
if len(jobs) == 0 {
return newTestReceiversResult(invalid, now), nil
return newTestReceiversResult(testAlert, invalid, now), nil
}
numWorkers := maxTestReceiversWorkers
@ -188,7 +178,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
Config: next.Config,
ReceiverName: next.ReceiverName,
}
if _, err := next.Notifier.Notify(ctx, testAlert); err != nil {
if _, err := next.Notifier.Notify(ctx, &testAlert); err != nil {
v.Error = err
}
resultCh <- v
@ -204,7 +194,43 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
results = append(results, next)
}
return newTestReceiversResult(append(invalid, results...), now), nil
return newTestReceiversResult(testAlert, append(invalid, results...), now), nil
}
func newTestAlert(c apimodels.TestReceiversConfigParams, startsAt, updatedAt time.Time) types.Alert {
var (
defaultAnnotations = model.LabelSet{
"summary": "Notification test",
}
defaultLabels = model.LabelSet{
"alertname": "TestAlert",
"instance": "Grafana",
}
)
alert := types.Alert{
Alert: model.Alert{
Labels: defaultLabels,
Annotations: defaultAnnotations,
StartsAt: startsAt,
},
UpdatedAt: updatedAt,
}
if c.Alert != nil {
if c.Alert.Annotations != nil {
for k, v := range c.Alert.Annotations {
alert.Annotations[k] = v
}
}
if c.Alert.Labels != nil {
for k, v := range c.Alert.Labels {
alert.Labels[k] = v
}
}
}
return alert
}
func processNotifierError(config *apimodels.PostableGrafanaReceiver, err error) error {

View File

@ -92,14 +92,14 @@ func TestTestReceivers(t *testing.T) {
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{
"uid": "",
"name": "receiver-1",
"type": "email",
"disableResolveMessage": false,
"settings": {
"addresses":"example@email.com"
},
"secureFields":{}
"secureFields": {}
}
]
}]
@ -109,22 +109,39 @@ func TestTestReceivers(t *testing.T) {
require.NoError(t, err)
})
var result apimodels.TestReceiversResult
require.NoError(t, json.NewDecoder(resp.Body).Decode(&result))
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
require.Equal(t, apimodels.TestReceiversResult{
Receivers: []apimodels.TestReceiverResult{{
Name: "receiver-1",
Configs: []apimodels.TestReceiverConfigResult{{
Name: "receiver-1",
UID: result.Receivers[0].Configs[0].UID,
Status: "ok",
}},
}},
NotifedAt: result.NotifedAt,
}, result)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "Notification test"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "ok"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
require.Len(t, mockEmails.emails, 1)
require.Equal(t, []string{"example@email.com"}, mockEmails.emails[0].To)
@ -160,38 +177,54 @@ func TestTestReceivers(t *testing.T) {
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{},
"secureFields":{}
"uid": "",
"name": "receiver-1",
"type": "email",
"disableResolveMessage": false,
"settings": {},
"secureFields": {}
}
]
}]
}`, http.StatusBadRequest)
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, resp.Body.Close())
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
require.Equal(t, apimodels.TestReceiversResult{
Receivers: []apimodels.TestReceiverResult{{
Name: "receiver-1",
Configs: []apimodels.TestReceiverConfigResult{{
Name: "receiver-1",
UID: result.Receivers[0].Configs[0].UID,
Status: "failed",
Error: "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings",
}},
}},
NotifedAt: result.NotifedAt,
}, result)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "Notification test"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "failed",
"error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
})
t.Run("assert timed out receiver returns 408 Request Timeout", func(t *testing.T) {
@ -225,14 +258,14 @@ func TestTestReceivers(t *testing.T) {
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{
"uid": "",
"name": "receiver-1",
"type": "email",
"disableResolveMessage": false,
"settings": {
"addresses":"example@email.com"
},
"secureFields":{}
"secureFields": {}
}
]
}]
@ -248,23 +281,40 @@ func TestTestReceivers(t *testing.T) {
})
require.Equal(t, http.StatusRequestTimeout, resp.StatusCode)
var result apimodels.TestReceiversResult
require.NoError(t, json.NewDecoder(resp.Body).Decode(&result))
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
require.Equal(t, apimodels.TestReceiversResult{
Receivers: []apimodels.TestReceiverResult{{
Name: "receiver-1",
Configs: []apimodels.TestReceiverConfigResult{{
Name: "receiver-1",
UID: result.Receivers[0].Configs[0].UID,
Status: "failed",
Error: "the receiver timed out: context deadline exceeded",
}},
}},
NotifedAt: result.NotifedAt,
}, result)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "Notification test"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "failed",
"error": "the receiver timed out: context deadline exceeded"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
})
t.Run("assert multiple different errors returns 207 Multi Status", func(t *testing.T) {
@ -298,26 +348,26 @@ func TestTestReceivers(t *testing.T) {
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{},
"secureFields":{}
"uid": "",
"name": "receiver-1",
"type": "email",
"disableResolveMessage": false,
"settings": {},
"secureFields": {}
}
]
}, {
"name":"receiver-2",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-2",
"type":"email",
"disableResolveMessage":false,
"settings":{
"uid": "",
"name": "receiver-2",
"type": "email",
"disableResolveMessage": false,
"settings": {
"addresses":"example@email.com"
},
"secureFields":{}
"secureFields": {}
}
]
}]
@ -333,32 +383,329 @@ func TestTestReceivers(t *testing.T) {
})
require.Equal(t, http.StatusMultiStatus, resp.StatusCode)
var result apimodels.TestReceiversResult
require.NoError(t, json.NewDecoder(resp.Body).Decode(&result))
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 2)
require.Len(t, result.Receivers[0].Configs, 1)
require.Len(t, result.Receivers[1].Configs, 1)
require.Equal(t, apimodels.TestReceiversResult{
Receivers: []apimodels.TestReceiverResult{{
Name: "receiver-1",
Configs: []apimodels.TestReceiverConfigResult{{
Name: "receiver-1",
UID: result.Receivers[0].Configs[0].UID,
Status: "failed",
Error: "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings",
}},
}, {
Name: "receiver-2",
Configs: []apimodels.TestReceiverConfigResult{{
Name: "receiver-2",
UID: result.Receivers[1].Configs[0].UID,
Status: "failed",
Error: "the receiver timed out: context deadline exceeded",
}},
}},
NotifedAt: result.NotifedAt,
}, result)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "Notification test"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "failed",
"error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings"
}
]
}, {
"name":"receiver-2",
"grafana_managed_receiver_configs": [
{
"name": "receiver-2",
"uid": "%s",
"status": "failed",
"error": "the receiver timed out: context deadline exceeded"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.Receivers[1].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
})
}
func TestTestReceiversAlertCustomization(t *testing.T) {
t.Run("assert custom annotations and labels are sent", func(t *testing.T) {
// Setup Grafana and its Database
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
DisableLegacyAlerting: true,
EnableUnifiedAlerting: true,
})
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
store.Bus = bus.GetBus()
createUser(t, store, models.CreateUserCommand{
DefaultOrgRole: string(models.ROLE_EDITOR),
Login: "grafana",
Password: "password",
})
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
mockEmails := &mockEmailHandler{}
bus.AddHandlerCtx("", mockEmails.sendEmailCommandHandlerSync)
t.Cleanup(func() {
bus.AddHandlerCtx("", oldEmailBus)
})
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
// nolint
resp := postRequest(t, testReceiversURL, `{
"alert": {
"annotations": {
"annotation1": "value1"
},
"labels": {
"label1": "value1"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{
"addresses":"example@email.com"
},
"secureFields":{}
}
]
}]
}`, http.StatusOK)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"annotation1": "value1",
"summary": "Notification test"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana",
"label1": "value1"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "ok"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
require.Len(t, mockEmails.emails, 1)
require.Equal(t, []string{"example@email.com"}, mockEmails.emails[0].To)
})
t.Run("assert custom annotations can replace default annotations", func(t *testing.T) {
// Setup Grafana and its Database
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
DisableLegacyAlerting: true,
EnableUnifiedAlerting: true,
})
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
store.Bus = bus.GetBus()
createUser(t, store, models.CreateUserCommand{
DefaultOrgRole: string(models.ROLE_EDITOR),
Login: "grafana",
Password: "password",
})
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
mockEmails := &mockEmailHandler{}
bus.AddHandlerCtx("", mockEmails.sendEmailCommandHandlerSync)
t.Cleanup(func() {
bus.AddHandlerCtx("", oldEmailBus)
})
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
// nolint
resp := postRequest(t, testReceiversURL, `{
"alert": {
"annotations": {
"summary": "This is a custom annotation"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{
"addresses":"example@email.com"
},
"secureFields":{}
}
]
}]
}`, http.StatusOK)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "This is a custom annotation"
},
"labels": {
"alertname": "TestAlert",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "ok"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
require.Len(t, mockEmails.emails, 1)
require.Equal(t, []string{"example@email.com"}, mockEmails.emails[0].To)
})
t.Run("assert custom labels can replace default label", func(t *testing.T) {
// Setup Grafana and its Database
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
DisableLegacyAlerting: true,
EnableUnifiedAlerting: true,
})
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
store.Bus = bus.GetBus()
createUser(t, store, models.CreateUserCommand{
DefaultOrgRole: string(models.ROLE_EDITOR),
Login: "grafana",
Password: "password",
})
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
mockEmails := &mockEmailHandler{}
bus.AddHandlerCtx("", mockEmails.sendEmailCommandHandlerSync)
t.Cleanup(func() {
bus.AddHandlerCtx("", oldEmailBus)
})
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
// nolint
resp := postRequest(t, testReceiversURL, `{
"alert": {
"labels": {
"alertname": "This is a custom label"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"uid":"",
"name":"receiver-1",
"type":"email",
"disableResolveMessage":false,
"settings":{
"addresses":"example@email.com"
},
"secureFields":{}
}
]
}]
}`, http.StatusOK)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var result apimodels.TestReceiversResult
require.NoError(t, json.Unmarshal(b, &result))
require.Len(t, result.Receivers, 1)
require.Len(t, result.Receivers[0].Configs, 1)
expectedJSON := fmt.Sprintf(`{
"alert": {
"annotations": {
"summary": "Notification test"
},
"labels": {
"alertname": "This is a custom label",
"instance": "Grafana"
}
},
"receivers": [{
"name":"receiver-1",
"grafana_managed_receiver_configs": [
{
"name": "receiver-1",
"uid": "%s",
"status": "ok"
}
]
}],
"notified_at": "%s"
}`,
result.Receivers[0].Configs[0].UID,
result.NotifiedAt.Format(time.RFC3339Nano))
require.JSONEq(t, expectedJSON, string(b))
require.Len(t, mockEmails.emails, 1)
require.Equal(t, []string{"example@email.com"}, mockEmails.emails[0].To)
})
}