mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Adds basic alerting notification service tests (#21467)
Adds basic alerting notification tests. First steps towards getting #18011 merged. Ref #18011
This commit is contained in:
parent
d26075644c
commit
492912845f
4
go.sum
4
go.sum
@ -123,10 +123,6 @@ github.com/gosimple/slug v1.4.2 h1:jDmprx3q/9Lfk4FkGZtvzDQ9Cj9eAmsjzeQGp24PeiQ=
|
||||
github.com/gosimple/slug v1.4.2/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0=
|
||||
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4 h1:SPdxCL9BChFTlyi0Khv64vdCW4TMna8+sxL7+Chx+Ag=
|
||||
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4/go.mod h1:nc0XxBzjeGcrMltCDw269LoWF9S8ibhgxolCdA1R8To=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.4.1-0.20200106141801-810a19341b9e h1:wRxFEkkFzqVAes3zBTVrNDrVfnknj89dtsr18wcfqH0=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.4.1-0.20200106141801-810a19341b9e/go.mod h1:ve2cjkGc2fafTxW3KvhFcE6h0la7La6Z3FCfPqxx+Jk=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.4.1-0.20200107153407-ccbf1374e434 h1:j9tPXQ/Wri4oZqySnyL/TrFhXshOHn9Wg1rz9mfNzO8=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.4.1-0.20200107153407-ccbf1374e434/go.mod h1:ve2cjkGc2fafTxW3KvhFcE6h0la7La6Z3FCfPqxx+Jk=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.5.0 h1:qe60CcvhWn0H+CNoXgD6527GXcIJ78dU+pv1PmJypM8=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.5.0/go.mod h1:78zFGQy3wwAtNE5imCeXklnD1xJ1VtIhF4JmxUIrwrw=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
|
@ -13,6 +13,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// for stubbing in tests
|
||||
var newImageUploaderProvider = func() (imguploader.ImageUploader, error) {
|
||||
return imguploader.NewImageUploader()
|
||||
}
|
||||
|
||||
// NotifierPlugin holds meta information about a notifier.
|
||||
type NotifierPlugin struct {
|
||||
Type string `json:"type"`
|
||||
@ -119,7 +124,7 @@ func (n *notificationService) sendNotifications(evalContext *EvalContext, notifi
|
||||
}
|
||||
|
||||
func (n *notificationService) uploadImage(context *EvalContext) (err error) {
|
||||
uploader, err := imguploader.NewImageUploader()
|
||||
uploader, err := newImageUploaderProvider()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
238
pkg/services/alerting/notifier_test.go
Normal file
238
pkg/services/alerting/notifier_test.go
Normal file
@ -0,0 +1,238 @@
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/imguploader"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestNotificationService(t *testing.T) {
|
||||
testRule := &Rule{
|
||||
ID: 1,
|
||||
DashboardID: 1,
|
||||
PanelID: 1,
|
||||
OrgID: 1,
|
||||
Name: "Test",
|
||||
Message: "Something is bad",
|
||||
State: models.AlertStateAlerting,
|
||||
Notifications: []string{"1"},
|
||||
}
|
||||
evalCtx := NewEvalContext(context.Background(), testRule)
|
||||
|
||||
notificationServiceScenario(t, "SendIfNeeded should render and upload image and send notification", evalCtx, true, func(scenarioCtx *scenarioContext) {
|
||||
err := scenarioCtx.notificationService.SendIfNeeded(evalCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equalf(t, 1, scenarioCtx.renderCount, "expected render to be called, but wasn't")
|
||||
require.Equalf(t, 1, scenarioCtx.imageUploadCount, "expected image to be uploaded, but wasn't")
|
||||
require.Truef(t, evalCtx.Ctx.Value("notificationSent").(bool), "expected notification to be sent, but wasn't")
|
||||
})
|
||||
|
||||
notificationServiceScenario(t, "SendIfNeeded should not render and upload image, but send notification", evalCtx, false, func(scenarioCtx *scenarioContext) {
|
||||
err := scenarioCtx.notificationService.SendIfNeeded(evalCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equalf(t, 0, scenarioCtx.renderCount, "expected render to be called, but wasn't")
|
||||
require.Equalf(t, 0, scenarioCtx.imageUploadCount, "expected image to be uploaded, but wasn't")
|
||||
require.Truef(t, evalCtx.Ctx.Value("notificationSent").(bool), "expected notification to be sent, but wasn't")
|
||||
})
|
||||
}
|
||||
|
||||
type scenarioContext struct {
|
||||
evalCtx *EvalContext
|
||||
notificationService *notificationService
|
||||
imageUploadCount int
|
||||
renderCount int
|
||||
}
|
||||
|
||||
type scenarioFunc func(c *scenarioContext)
|
||||
|
||||
func notificationServiceScenario(t *testing.T, name string, evalCtx *EvalContext, uploadImage bool, fn scenarioFunc) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
RegisterNotifier(&NotifierPlugin{
|
||||
Type: "test",
|
||||
Name: "Test",
|
||||
Description: "Test notifier",
|
||||
Factory: newTestNotifier,
|
||||
})
|
||||
|
||||
evalCtx.dashboardRef = &models.DashboardRef{Uid: "db-uid"}
|
||||
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error {
|
||||
query.Result = []*models.AlertNotification{
|
||||
{
|
||||
Id: 1,
|
||||
Type: "test",
|
||||
Settings: simplejson.NewFromAny(map[string]interface{}{
|
||||
"uploadImage": uploadImage,
|
||||
}),
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetOrCreateNotificationStateQuery) error {
|
||||
query.Result = &models.AlertNotificationState{
|
||||
AlertId: evalCtx.Rule.ID,
|
||||
AlertRuleStateUpdatedVersion: 1,
|
||||
Id: 1,
|
||||
OrgId: evalCtx.Rule.OrgID,
|
||||
State: models.AlertNotificationStateUnknown,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
scenarioCtx := &scenarioContext{
|
||||
evalCtx: evalCtx,
|
||||
}
|
||||
|
||||
imageUploader := &testImageUploader{
|
||||
uploadProvider: func(ctx context.Context, path string) (string, error) {
|
||||
scenarioCtx.imageUploadCount++
|
||||
return "", nil
|
||||
},
|
||||
}
|
||||
|
||||
origNewImageUploaderProvider := newImageUploaderProvider
|
||||
newImageUploaderProvider = func() (imguploader.ImageUploader, error) {
|
||||
return imageUploader, nil
|
||||
}
|
||||
defer func() {
|
||||
newImageUploaderProvider = origNewImageUploaderProvider
|
||||
}()
|
||||
|
||||
renderService := &testRenderService{
|
||||
renderProvider: func(ctx context.Context, opts rendering.Opts) (*rendering.RenderResult, error) {
|
||||
scenarioCtx.renderCount++
|
||||
return &rendering.RenderResult{FilePath: "image.png"}, nil
|
||||
},
|
||||
}
|
||||
|
||||
scenarioCtx.notificationService = newNotificationService(renderService)
|
||||
fn(scenarioCtx)
|
||||
})
|
||||
}
|
||||
|
||||
type testNotifier struct {
|
||||
Name string
|
||||
Type string
|
||||
UID string
|
||||
IsDeault bool
|
||||
UploadImage bool
|
||||
SendReminder bool
|
||||
DisableResolveMessage bool
|
||||
Frequency time.Duration
|
||||
}
|
||||
|
||||
func newTestNotifier(model *models.AlertNotification) (Notifier, error) {
|
||||
uploadImage := true
|
||||
value, exist := model.Settings.CheckGet("uploadImage")
|
||||
if exist {
|
||||
uploadImage = value.MustBool()
|
||||
}
|
||||
|
||||
return &testNotifier{
|
||||
UID: model.Uid,
|
||||
Name: model.Name,
|
||||
IsDeault: model.IsDefault,
|
||||
Type: model.Type,
|
||||
UploadImage: uploadImage,
|
||||
SendReminder: model.SendReminder,
|
||||
DisableResolveMessage: model.DisableResolveMessage,
|
||||
Frequency: model.Frequency,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *testNotifier) Notify(evalCtx *EvalContext) error {
|
||||
evalCtx.Ctx = context.WithValue(evalCtx.Ctx, "notificationSent", true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *testNotifier) ShouldNotify(ctx context.Context, evalCtx *EvalContext, notiferState *models.AlertNotificationState) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetType() string {
|
||||
return n.Type
|
||||
}
|
||||
|
||||
func (n *testNotifier) NeedsImage() bool {
|
||||
return n.UploadImage
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetNotifierUID() string {
|
||||
return n.UID
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetIsDefault() bool {
|
||||
return n.IsDeault
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetSendReminder() bool {
|
||||
return n.SendReminder
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetDisableResolveMessage() bool {
|
||||
return n.DisableResolveMessage
|
||||
}
|
||||
|
||||
func (n *testNotifier) GetFrequency() time.Duration {
|
||||
return n.Frequency
|
||||
}
|
||||
|
||||
var _ Notifier = &testNotifier{}
|
||||
|
||||
type testRenderService struct {
|
||||
renderProvider func(ctx context.Context, opts rendering.Opts) (*rendering.RenderResult, error)
|
||||
renderErrorImageProvider func(error error) (*rendering.RenderResult, error)
|
||||
}
|
||||
|
||||
func (s *testRenderService) Render(ctx context.Context, opts rendering.Opts) (*rendering.RenderResult, error) {
|
||||
if s.renderProvider != nil {
|
||||
return s.renderProvider(ctx, opts)
|
||||
}
|
||||
|
||||
return &rendering.RenderResult{FilePath: "image.png"}, nil
|
||||
}
|
||||
|
||||
func (s *testRenderService) RenderErrorImage(err error) (*rendering.RenderResult, error) {
|
||||
if s.renderErrorImageProvider != nil {
|
||||
return s.renderErrorImageProvider(err)
|
||||
}
|
||||
|
||||
return &rendering.RenderResult{FilePath: "image.png"}, nil
|
||||
}
|
||||
|
||||
var _ rendering.Service = &testRenderService{}
|
||||
|
||||
type testImageUploader struct {
|
||||
uploadProvider func(ctx context.Context, path string) (string, error)
|
||||
}
|
||||
|
||||
func (u *testImageUploader) Upload(ctx context.Context, path string) (string, error) {
|
||||
if u.uploadProvider != nil {
|
||||
return u.uploadProvider(ctx, path)
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var _ imguploader.ImageUploader = &testImageUploader{}
|
Loading…
Reference in New Issue
Block a user