Chore: Remove bus from ngalert (#44465)
* pass notification service down to the notifiers * add ns to all notifiers * remove bus from ngalert notifiers * use smaller interfaces for notificationservice * attempt to fix the tests * remove unused struct field * simplify notification service mock * trying to resolve issues in the tests * make linter happy * make linter even happier * linter, you are annoying
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
package server
|
||||
|
||||
import "github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
func ProvideTestEnv(server *Server, store *sqlstore.SQLStore) (*TestEnv, error) {
|
||||
return &TestEnv{server, store}, nil
|
||||
func ProvideTestEnv(server *Server, store *sqlstore.SQLStore, ns *notifications.NotificationServiceMock) (*TestEnv, error) {
|
||||
return &TestEnv{server, store, ns}, nil
|
||||
}
|
||||
|
||||
type TestEnv struct {
|
||||
Server *Server
|
||||
SQLStore *sqlstore.SQLStore
|
||||
Server *Server
|
||||
SQLStore *sqlstore.SQLStore
|
||||
NotificationService *notifications.NotificationServiceMock
|
||||
}
|
||||
|
||||
@@ -190,6 +190,9 @@ var wireSet = wire.NewSet(
|
||||
wireBasicSet,
|
||||
sqlstore.ProvideService,
|
||||
ngmetrics.ProvideService,
|
||||
wire.Bind(new(notifications.Service), new(*notifications.NotificationService)),
|
||||
wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)),
|
||||
wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)),
|
||||
)
|
||||
|
||||
var wireTestSet = wire.NewSet(
|
||||
@@ -197,6 +200,11 @@ var wireTestSet = wire.NewSet(
|
||||
ProvideTestEnv,
|
||||
sqlstore.ProvideServiceForTests,
|
||||
ngmetrics.ProvideServiceForTest,
|
||||
|
||||
notifications.MockNotificationService,
|
||||
wire.Bind(new(notifications.Service), new(*notifications.NotificationServiceMock)),
|
||||
wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationServiceMock)),
|
||||
wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationServiceMock)),
|
||||
)
|
||||
|
||||
func Initialize(cla setting.CommandLineArgs, opts Options, apiOpts api.ServerOptions) (*Server, error) {
|
||||
|
||||
@@ -261,7 +261,7 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager {
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
|
||||
mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(cleanOrgDirectories(tmpDir, t))
|
||||
err = mam.LoadAndSyncAlertmanagersForOrgs(context.Background())
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
@@ -40,19 +41,20 @@ const (
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, dataSourceCache datasources.CacheService, routeRegister routing.RouteRegister,
|
||||
sqlStore *sqlstore.SQLStore, kvStore kvstore.KVStore, expressionService *expr.Service, dataProxy *datasourceproxy.DataSourceProxyService,
|
||||
quotaService *quota.QuotaService, secretsService secrets.Service, m *metrics.NGAlert) (*AlertNG, error) {
|
||||
quotaService *quota.QuotaService, secretsService secrets.Service, notificationService notifications.Service, m *metrics.NGAlert) (*AlertNG, error) {
|
||||
ng := &AlertNG{
|
||||
Cfg: cfg,
|
||||
DataSourceCache: dataSourceCache,
|
||||
RouteRegister: routeRegister,
|
||||
SQLStore: sqlStore,
|
||||
KVStore: kvStore,
|
||||
ExpressionService: expressionService,
|
||||
DataProxy: dataProxy,
|
||||
QuotaService: quotaService,
|
||||
SecretsService: secretsService,
|
||||
Metrics: m,
|
||||
Log: log.New("ngalert"),
|
||||
Cfg: cfg,
|
||||
DataSourceCache: dataSourceCache,
|
||||
RouteRegister: routeRegister,
|
||||
SQLStore: sqlStore,
|
||||
KVStore: kvStore,
|
||||
ExpressionService: expressionService,
|
||||
DataProxy: dataProxy,
|
||||
QuotaService: quotaService,
|
||||
SecretsService: secretsService,
|
||||
Metrics: m,
|
||||
NotificationService: notificationService,
|
||||
Log: log.New("ngalert"),
|
||||
}
|
||||
|
||||
if ng.IsDisabled() {
|
||||
@@ -68,19 +70,20 @@ func ProvideService(cfg *setting.Cfg, dataSourceCache datasources.CacheService,
|
||||
|
||||
// AlertNG is the service for evaluating the condition of an alert definition.
|
||||
type AlertNG struct {
|
||||
Cfg *setting.Cfg
|
||||
DataSourceCache datasources.CacheService
|
||||
RouteRegister routing.RouteRegister
|
||||
SQLStore *sqlstore.SQLStore
|
||||
KVStore kvstore.KVStore
|
||||
ExpressionService *expr.Service
|
||||
DataProxy *datasourceproxy.DataSourceProxyService
|
||||
QuotaService *quota.QuotaService
|
||||
SecretsService secrets.Service
|
||||
Metrics *metrics.NGAlert
|
||||
Log log.Logger
|
||||
schedule schedule.ScheduleService
|
||||
stateManager *state.Manager
|
||||
Cfg *setting.Cfg
|
||||
DataSourceCache datasources.CacheService
|
||||
RouteRegister routing.RouteRegister
|
||||
SQLStore *sqlstore.SQLStore
|
||||
KVStore kvstore.KVStore
|
||||
ExpressionService *expr.Service
|
||||
DataProxy *datasourceproxy.DataSourceProxyService
|
||||
QuotaService *quota.QuotaService
|
||||
SecretsService secrets.Service
|
||||
Metrics *metrics.NGAlert
|
||||
NotificationService notifications.Service
|
||||
Log log.Logger
|
||||
schedule schedule.ScheduleService
|
||||
stateManager *state.Manager
|
||||
|
||||
// Alerting notification services
|
||||
MultiOrgAlertmanager *notifier.MultiOrgAlertmanager
|
||||
@@ -104,7 +107,7 @@ func (ng *AlertNG) init() error {
|
||||
|
||||
decryptFn := ng.SecretsService.GetDecryptedValue
|
||||
multiOrgMetrics := ng.Metrics.GetMultiOrgAlertmanagerMetrics()
|
||||
ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, decryptFn, multiOrgMetrics, log.New("ngalert.multiorg.alertmanager"))
|
||||
ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, decryptFn, multiOrgMetrics, ng.NotificationService, log.New("ngalert.multiorg.alertmanager"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
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/notifications"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -86,10 +87,11 @@ type ClusterPeer interface {
|
||||
type Alertmanager struct {
|
||||
logger log.Logger
|
||||
|
||||
Settings *setting.Cfg
|
||||
Store store.AlertingStore
|
||||
fileStore *FileStore
|
||||
Metrics *metrics.Alertmanager
|
||||
Settings *setting.Cfg
|
||||
Store store.AlertingStore
|
||||
fileStore *FileStore
|
||||
Metrics *metrics.Alertmanager
|
||||
NotificationService notifications.Service
|
||||
|
||||
notificationLog *nflog.Log
|
||||
marker types.Marker
|
||||
@@ -125,20 +127,21 @@ type Alertmanager struct {
|
||||
}
|
||||
|
||||
func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store store.AlertingStore, kvStore kvstore.KVStore,
|
||||
peer ClusterPeer, decryptFn channels.GetDecryptedValueFn, m *metrics.Alertmanager) (*Alertmanager, error) {
|
||||
peer ClusterPeer, decryptFn channels.GetDecryptedValueFn, ns notifications.Service, m *metrics.Alertmanager) (*Alertmanager, error) {
|
||||
am := &Alertmanager{
|
||||
Settings: cfg,
|
||||
stopc: make(chan struct{}),
|
||||
logger: log.New("alertmanager", "org", orgID),
|
||||
marker: types.NewMarker(m.Registerer),
|
||||
stageMetrics: notify.NewMetrics(m.Registerer),
|
||||
dispatcherMetrics: dispatch.NewDispatcherMetrics(false, m.Registerer),
|
||||
Store: store,
|
||||
peer: peer,
|
||||
peerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
||||
Metrics: m,
|
||||
orgID: orgID,
|
||||
decryptFn: decryptFn,
|
||||
Settings: cfg,
|
||||
stopc: make(chan struct{}),
|
||||
logger: log.New("alertmanager", "org", orgID),
|
||||
marker: types.NewMarker(m.Registerer),
|
||||
stageMetrics: notify.NewMetrics(m.Registerer),
|
||||
dispatcherMetrics: dispatch.NewDispatcherMetrics(false, m.Registerer),
|
||||
Store: store,
|
||||
peer: peer,
|
||||
peerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
||||
Metrics: m,
|
||||
NotificationService: ns,
|
||||
orgID: orgID,
|
||||
decryptFn: decryptFn,
|
||||
}
|
||||
|
||||
am.fileStore = NewFileStore(am.orgID, kvStore, am.WorkingDirPath())
|
||||
@@ -496,39 +499,39 @@ func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaRec
|
||||
)
|
||||
switch r.Type {
|
||||
case "email":
|
||||
n, err = channels.NewEmailNotifier(cfg, tmpl) // Email notifier already has a default template.
|
||||
n, err = channels.NewEmailNotifier(cfg, am.NotificationService, tmpl) // Email notifier already has a default template.
|
||||
case "pagerduty":
|
||||
n, err = channels.NewPagerdutyNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewPagerdutyNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "pushover":
|
||||
n, err = channels.NewPushoverNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewPushoverNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "slack":
|
||||
n, err = channels.NewSlackNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "telegram":
|
||||
n, err = channels.NewTelegramNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewTelegramNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "victorops":
|
||||
n, err = channels.NewVictoropsNotifier(cfg, tmpl)
|
||||
n, err = channels.NewVictoropsNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "teams":
|
||||
n, err = channels.NewTeamsNotifier(cfg, tmpl)
|
||||
n, err = channels.NewTeamsNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "dingding":
|
||||
n, err = channels.NewDingDingNotifier(cfg, tmpl)
|
||||
n, err = channels.NewDingDingNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "kafka":
|
||||
n, err = channels.NewKafkaNotifier(cfg, tmpl)
|
||||
n, err = channels.NewKafkaNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "webhook":
|
||||
n, err = channels.NewWebHookNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewWebHookNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "wecom":
|
||||
n, err = channels.NewWeComNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewWeComNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "sensugo":
|
||||
n, err = channels.NewSensuGoNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewSensuGoNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "discord":
|
||||
n, err = channels.NewDiscordNotifier(cfg, tmpl)
|
||||
n, err = channels.NewDiscordNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "googlechat":
|
||||
n, err = channels.NewGoogleChatNotifier(cfg, tmpl)
|
||||
n, err = channels.NewGoogleChatNotifier(cfg, am.NotificationService, tmpl)
|
||||
case "LINE":
|
||||
n, err = channels.NewLineNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewLineNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "threema":
|
||||
n, err = channels.NewThreemaNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewThreemaNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "opsgenie":
|
||||
n, err = channels.NewOpsgenieNotifier(cfg, tmpl, am.decryptFn)
|
||||
n, err = channels.NewOpsgenieNotifier(cfg, am.NotificationService, tmpl, am.decryptFn)
|
||||
case "prometheus-alertmanager":
|
||||
n, err = channels.NewAlertmanagerNotifier(cfg, tmpl, am.decryptFn)
|
||||
default:
|
||||
|
||||
@@ -50,7 +50,7 @@ func setupAMTest(t *testing.T) *Alertmanager {
|
||||
kvStore := NewFakeKVStore(t)
|
||||
secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore))
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
am, err := newAlertmanager(context.Background(), 1, cfg, s, kvStore, &NilPeer{}, decryptFn, m)
|
||||
am, err := newAlertmanager(context.Background(), 1, cfg, s, kvStore, &NilPeer{}, decryptFn, nil, m)
|
||||
require.NoError(t, err)
|
||||
return am
|
||||
}
|
||||
|
||||
@@ -9,15 +9,15 @@ import (
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
)
|
||||
|
||||
const defaultDingdingMsgType = "link"
|
||||
|
||||
// NewDingDingNotifier is the constructor for the Dingding notifier
|
||||
func NewDingDingNotifier(model *NotificationChannelConfig, t *template.Template) (*DingDingNotifier, error) {
|
||||
func NewDingDingNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*DingDingNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ func NewDingDingNotifier(model *NotificationChannelConfig, t *template.Template)
|
||||
Message: model.Settings.Get("message").MustString(`{{ template "default.message" .}}`),
|
||||
log: log.New("alerting.notifier.dingding"),
|
||||
tmpl: t,
|
||||
ns: ns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@ type DingDingNotifier struct {
|
||||
URL string
|
||||
Message string
|
||||
tmpl *template.Template
|
||||
ns notifications.WebhookSender
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
@@ -115,7 +117,7 @@ func (dd *DingDingNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
||||
Body: string(body),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := dd.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
return false, fmt.Errorf("send notification to dingding: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestDingdingNotifier(t *testing.T) {
|
||||
@@ -99,19 +97,14 @@ func TestDingdingNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewDingDingNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
pn, err := NewDingDingNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -127,7 +120,7 @@ func TestDingdingNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,17 @@ import (
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type DiscordNotifier struct {
|
||||
*Base
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
Content string
|
||||
AvatarURL string
|
||||
@@ -26,7 +27,7 @@ type DiscordNotifier struct {
|
||||
UseDiscordUsername bool
|
||||
}
|
||||
|
||||
func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template) (*DiscordNotifier, error) {
|
||||
func NewDiscordNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*DiscordNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -55,6 +56,7 @@ func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template)
|
||||
AvatarURL: avatarURL,
|
||||
WebhookURL: discordURL,
|
||||
log: log.New("alerting.notifier.discord"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
UseDiscordUsername: useDiscordUsername,
|
||||
}, nil
|
||||
@@ -114,7 +116,7 @@ func (d DiscordNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
||||
Body: string(body),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := d.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
d.log.Error("Failed to send notification to Discord", "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -143,19 +141,14 @@ func TestDiscordNotifier(t *testing.T) {
|
||||
Settings: settingsJson,
|
||||
}
|
||||
|
||||
dn, err := NewDiscordNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
dn, err := NewDiscordNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := dn.Notify(ctx, c.alerts...)
|
||||
@@ -171,7 +164,7 @@ func TestDiscordNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@@ -22,12 +22,13 @@ type EmailNotifier struct {
|
||||
SingleEmail bool
|
||||
Message string
|
||||
log log.Logger
|
||||
ns notifications.EmailSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// NewEmailNotifier is the constructor function
|
||||
// for the EmailNotifier.
|
||||
func NewEmailNotifier(model *NotificationChannelConfig, t *template.Template) (*EmailNotifier, error) {
|
||||
func NewEmailNotifier(model *NotificationChannelConfig, ns notifications.EmailSender, t *template.Template) (*EmailNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -54,6 +55,7 @@ func NewEmailNotifier(model *NotificationChannelConfig, t *template.Template) (*
|
||||
SingleEmail: singleEmail,
|
||||
Message: model.Settings.Get("message").MustString(),
|
||||
log: log.New("alerting.notifier.email"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -103,7 +105,7 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
||||
en.log.Warn("failed to template email message", "err", tmplErr.Error())
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := en.ns.SendEmailCommandHandlerSync(ctx, cmd); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestEmailNotifier(t *testing.T) {
|
||||
@@ -32,7 +30,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewEmailNotifier(model, tmpl)
|
||||
_, err := NewEmailNotifier(model, nil, tmpl)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -44,25 +42,16 @@ func TestEmailNotifier(t *testing.T) {
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
require.NoError(t, err)
|
||||
|
||||
emailSender := mockNotificationService()
|
||||
|
||||
emailNotifier, err := NewEmailNotifier(&NotificationChannelConfig{
|
||||
Name: "ops",
|
||||
Type: "email",
|
||||
Settings: settingsJSON,
|
||||
}, tmpl)
|
||||
}, emailSender, tmpl)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := map[string]interface{}{}
|
||||
bus.AddHandler("test", func(ctx context.Context, cmd *models.SendEmailCommandSync) error {
|
||||
expected["subject"] = cmd.SendEmailCommand.Subject
|
||||
expected["to"] = cmd.SendEmailCommand.To
|
||||
expected["single_email"] = cmd.SendEmailCommand.SingleEmail
|
||||
expected["template"] = cmd.SendEmailCommand.Template
|
||||
expected["data"] = cmd.SendEmailCommand.Data
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
alerts := []*types.Alert{
|
||||
{
|
||||
Alert: model.Alert{
|
||||
@@ -76,6 +65,13 @@ func TestEmailNotifier(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"subject": emailSender.Email.Subject,
|
||||
"to": emailSender.Email.To,
|
||||
"single_email": emailSender.Email.SingleEmail,
|
||||
"template": emailSender.Email.Template,
|
||||
"data": emailSender.Email.Data,
|
||||
}
|
||||
require.Equal(t, map[string]interface{}{
|
||||
"subject": "[FIRING:1] (AlwaysFiring warning)",
|
||||
"to": []string{"someops@example.com", "somedev@example.com"},
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -21,11 +21,12 @@ type GoogleChatNotifier struct {
|
||||
*Base
|
||||
URL string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
content string
|
||||
}
|
||||
|
||||
func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Template) (*GoogleChatNotifier, error) {
|
||||
func NewGoogleChatNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*GoogleChatNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -47,6 +48,7 @@ func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Templat
|
||||
}),
|
||||
URL: url,
|
||||
log: log.New("alerting.notifier.googlechat"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
content: content,
|
||||
}, nil
|
||||
@@ -137,7 +139,7 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
||||
Body: string(body),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := gcn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
gcn.log.Error("Failed to send Google Hangouts Chat alert", "error", err, "webhook", gcn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -12,9 +12,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -274,7 +272,8 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewGoogleChatNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
pn, err := NewGoogleChatNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -282,12 +281,6 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -303,7 +296,7 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
)
|
||||
|
||||
// KafkaNotifier is responsible for sending
|
||||
@@ -22,11 +22,12 @@ type KafkaNotifier struct {
|
||||
Endpoint string
|
||||
Topic string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// NewKafkaNotifier is the constructor function for the Kafka notifier.
|
||||
func NewKafkaNotifier(model *NotificationChannelConfig, t *template.Template) (*KafkaNotifier, error) {
|
||||
func NewKafkaNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*KafkaNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -51,6 +52,7 @@ func NewKafkaNotifier(model *NotificationChannelConfig, t *template.Template) (*
|
||||
Endpoint: endpoint,
|
||||
Topic: topic,
|
||||
log: log.New("alerting.notifier.kafka"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -112,7 +114,7 @@ func (kn *KafkaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
||||
},
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := kn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
kn.log.Error("Failed to send notification to Kafka", "error", err, "body", string(body))
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestKafkaNotifier(t *testing.T) {
|
||||
@@ -117,7 +115,8 @@ func TestKafkaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewKafkaNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
pn, err := NewKafkaNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -125,14 +124,6 @@ func TestKafkaNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
actUrl := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
actUrl = webhook.Url
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -145,8 +136,8 @@ func TestKafkaNotifier(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, c.expUrl, actUrl)
|
||||
require.JSONEq(t, c.expMsg, body)
|
||||
require.Equal(t, c.expUrl, webhookSender.Webhook.Url)
|
||||
require.JSONEq(t, c.expMsg, webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
@@ -18,7 +18,7 @@ var (
|
||||
)
|
||||
|
||||
// NewLineNotifier is the constructor for the LINE notifier
|
||||
func NewLineNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*LineNotifier, error) {
|
||||
func NewLineNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*LineNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ func NewLineNotifier(model *NotificationChannelConfig, t *template.Template, fn
|
||||
}),
|
||||
Token: token,
|
||||
log: log.New("alerting.notifier.line"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -51,6 +52,7 @@ type LineNotifier struct {
|
||||
*Base
|
||||
Token string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ func (ln *LineNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, e
|
||||
Body: form.Encode(),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := ln.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
ln.log.Error("Failed to send notification to LINE", "error", err, "body", body)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
)
|
||||
@@ -92,9 +90,10 @@ func TestLineNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewLineNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewLineNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -102,14 +101,6 @@ func TestLineNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
var headers map[string]string
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
headers = webhook.HttpHeader
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -122,8 +113,8 @@ func TestLineNotifier(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, c.expHeaders, headers)
|
||||
require.Equal(t, c.expMsg, body)
|
||||
require.Equal(t, c.expHeaders, webhookSender.Webhook.HttpHeader)
|
||||
require.Equal(t, c.expMsg, webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
@@ -38,10 +38,11 @@ type OpsgenieNotifier struct {
|
||||
SendTagsAs string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
}
|
||||
|
||||
// NewOpsgenieNotifier is the constructor for the Opsgenie notifier
|
||||
func NewOpsgenieNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*OpsgenieNotifier, error) {
|
||||
func NewOpsgenieNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*OpsgenieNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -81,6 +82,7 @@ func NewOpsgenieNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
SendTagsAs: sendTagsAs,
|
||||
tmpl: t,
|
||||
log: log.New("alerting.notifier." + model.Name),
|
||||
ns: ns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -120,7 +122,7 @@ func (on *OpsgenieNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
||||
},
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := on.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
return false, fmt.Errorf("send notification to Opsgenie: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -172,9 +170,11 @@ func TestOpsgenieNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
webhookSender.Webhook.Body = "<not-sent>"
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewOpsgenieNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewOpsgenieNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -182,12 +182,6 @@ func TestOpsgenieNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := "<not-sent>"
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -202,9 +196,9 @@ func TestOpsgenieNotifier(t *testing.T) {
|
||||
|
||||
if c.expMsg == "" {
|
||||
// No notification was expected.
|
||||
require.Equal(t, "<not-sent>", body)
|
||||
require.Equal(t, "<not-sent>", webhookSender.Webhook.Body)
|
||||
} else {
|
||||
require.JSONEq(t, c.expMsg, body)
|
||||
require.JSONEq(t, c.expMsg, webhookSender.Webhook.Body)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
@@ -37,10 +37,11 @@ type PagerdutyNotifier struct {
|
||||
Summary string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
}
|
||||
|
||||
// NewPagerdutyNotifier is the constructor for the PagerDuty notifier
|
||||
func NewPagerdutyNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*PagerdutyNotifier, error) {
|
||||
func NewPagerdutyNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*PagerdutyNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -75,6 +76,7 @@ func NewPagerdutyNotifier(model *NotificationChannelConfig, t *template.Template
|
||||
Summary: model.Settings.Get("summary").MustString(DefaultMessageTitleEmbed),
|
||||
tmpl: t,
|
||||
log: log.New("alerting.notifier." + model.Name),
|
||||
ns: ns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -105,7 +107,7 @@ func (pn *PagerdutyNotifier) Notify(ctx context.Context, as ...*types.Alert) (bo
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := pn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
return false, fmt.Errorf("send notification to Pagerduty: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -138,9 +136,10 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewPagerdutyNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewPagerdutyNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -148,12 +147,6 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -169,7 +162,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -36,10 +36,11 @@ type PushoverNotifier struct {
|
||||
Message string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
}
|
||||
|
||||
// NewSlackNotifier is the constructor for the Slack notifier
|
||||
func NewPushoverNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*PushoverNotifier, error) {
|
||||
func NewPushoverNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*PushoverNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -92,6 +93,7 @@ func NewPushoverNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
Message: model.Settings.Get("message").MustString(`{{ template "default.message" .}}`),
|
||||
tmpl: t,
|
||||
log: log.New("alerting.notifier.pushover"),
|
||||
ns: ns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -110,7 +112,7 @@ func (pn *PushoverNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
||||
Body: uploadBody.String(),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := pn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
pn.log.Error("Failed to send pushover notification", "error", err, "webhook", pn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -146,9 +144,10 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewPushoverNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewPushoverNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -156,12 +155,6 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -174,7 +167,7 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
bodyReader := multipart.NewReader(strings.NewReader(body), boundary)
|
||||
bodyReader := multipart.NewReader(strings.NewReader(webhookSender.Webhook.Body), boundary)
|
||||
for {
|
||||
part, err := bodyReader.NextPart()
|
||||
if part == nil || errors.Is(err, io.EOF) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
type SensuGoNotifier struct {
|
||||
*Base
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
|
||||
URL string
|
||||
@@ -29,7 +30,7 @@ type SensuGoNotifier struct {
|
||||
}
|
||||
|
||||
// NewSensuGoNotifier is the constructor for the SensuGo notifier
|
||||
func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*SensuGoNotifier, error) {
|
||||
func NewSensuGoNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*SensuGoNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -63,6 +64,7 @@ func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
APIKey: apikey,
|
||||
Message: model.Settings.Get("message").MustString(`{{ template "default.message" .}}`),
|
||||
log: log.New("alerting.notifier.sensugo"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -145,7 +147,7 @@ func (sn *SensuGoNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
||||
"Authorization": fmt.Sprintf("Key %s", sn.APIKey),
|
||||
},
|
||||
}
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := sn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
sn.log.Error("Failed to send Sensu Go event", "error", err, "sensugo", sn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -146,9 +144,10 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
sn, err := NewSensuGoNotifier(m, tmpl, decryptFn)
|
||||
sn, err := NewSensuGoNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -156,12 +155,6 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := sn.Notify(ctx, c.alerts...)
|
||||
@@ -177,7 +170,7 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
)
|
||||
|
||||
// TeamsNotifier is responsible for sending
|
||||
@@ -21,10 +21,11 @@ type TeamsNotifier struct {
|
||||
Message string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
}
|
||||
|
||||
// NewTeamsNotifier is the constructor for Teams notifier.
|
||||
func NewTeamsNotifier(model *NotificationChannelConfig, t *template.Template) (*TeamsNotifier, error) {
|
||||
func NewTeamsNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*TeamsNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -45,6 +46,7 @@ func NewTeamsNotifier(model *NotificationChannelConfig, t *template.Template) (*
|
||||
URL: u,
|
||||
Message: model.Settings.Get("message").MustString(`{{ template "teams.default.message" .}}`),
|
||||
log: log.New("alerting.notifier.teams"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -97,7 +99,7 @@ func (tn *TeamsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
||||
}
|
||||
cmd := &models.SendWebhookSync{Url: u, Body: string(b)}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := tn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
return false, errors.Wrap(err, "send notification to Teams")
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestTeamsNotifier(t *testing.T) {
|
||||
@@ -123,7 +121,8 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewTeamsNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
pn, err := NewTeamsNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -131,12 +130,6 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -152,7 +145,7 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
@@ -25,11 +25,12 @@ type TelegramNotifier struct {
|
||||
ChatID string
|
||||
Message string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// NewTelegramNotifier is the constructor for the Telegram notifier
|
||||
func NewTelegramNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*TelegramNotifier, error) {
|
||||
func NewTelegramNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*TelegramNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -62,6 +63,7 @@ func NewTelegramNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
Message: message,
|
||||
tmpl: t,
|
||||
log: log.New("alerting.notifier.telegram"),
|
||||
ns: ns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ func (tn *TelegramNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
||||
},
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := tn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
tn.log.Error("Failed to send webhook", "error", err, "webhook", tn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -98,9 +98,10 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewTelegramNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewTelegramNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package channels
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
// mockTimeNow replaces function timeNow to return constant time.
|
||||
// It returns a function that resets the variable back to its original value.
|
||||
@@ -21,3 +26,20 @@ func mockTimeNow(constTime time.Time) func() {
|
||||
func resetTimeNow() {
|
||||
timeNow = time.Now
|
||||
}
|
||||
|
||||
type notificationServiceMock struct {
|
||||
Webhook models.SendWebhookSync
|
||||
Email models.SendEmailCommandSync
|
||||
ShouldError error
|
||||
}
|
||||
|
||||
func (ns *notificationServiceMock) SendWebhookSync(ctx context.Context, cmd *models.SendWebhookSync) error {
|
||||
ns.Webhook = *cmd
|
||||
return ns.ShouldError
|
||||
}
|
||||
func (ns *notificationServiceMock) SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error {
|
||||
ns.Email = *cmd
|
||||
return ns.ShouldError
|
||||
}
|
||||
|
||||
func mockNotificationService() *notificationServiceMock { return ¬ificationServiceMock{} }
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -27,11 +27,12 @@ type ThreemaNotifier struct {
|
||||
RecipientID string
|
||||
APISecret string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// NewThreemaNotifier is the constructor for the Threema notifier
|
||||
func NewThreemaNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*ThreemaNotifier, error) {
|
||||
func NewThreemaNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*ThreemaNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -74,6 +75,7 @@ func NewThreemaNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
RecipientID: recipientID,
|
||||
APISecret: apiSecret,
|
||||
log: log.New("alerting.notifier.threema"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -119,7 +121,7 @@ func (tn *ThreemaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
}
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := tn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
tn.log.Error("Failed to send threema notification", "error", err, "webhook", tn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -110,9 +108,10 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewThreemaNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewThreemaNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -120,12 +119,6 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -138,7 +131,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, c.expMsg, body)
|
||||
require.Equal(t, c.expMsg, webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@ const (
|
||||
|
||||
// NewVictoropsNotifier creates an instance of VictoropsNotifier that
|
||||
// handles posting notifications to Victorops REST API
|
||||
func NewVictoropsNotifier(model *NotificationChannelConfig, t *template.Template) (*VictoropsNotifier, error) {
|
||||
func NewVictoropsNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template) (*VictoropsNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ func NewVictoropsNotifier(model *NotificationChannelConfig, t *template.Template
|
||||
URL: url,
|
||||
MessageType: model.Settings.Get("messageType").MustString(),
|
||||
log: log.New("alerting.notifier.victorops"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -60,6 +61,7 @@ type VictoropsNotifier struct {
|
||||
URL string
|
||||
MessageType string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ func (vn *VictoropsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bo
|
||||
Body: string(b),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := vn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
vn.log.Error("Failed to send Victorops notification", "error", err, "webhook", vn.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -95,7 +93,8 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewVictoropsNotifier(m, tmpl)
|
||||
webhookSender := mockNotificationService()
|
||||
pn, err := NewVictoropsNotifier(m, webhookSender, tmpl)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -103,12 +102,6 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -122,12 +115,12 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
require.True(t, ok)
|
||||
|
||||
// Remove the non-constant timestamp
|
||||
j, err := simplejson.NewJson([]byte(body))
|
||||
j, err := simplejson.NewJson([]byte(webhookSender.Webhook.Body))
|
||||
require.NoError(t, err)
|
||||
j.Del("timestamp")
|
||||
b, err := j.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
body = string(b)
|
||||
body := string(b)
|
||||
|
||||
expJson, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
@@ -23,13 +23,14 @@ type WebhookNotifier struct {
|
||||
HTTPMethod string
|
||||
MaxAlerts int
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
tmpl *template.Template
|
||||
orgID int64
|
||||
}
|
||||
|
||||
// NewWebHookNotifier is the constructor for
|
||||
// the WebHook notifier.
|
||||
func NewWebHookNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*WebhookNotifier, error) {
|
||||
func NewWebHookNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*WebhookNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -55,6 +56,7 @@ func NewWebHookNotifier(model *NotificationChannelConfig, t *template.Template,
|
||||
HTTPMethod: model.Settings.Get("httpMethod").MustString("POST"),
|
||||
MaxAlerts: model.Settings.Get("maxAlerts").MustInt(0),
|
||||
log: log.New("alerting.notifier.webhook"),
|
||||
ns: ns,
|
||||
tmpl: t,
|
||||
}, nil
|
||||
}
|
||||
@@ -118,7 +120,7 @@ func (wn *WebhookNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
||||
HttpMethod: wn.HTTPMethod,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := wn.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
@@ -192,9 +190,10 @@ func TestWebhookNotifier(t *testing.T) {
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewWebHookNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewWebHookNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@@ -202,12 +201,6 @@ func TestWebhookNotifier(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
var payload *models.SendWebhookSync
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
payload = webhook
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ctx = notify.WithReceiverName(ctx, "my_receiver")
|
||||
@@ -224,11 +217,11 @@ func TestWebhookNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), payload.Body)
|
||||
require.Equal(t, c.expUrl, payload.Url)
|
||||
require.Equal(t, c.expUsername, payload.User)
|
||||
require.Equal(t, c.expPassword, payload.Password)
|
||||
require.Equal(t, c.expHttpMethod, payload.HttpMethod)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
require.Equal(t, c.expUrl, webhookSender.Webhook.Url)
|
||||
require.Equal(t, c.expUsername, webhookSender.Webhook.User)
|
||||
require.Equal(t, c.expPassword, webhookSender.Webhook.Password)
|
||||
require.Equal(t, c.expHttpMethod, webhookSender.Webhook.HttpMethod)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
)
|
||||
|
||||
// NewWeComNotifier is the constructor for WeCom notifier.
|
||||
func NewWeComNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*WeComNotifier, error) {
|
||||
func NewWeComNotifier(model *NotificationChannelConfig, ns notifications.WebhookSender, t *template.Template, fn GetDecryptedValueFn) (*WeComNotifier, error) {
|
||||
url := fn(context.Background(), model.SecureSettings, "url", model.Settings.Get("url").MustString())
|
||||
|
||||
if url == "" {
|
||||
@@ -31,6 +31,7 @@ func NewWeComNotifier(model *NotificationChannelConfig, t *template.Template, fn
|
||||
}),
|
||||
URL: url,
|
||||
log: log.New("alerting.notifier.wecom"),
|
||||
ns: ns,
|
||||
Message: model.Settings.Get("message").MustString(`{{ template "default.message" .}}`),
|
||||
tmpl: t,
|
||||
}, nil
|
||||
@@ -43,6 +44,7 @@ type WeComNotifier struct {
|
||||
Message string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
}
|
||||
|
||||
// Notify send an alert notification to WeCom.
|
||||
@@ -74,7 +76,7 @@ func (w *WeComNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, e
|
||||
Body: string(body),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||
if err := w.ns.SendWebhookSync(ctx, cmd); err != nil {
|
||||
w.log.Error("failed to send WeCom webhook", "error", err, "notification", w.Name)
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestWeComNotifier(t *testing.T) {
|
||||
@@ -96,21 +94,16 @@ func TestWeComNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
pn, err := NewWeComNotifier(m, tmpl, decryptFn)
|
||||
pn, err := NewWeComNotifier(m, webhookSender, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
body := ""
|
||||
bus.AddHandler("test", func(ctx context.Context, webhook *models.SendWebhookSync) error {
|
||||
body = webhook.Body
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
@@ -126,7 +119,7 @@ func TestWeComNotifier(t *testing.T) {
|
||||
expBody, err := json.Marshal(c.expMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(expBody), body)
|
||||
require.JSONEq(t, string(expBody), webhookSender.Webhook.Body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
|
||||
"github.com/prometheus/alertmanager/cluster"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -45,10 +46,12 @@ type MultiOrgAlertmanager struct {
|
||||
decryptFn channels.GetDecryptedValueFn
|
||||
|
||||
metrics *metrics.MultiOrgAlertmanager
|
||||
ns notifications.Service
|
||||
}
|
||||
|
||||
func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore, orgStore store.OrgStore,
|
||||
kvStore kvstore.KVStore, decryptFn channels.GetDecryptedValueFn, m *metrics.MultiOrgAlertmanager, l log.Logger,
|
||||
kvStore kvstore.KVStore, decryptFn channels.GetDecryptedValueFn, m *metrics.MultiOrgAlertmanager,
|
||||
ns notifications.Service, l log.Logger,
|
||||
) (*MultiOrgAlertmanager, error) {
|
||||
moa := &MultiOrgAlertmanager{
|
||||
logger: l,
|
||||
@@ -59,6 +62,7 @@ func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore,
|
||||
kvStore: kvStore,
|
||||
decryptFn: decryptFn,
|
||||
metrics: m,
|
||||
ns: ns,
|
||||
}
|
||||
|
||||
clusterLogger := l.New("component", "cluster")
|
||||
@@ -170,7 +174,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
|
||||
// To export them, we need to translate the metrics from each individual registry and,
|
||||
// then aggregate them on the main registry.
|
||||
m := metrics.NewAlertmanagerMetrics(moa.metrics.GetOrCreateOrgRegistry(orgID))
|
||||
am, err := newAlertmanager(ctx, orgID, moa.settings, moa.configStore, moa.kvStore, moa.peer, moa.decryptFn, m)
|
||||
am, err := newAlertmanager(ctx, orgID, moa.settings, moa.configStore, moa.kvStore, moa.peer, moa.decryptFn, moa.ns, m)
|
||||
if err != nil {
|
||||
moa.logger.Error("unable to create Alertmanager for org", "org", orgID, "err", err)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) {
|
||||
DisabledOrgs: map[int64]struct{}{5: {}},
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -173,7 +173,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgsWithFailures(t *testing.T)
|
||||
DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration(),
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -224,7 +224,7 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) {
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
m := metrics.NewNGAlert(reg)
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -923,7 +923,7 @@ func setupScheduler(t *testing.T, rs store.RuleStore, is store.InstanceStore, ac
|
||||
m := metrics.NewNGAlert(registry)
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, decryptFn, nil, log.New("testlogger"))
|
||||
moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
|
||||
schedCfg := SchedulerCfg{
|
||||
|
||||
@@ -39,7 +39,7 @@ func SetupTestEnv(t *testing.T, baseInterval time.Duration) (*ngalert.AlertNG, *
|
||||
secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore))
|
||||
ng, err := ngalert.ProvideService(
|
||||
cfg, nil, routing.NewRouteRegister(), sqlStore,
|
||||
nil, nil, nil, nil, secretsService, m,
|
||||
nil, nil, nil, nil, secretsService, nil, m,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return ng, &store.DBstore{
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package notifications
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type NotificationServiceMock struct {
|
||||
Webhook models.SendWebhookSync
|
||||
Email models.SendEmailCommandSync
|
||||
ShouldError error
|
||||
|
||||
WebhookHandler func(context.Context, *models.SendWebhookSync) error
|
||||
EmailHandler func(context.Context, *models.SendEmailCommandSync) error
|
||||
}
|
||||
|
||||
func (ns *NotificationServiceMock) SendWebhookSync(ctx context.Context, cmd *models.SendWebhookSync) error {
|
||||
ns.Webhook = *cmd
|
||||
if ns.WebhookHandler != nil {
|
||||
return ns.WebhookHandler(ctx, cmd)
|
||||
}
|
||||
return ns.ShouldError
|
||||
}
|
||||
func (ns *NotificationServiceMock) SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error {
|
||||
ns.Email = *cmd
|
||||
if ns.EmailHandler != nil {
|
||||
return ns.EmailHandler(ctx, cmd)
|
||||
}
|
||||
return ns.ShouldError
|
||||
}
|
||||
|
||||
func MockNotificationService() *NotificationServiceMock { return &NotificationServiceMock{} }
|
||||
@@ -17,6 +17,17 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type WebhookSender interface {
|
||||
SendWebhookSync(ctx context.Context, cmd *models.SendWebhookSync) error
|
||||
}
|
||||
type EmailSender interface {
|
||||
SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error
|
||||
}
|
||||
type Service interface {
|
||||
WebhookSender
|
||||
EmailSender
|
||||
}
|
||||
|
||||
var mailTemplates *template.Template
|
||||
var tmplResetPassword = "reset_password"
|
||||
var tmplSignUpStarted = "signup_started"
|
||||
@@ -36,7 +47,7 @@ func ProvideService(bus bus.Bus, cfg *setting.Cfg, mailer Mailer) (*Notification
|
||||
ns.Bus.AddHandler(ns.validateResetPasswordCode)
|
||||
ns.Bus.AddHandler(ns.sendEmailCommandHandler)
|
||||
|
||||
ns.Bus.AddHandler(ns.sendEmailCommandHandlerSync)
|
||||
ns.Bus.AddHandler(ns.SendEmailCommandHandlerSync)
|
||||
ns.Bus.AddHandler(ns.SendWebhookSync)
|
||||
|
||||
ns.Bus.AddEventListener(ns.signUpStartedHandler)
|
||||
@@ -119,7 +130,7 @@ func subjectTemplateFunc(obj map[string]interface{}, value string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ns *NotificationService) sendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error {
|
||||
func (ns *NotificationService) SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error {
|
||||
message, err := ns.buildEmailMessage(&models.SendEmailCommand{
|
||||
Data: cmd.Data,
|
||||
Info: cmd.Info,
|
||||
|
||||
@@ -493,37 +493,37 @@ func (m *migration) validateAlertmanagerConfig(orgID int64, config *PostableUser
|
||||
|
||||
switch gr.Type {
|
||||
case "email":
|
||||
_, err = channels.NewEmailNotifier(cfg, nil) // Email notifier already has a default template.
|
||||
_, err = channels.NewEmailNotifier(cfg, nil, nil) // Email notifier already has a default template.
|
||||
case "pagerduty":
|
||||
_, err = channels.NewPagerdutyNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewPagerdutyNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "pushover":
|
||||
_, err = channels.NewPushoverNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewPushoverNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "slack":
|
||||
_, err = channels.NewSlackNotifier(cfg, nil, decryptFunc)
|
||||
case "telegram":
|
||||
_, err = channels.NewTelegramNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewTelegramNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "victorops":
|
||||
_, err = channels.NewVictoropsNotifier(cfg, nil)
|
||||
_, err = channels.NewVictoropsNotifier(cfg, nil, nil)
|
||||
case "teams":
|
||||
_, err = channels.NewTeamsNotifier(cfg, nil)
|
||||
_, err = channels.NewTeamsNotifier(cfg, nil, nil)
|
||||
case "dingding":
|
||||
_, err = channels.NewDingDingNotifier(cfg, nil)
|
||||
_, err = channels.NewDingDingNotifier(cfg, nil, nil)
|
||||
case "kafka":
|
||||
_, err = channels.NewKafkaNotifier(cfg, nil)
|
||||
_, err = channels.NewKafkaNotifier(cfg, nil, nil)
|
||||
case "webhook":
|
||||
_, err = channels.NewWebHookNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewWebHookNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "sensugo":
|
||||
_, err = channels.NewSensuGoNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewSensuGoNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "discord":
|
||||
_, err = channels.NewDiscordNotifier(cfg, nil)
|
||||
_, err = channels.NewDiscordNotifier(cfg, nil, nil)
|
||||
case "googlechat":
|
||||
_, err = channels.NewGoogleChatNotifier(cfg, nil)
|
||||
_, err = channels.NewGoogleChatNotifier(cfg, nil, nil)
|
||||
case "LINE":
|
||||
_, err = channels.NewLineNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewLineNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "threema":
|
||||
_, err = channels.NewThreemaNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewThreemaNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "opsgenie":
|
||||
_, err = channels.NewOpsgenieNotifier(cfg, nil, decryptFunc)
|
||||
_, err = channels.NewOpsgenieNotifier(cfg, nil, nil, decryptFunc)
|
||||
case "prometheus-alertmanager":
|
||||
_, err = channels.NewAlertmanagerNotifier(cfg, nil, decryptFunc)
|
||||
default:
|
||||
|
||||
@@ -41,10 +41,10 @@ func TestTestReceivers(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
@@ -74,21 +74,17 @@ func TestTestReceivers(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandler{}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
// nolint
|
||||
@@ -162,21 +158,17 @@ func TestTestReceivers(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandler{}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
// nolint
|
||||
@@ -245,23 +237,19 @@ func TestTestReceivers(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandlerWithTimeout{
|
||||
timeout: 5 * time.Second,
|
||||
}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
req, err := http.NewRequest(http.MethodPost, testReceiversURL, strings.NewReader(`{
|
||||
@@ -338,23 +326,19 @@ func TestTestReceivers(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandlerWithTimeout{
|
||||
timeout: 5 * time.Second,
|
||||
}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
req, err := http.NewRequest(http.MethodPost, testReceiversURL, strings.NewReader(`{
|
||||
@@ -457,21 +441,17 @@ func TestTestReceiversAlertCustomization(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandler{}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
// nolint
|
||||
@@ -556,21 +536,17 @@ func TestTestReceiversAlertCustomization(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandler{}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
// nolint
|
||||
@@ -650,21 +626,17 @@ func TestTestReceiversAlertCustomization(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||
store.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
createUser(t, store, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Login: "grafana",
|
||||
Password: "password",
|
||||
})
|
||||
|
||||
oldEmailBus := bus.GetHandlerCtx("SendEmailCommandSync")
|
||||
mockEmails := &mockEmailHandler{}
|
||||
bus.AddHandler("", mockEmails.sendEmailCommandHandlerSync)
|
||||
t.Cleanup(func() {
|
||||
bus.AddHandler("", oldEmailBus)
|
||||
})
|
||||
env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync
|
||||
|
||||
testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr)
|
||||
// nolint
|
||||
@@ -745,8 +717,8 @@ func TestNotificationChannels(t *testing.T) {
|
||||
DisableAnonymous: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, s := testinfra.StartGrafana(t, dir, path)
|
||||
s.Bus = bus.GetBus()
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
env.SQLStore.Bus = bus.GetBus()
|
||||
|
||||
mockChannel := newMockNotificationChannel(t, grafanaListedAddr)
|
||||
amConfig := getAlertmanagerConfig(mockChannel.server.Addr)
|
||||
@@ -757,13 +729,11 @@ func TestNotificationChannels(t *testing.T) {
|
||||
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.AddHandler("", originalEmailBus)
|
||||
})
|
||||
channels.DefaultTemplateString = channels.TemplateForTestsString
|
||||
channels.SlackAPIEndpoint = fmt.Sprintf("http://%s/slack_recvX/slack_testX", mockChannel.server.Addr)
|
||||
@@ -773,10 +743,19 @@ func TestNotificationChannels(t *testing.T) {
|
||||
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.AddHandler("", mockEmail.sendEmailCommandHandlerSync)
|
||||
|
||||
env.NotificationService.EmailHandler = mockEmail.sendEmailCommandHandlerSync
|
||||
// As we are using a NotificationService mock here, but he test expects real NotificationService -
|
||||
// we try to issue a real POST request here
|
||||
env.NotificationService.WebhookHandler = func(_ context.Context, cmd *models.SendWebhookSync) error {
|
||||
if res, err := http.Post(cmd.Url, "", strings.NewReader(cmd.Body)); err == nil {
|
||||
_ = res.Body.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a user to make authenticated requests
|
||||
createUser(t, s, models.CreateUserCommand{
|
||||
createUser(t, env.SQLStore, models.CreateUserCommand{
|
||||
DefaultOrgRole: string(models.ROLE_EDITOR),
|
||||
Password: "password",
|
||||
Login: "grafana",
|
||||
@@ -793,7 +772,7 @@ func TestNotificationChannels(t *testing.T) {
|
||||
|
||||
{
|
||||
// Create the namespace we'll save our alerts to.
|
||||
_, err := createFolder(t, s, 0, "default")
|
||||
_, err := createFolder(t, env.SQLStore, 0, "default")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Post the alertmanager config.
|
||||
|
||||
@@ -27,6 +27,11 @@ import (
|
||||
// StartGrafana starts a Grafana server.
|
||||
// The server address is returned.
|
||||
func StartGrafana(t *testing.T, grafDir, cfgPath string) (string, *sqlstore.SQLStore) {
|
||||
addr, env := StartGrafanaEnv(t, grafDir, cfgPath)
|
||||
return addr, env.SQLStore
|
||||
}
|
||||
|
||||
func StartGrafanaEnv(t *testing.T, grafDir, cfgPath string) (string, *server.TestEnv) {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -65,7 +70,7 @@ func StartGrafana(t *testing.T, grafDir, cfgPath string) (string, *sqlstore.SQLS
|
||||
|
||||
t.Logf("Grafana is listening on %s", addr)
|
||||
|
||||
return addr, env.SQLStore
|
||||
return addr, env
|
||||
}
|
||||
|
||||
// SetUpDatabase sets up the Grafana database.
|
||||
|
||||
Reference in New Issue
Block a user