renames alert_notifications -> notifiers

This commit is contained in:
bergquist
2019-01-28 20:39:09 +01:00
parent 21fff415ed
commit 8f0e65a150
19 changed files with 44 additions and 31 deletions
@@ -0,0 +1,180 @@
package notifiers
import (
"errors"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/models"
)
var (
ErrInvalidConfigTooManyDefault = errors.New("Alert notification provisioning config is invalid. Only one alert notification can be marked as default")
)
func Provision(configDirectory string) error {
dc := newNotificationProvisioner(log.New("provisioning.notifiers"))
return dc.applyChanges(configDirectory)
}
type NotificationProvisioner struct {
log log.Logger
cfgProvider *configReader
}
func newNotificationProvisioner(log log.Logger) NotificationProvisioner {
return NotificationProvisioner{
log: log,
cfgProvider: &configReader{log: log},
}
}
func (dc *NotificationProvisioner) apply(cfg *notificationsAsConfig) error {
if err := dc.deleteNotifications(cfg.DeleteNotifications); err != nil {
return err
}
if err := dc.mergeNotifications(cfg.Notifications); err != nil {
return err
}
return nil
}
func (dc *NotificationProvisioner) deleteNotifications(notificationToDelete []*deleteNotificationConfig) error {
for _, notification := range notificationToDelete {
dc.log.Info("Deleting alert notification", "name", notification.Name, "uid", notification.Uid)
if notification.OrgId == 0 && notification.OrgName != "" {
getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName}
if err := bus.Dispatch(getOrg); err != nil {
return err
}
notification.OrgId = getOrg.Result.Id
} else if notification.OrgId < 0 {
notification.OrgId = 1
}
getNotification := &models.GetAlertNotificationsWithUidQuery{Uid: notification.Uid, OrgId: notification.OrgId}
if err := bus.Dispatch(getNotification); err != nil {
return err
}
if getNotification.Result != nil {
cmd := &models.DeleteAlertNotificationWithUidCommand{Uid: getNotification.Result.Uid, OrgId: getNotification.OrgId}
if err := bus.Dispatch(cmd); err != nil {
return err
}
}
}
return nil
}
func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*notificationFromConfig) error {
for _, notification := range notificationToMerge {
if notification.OrgId == 0 && notification.OrgName != "" {
getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName}
if err := bus.Dispatch(getOrg); err != nil {
return err
}
notification.OrgId = getOrg.Result.Id
} else if notification.OrgId < 0 {
notification.OrgId = 1
}
cmd := &models.GetAlertNotificationsWithUidQuery{OrgId: notification.OrgId, Uid: notification.Uid}
err := bus.Dispatch(cmd)
if err != nil {
return err
}
if cmd.Result == nil {
dc.log.Info("Inserting alert notification from configuration ", "name", notification.Name, "uid", notification.Uid)
insertCmd := &models.CreateAlertNotificationCommand{
Uid: notification.Uid,
Name: notification.Name,
Type: notification.Type,
IsDefault: notification.IsDefault,
Settings: notification.SettingsToJson(),
OrgId: notification.OrgId,
DisableResolveMessage: notification.DisableResolveMessage,
Frequency: notification.Frequency,
SendReminder: notification.SendReminder,
}
if err := bus.Dispatch(insertCmd); err != nil {
return err
}
} else {
dc.log.Info("Updating alert notification from configuration", "name", notification.Name)
updateCmd := &models.UpdateAlertNotificationWithUidCommand{
Uid: notification.Uid,
Name: notification.Name,
Type: notification.Type,
IsDefault: notification.IsDefault,
Settings: notification.SettingsToJson(),
OrgId: notification.OrgId,
DisableResolveMessage: notification.DisableResolveMessage,
Frequency: notification.Frequency,
SendReminder: notification.SendReminder,
}
if err := bus.Dispatch(updateCmd); err != nil {
return err
}
}
}
return nil
}
func (cfg *notificationsAsConfig) mapToNotificationFromConfig() *notificationsAsConfig {
r := &notificationsAsConfig{}
if cfg == nil {
return r
}
for _, notification := range cfg.Notifications {
r.Notifications = append(r.Notifications, &notificationFromConfig{
Uid: notification.Uid,
OrgId: notification.OrgId,
OrgName: notification.OrgName,
Name: notification.Name,
Type: notification.Type,
IsDefault: notification.IsDefault,
Settings: notification.Settings,
DisableResolveMessage: notification.DisableResolveMessage,
Frequency: notification.Frequency,
SendReminder: notification.SendReminder,
})
}
for _, notification := range cfg.DeleteNotifications {
r.DeleteNotifications = append(r.DeleteNotifications, &deleteNotificationConfig{
Uid: notification.Uid,
OrgId: notification.OrgId,
OrgName: notification.OrgName,
Name: notification.Name,
})
}
return r
}
func (dc *NotificationProvisioner) applyChanges(configPath string) error {
configs, err := dc.cfgProvider.readConfig(configPath)
if err != nil {
return err
}
for _, cfg := range configs {
if err := dc.apply(cfg); err != nil {
return err
}
}
return nil
}
@@ -0,0 +1,163 @@
package notifiers
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"gopkg.in/yaml.v2"
)
type configReader struct {
log log.Logger
}
func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error) {
var notifications []*notificationsAsConfig
cr.log.Debug("Looking for alert notification provisioning files", "path", path)
files, err := ioutil.ReadDir(path)
if err != nil {
cr.log.Error("Can't read alert notification provisioning files from directory", "path", path)
return notifications, nil
}
for _, file := range files {
if strings.HasSuffix(file.Name(), ".yaml") || strings.HasSuffix(file.Name(), ".yml") {
cr.log.Debug("Parsing alert notifications provisioning file", "path", path, "file.Name", file.Name())
notifs, err := cr.parseNotificationConfig(path, file)
if err != nil {
return nil, err
}
if notifs != nil {
notifications = append(notifications, notifs)
}
}
}
cr.log.Debug("Validating alert notifications")
if err = validateRequiredField(notifications); err != nil {
return nil, err
}
checkOrgIdAndOrgName(notifications)
err = validateNotifications(notifications)
if err != nil {
return nil, err
}
return notifications, nil
}
func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) (*notificationsAsConfig, error) {
filename, _ := filepath.Abs(filepath.Join(path, file.Name()))
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
var cfg *notificationsAsConfig
err = yaml.Unmarshal(yamlFile, &cfg)
if err != nil {
return nil, err
}
return cfg.mapToNotificationFromConfig(), nil
}
func checkOrgIdAndOrgName(notifications []*notificationsAsConfig) {
for i := range notifications {
for _, notification := range notifications[i].Notifications {
if notification.OrgId < 1 {
if notification.OrgName == "" {
notification.OrgId = 1
} else {
notification.OrgId = 0
}
}
}
for _, notification := range notifications[i].DeleteNotifications {
if notification.OrgId < 1 {
if notification.OrgName == "" {
notification.OrgId = 1
} else {
notification.OrgId = 0
}
}
}
}
}
func validateRequiredField(notifications []*notificationsAsConfig) error {
for i := range notifications {
var errStrings []string
for index, notification := range notifications[i].Notifications {
if notification.Name == "" {
errStrings = append(
errStrings,
fmt.Sprintf("Added alert notification item %d in configuration doesn't contain required field name", index+1),
)
}
if notification.Uid == "" {
errStrings = append(
errStrings,
fmt.Sprintf("Added alert notification item %d in configuration doesn't contain required field uid", index+1),
)
}
}
for index, notification := range notifications[i].DeleteNotifications {
if notification.Name == "" {
errStrings = append(
errStrings,
fmt.Sprintf("Deleted alert notification item %d in configuration doesn't contain required field name", index+1),
)
}
if notification.Uid == "" {
errStrings = append(
errStrings,
fmt.Sprintf("Deleted alert notification item %d in configuration doesn't contain required field uid", index+1),
)
}
}
if len(errStrings) != 0 {
return fmt.Errorf(strings.Join(errStrings, "\n"))
}
}
return nil
}
func validateNotifications(notifications []*notificationsAsConfig) error {
for i := range notifications {
if notifications[i].Notifications == nil {
continue
}
for _, notification := range notifications[i].Notifications {
_, err := alerting.InitNotifier(&m.AlertNotification{
Name: notification.Name,
Settings: notification.SettingsToJson(),
Type: notification.Type,
})
if err != nil {
return err
}
}
}
return nil
}
@@ -0,0 +1,313 @@
package notifiers
import (
"testing"
"github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/alerting/notifiers"
"github.com/grafana/grafana/pkg/services/sqlstore"
. "github.com/smartystreets/goconvey/convey"
)
var (
logger = log.New("fake.log")
correct_properties = "./test-configs/correct-properties"
incorrect_settings = "./test-configs/incorrect-settings"
no_required_fields = "./test-configs/no-required-fields"
correct_properties_with_orgName = "./test-configs/correct-properties-with-orgName"
brokenYaml = "./test-configs/broken-yaml"
doubleNotificationsConfig = "./test-configs/double-default"
emptyFolder = "./test-configs/empty_folder"
emptyFile = "./test-configs/empty"
twoNotificationsConfig = "./test-configs/two-notifications"
unknownNotifier = "./test-configs/unknown-notifier"
)
func TestNotificationAsConfig(t *testing.T) {
Convey("Testing notification as configuration", t, func() {
sqlstore.InitTestDB(t)
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "slack",
Name: "slack",
Factory: notifiers.NewSlackNotifier,
})
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "email",
Name: "email",
Factory: notifiers.NewEmailNotifier,
})
Convey("Can read correct properties", func() {
cfgProvifer := &configReader{log: log.New("test logger")}
cfg, err := cfgProvifer.readConfig(correct_properties)
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 1)
ntCfg := cfg[0]
nts := ntCfg.Notifications
So(len(nts), ShouldEqual, 4)
nt := nts[0]
So(nt.Name, ShouldEqual, "default-slack-notification")
So(nt.Type, ShouldEqual, "slack")
So(nt.OrgId, ShouldEqual, 2)
So(nt.Uid, ShouldEqual, "notifier1")
So(nt.IsDefault, ShouldBeTrue)
So(nt.Settings, ShouldResemble, map[string]interface{}{
"recipient": "XXX", "token": "xoxb", "uploadImage": true, "url": "https://slack.com",
})
nt = nts[1]
So(nt.Name, ShouldEqual, "another-not-default-notification")
So(nt.Type, ShouldEqual, "email")
So(nt.OrgId, ShouldEqual, 3)
So(nt.Uid, ShouldEqual, "notifier2")
So(nt.IsDefault, ShouldBeFalse)
nt = nts[2]
So(nt.Name, ShouldEqual, "check-unset-is_default-is-false")
So(nt.Type, ShouldEqual, "slack")
So(nt.OrgId, ShouldEqual, 3)
So(nt.Uid, ShouldEqual, "notifier3")
So(nt.IsDefault, ShouldBeFalse)
nt = nts[3]
So(nt.Name, ShouldEqual, "Added notification with whitespaces in name")
So(nt.Type, ShouldEqual, "email")
So(nt.Uid, ShouldEqual, "notifier4")
So(nt.OrgId, ShouldEqual, 3)
deleteNts := ntCfg.DeleteNotifications
So(len(deleteNts), ShouldEqual, 4)
deleteNt := deleteNts[0]
So(deleteNt.Name, ShouldEqual, "default-slack-notification")
So(deleteNt.Uid, ShouldEqual, "notifier1")
So(deleteNt.OrgId, ShouldEqual, 2)
deleteNt = deleteNts[1]
So(deleteNt.Name, ShouldEqual, "deleted-notification-without-orgId")
So(deleteNt.OrgId, ShouldEqual, 1)
So(deleteNt.Uid, ShouldEqual, "notifier2")
deleteNt = deleteNts[2]
So(deleteNt.Name, ShouldEqual, "deleted-notification-with-0-orgId")
So(deleteNt.OrgId, ShouldEqual, 1)
So(deleteNt.Uid, ShouldEqual, "notifier3")
deleteNt = deleteNts[3]
So(deleteNt.Name, ShouldEqual, "Deleted notification with whitespaces in name")
So(deleteNt.OrgId, ShouldEqual, 1)
So(deleteNt.Uid, ShouldEqual, "notifier4")
})
Convey("One configured notification", func() {
Convey("no notification in database", func() {
dc := newNotificationProvisioner(logger)
err := dc.applyChanges(twoNotificationsConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
})
Convey("One notification in database with same name and uid", func() {
existingNotificationCmd := m.CreateAlertNotificationCommand{
Name: "channel1",
OrgId: 1,
Uid: "notifier1",
Type: "slack",
}
err := sqlstore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
So(existingNotificationCmd.Result, ShouldNotBeNil)
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 1)
Convey("should update one notification", func() {
dc := newNotificationProvisioner(logger)
err = dc.applyChanges(twoNotificationsConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
nts := notificationsQuery.Result
nt1 := nts[0]
So(nt1.Type, ShouldEqual, "email")
So(nt1.Name, ShouldEqual, "channel1")
So(nt1.Uid, ShouldEqual, "notifier1")
nt2 := nts[1]
So(nt2.Type, ShouldEqual, "slack")
So(nt2.Name, ShouldEqual, "channel2")
So(nt2.Uid, ShouldEqual, "notifier2")
})
})
Convey("Two notifications with is_default", func() {
dc := newNotificationProvisioner(logger)
err := dc.applyChanges(doubleNotificationsConfig)
Convey("should both be inserted", func() {
So(err, ShouldBeNil)
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
So(notificationsQuery.Result[0].IsDefault, ShouldBeTrue)
So(notificationsQuery.Result[1].IsDefault, ShouldBeTrue)
})
})
})
Convey("Two configured notification", func() {
Convey("two other notifications in database", func() {
existingNotificationCmd := m.CreateAlertNotificationCommand{
Name: "channel0",
OrgId: 1,
Uid: "notifier0",
Type: "slack",
}
err := sqlstore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
existingNotificationCmd = m.CreateAlertNotificationCommand{
Name: "channel3",
OrgId: 1,
Uid: "notifier3",
Type: "slack",
}
err = sqlstore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
Convey("should have two new notifications", func() {
dc := newNotificationProvisioner(logger)
err := dc.applyChanges(twoNotificationsConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
notificationsQuery = m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 4)
})
})
})
Convey("Can read correct properties with orgName instead of orgId", func() {
existingOrg1 := m.CreateOrgCommand{Name: "Main Org. 1"}
err := sqlstore.CreateOrg(&existingOrg1)
So(err, ShouldBeNil)
So(existingOrg1.Result, ShouldNotBeNil)
existingOrg2 := m.CreateOrgCommand{Name: "Main Org. 2"}
err = sqlstore.CreateOrg(&existingOrg2)
So(err, ShouldBeNil)
So(existingOrg2.Result, ShouldNotBeNil)
existingNotificationCmd := m.CreateAlertNotificationCommand{
Name: "default-notification-delete",
OrgId: existingOrg2.Result.Id,
Uid: "notifier2",
Type: "slack",
}
err = sqlstore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
dc := newNotificationProvisioner(logger)
err = dc.applyChanges(correct_properties_with_orgName)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: existingOrg2.Result.Id}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 1)
nt := notificationsQuery.Result[0]
So(nt.Name, ShouldEqual, "default-notification-create")
So(nt.OrgId, ShouldEqual, existingOrg2.Result.Id)
})
Convey("Config doesn't contain required field", func() {
dc := newNotificationProvisioner(logger)
err := dc.applyChanges(no_required_fields)
So(err, ShouldNotBeNil)
errString := err.Error()
So(errString, ShouldContainSubstring, "Deleted alert notification item 1 in configuration doesn't contain required field uid")
So(errString, ShouldContainSubstring, "Deleted alert notification item 2 in configuration doesn't contain required field name")
So(errString, ShouldContainSubstring, "Added alert notification item 1 in configuration doesn't contain required field name")
So(errString, ShouldContainSubstring, "Added alert notification item 2 in configuration doesn't contain required field uid")
})
Convey("Empty yaml file", func() {
Convey("should have not changed repo", func() {
dc := newNotificationProvisioner(logger)
err := dc.applyChanges(emptyFile)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
notificationsQuery := m.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlstore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldBeEmpty)
})
})
Convey("Broken yaml should return error", func() {
reader := &configReader{log: log.New("test logger")}
_, err := reader.readConfig(brokenYaml)
So(err, ShouldNotBeNil)
})
Convey("Skip invalid directory", func() {
cfgProvifer := &configReader{log: log.New("test logger")}
cfg, err := cfgProvifer.readConfig(emptyFolder)
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 0)
})
Convey("Unknown notifier should return error", func() {
cfgProvifer := &configReader{log: log.New("test logger")}
_, err := cfgProvifer.readConfig(unknownNotifier)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, "Unsupported notification type")
})
Convey("Read incorrect properties", func() {
cfgProvifer := &configReader{log: log.New("test logger")}
_, err := cfgProvifer.readConfig(incorrect_settings)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, "Alert validation error: Could not find url property in settings")
})
})
}
@@ -0,0 +1,9 @@
notifiers:
- name: notification-channel-1
type: slack
org_id: 2
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
@@ -0,0 +1,6 @@
#sfxzgnsxzcvnbzcvn
cvbn
cvbn
c
vbn
cvbncvbn
@@ -0,0 +1,12 @@
notifiers:
- name: default-notification-create
type: email
uid: notifier2
settings:
addresses: example@example.com
org_name: Main Org. 2
is_default: false
delete_notifiers:
- name: default-notification-delete
org_name: Main Org. 2
uid: notifier2
@@ -0,0 +1,42 @@
notifiers:
- name: default-slack-notification
type: slack
uid: notifier1
org_id: 2
uid: "notifier1"
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
url: https://slack.com
- name: another-not-default-notification
type: email
settings:
addresses: example@exmaple.com
org_id: 3
uid: "notifier2"
is_default: false
- name: check-unset-is_default-is-false
type: slack
org_id: 3
uid: "notifier3"
settings:
url: https://slack.com
- name: Added notification with whitespaces in name
type: email
org_id: 3
uid: "notifier4"
settings:
addresses: example@exmaple.com
delete_notifiers:
- name: default-slack-notification
org_id: 2
uid: notifier1
- name: deleted-notification-without-orgId
uid: "notifier2"
- name: deleted-notification-with-0-orgId
org_id: 0
uid: "notifier3"
- name: Deleted notification with whitespaces in name
uid: "notifier4"
@@ -0,0 +1,7 @@
notifiers:
- name: first-default
type: slack
uid: notifier1
is_default: true
settings:
url: https://slack.com
@@ -0,0 +1,7 @@
notifiers:
- name: second-default
type: email
uid: notifier2
is_default: true
settings:
addresses: example@example.com
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -0,0 +1,10 @@
notifiers:
- name: slack-notification-without-url-in-settings
type: slack
org_id: 2
uid: notifier1
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
@@ -0,0 +1,35 @@
notifiers:
- type: slack
org_id: 2
uid: no-name_added-notification
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
- name: no-uid
type: slack
org_id: 2
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
delete_notifiers:
- name: no-uid
type: slack
org_id: 2
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
- type: slack
org_id: 2
uid: no-name_added-notification
is_default: true
settings:
recipient: "XXX"
token: "xoxb"
uploadImage: true
@@ -0,0 +1,12 @@
notifiers:
- name: channel1
type: email
uid: notifier1
org_id: 1
settings:
addresses: example@example.com
- name: channel2
type: slack
uid: notifier2
settings:
url: http://slack.com
@@ -0,0 +1,4 @@
notifiers:
- name: unknown-notifier
type: nonexisting
uid: notifier1
@@ -0,0 +1,38 @@
package notifiers
import "github.com/grafana/grafana/pkg/components/simplejson"
type notificationsAsConfig struct {
Notifications []*notificationFromConfig `json:"notifiers" yaml:"notifiers"`
DeleteNotifications []*deleteNotificationConfig `json:"delete_notifiers" yaml:"delete_notifiers"`
}
type deleteNotificationConfig struct {
Uid string `json:"uid" yaml:"uid"`
Name string `json:"name" yaml:"name"`
OrgId int64 `json:"org_id" yaml:"org_id"`
OrgName string `json:"org_name" yaml:"org_name"`
}
type notificationFromConfig struct {
Uid string `json:"uid" yaml:"uid"`
OrgId int64 `json:"org_id" yaml:"org_id"`
OrgName string `json:"org_name" yaml:"org_name"`
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
SendReminder bool `json:"send_reminder" yaml:"send_reminder"`
DisableResolveMessage bool `json:"disable_resolve_message" yaml:"disable_resolve_message"`
Frequency string `json:"frequency" yaml:"frequency"`
IsDefault bool `json:"is_default" yaml:"is_default"`
Settings map[string]interface{} `json:"settings" yaml:"settings"`
}
func (notification notificationFromConfig) SettingsToJson() *simplejson.Json {
settings := simplejson.New()
if len(notification.Settings) > 0 {
for k, v := range notification.Settings {
settings.Set(k, v)
}
}
return settings
}