alert_notifications.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package alert_notifications
  2. import (
  3. "errors"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/components/simplejson"
  6. "github.com/grafana/grafana/pkg/log"
  7. "github.com/grafana/grafana/pkg/models"
  8. )
  9. var (
  10. ErrInvalidConfigTooManyDefault = errors.New("Alert notification provisioning config is invalid. Only one alert notification can be marked as default")
  11. ErrInvalidNotifierType = errors.New("Unknown notifier type")
  12. )
  13. func Provision(configDirectory string) error {
  14. dc := newNotificationProvisioner(log.New("provisioning.alert_notifications"))
  15. return dc.applyChanges(configDirectory)
  16. }
  17. type NotificationProvisioner struct {
  18. log log.Logger
  19. cfgProvider *configReader
  20. }
  21. func newNotificationProvisioner(log log.Logger) NotificationProvisioner {
  22. return NotificationProvisioner{
  23. log: log,
  24. cfgProvider: &configReader{log: log},
  25. }
  26. }
  27. func (dc *NotificationProvisioner) apply(cfg *notificationsAsConfig) error {
  28. if err := dc.deleteNotifications(cfg.DeleteNotifications); err != nil {
  29. return err
  30. }
  31. if err := dc.mergeNotifications(cfg.Notifications); err != nil {
  32. return err
  33. }
  34. return nil
  35. }
  36. func (dc *NotificationProvisioner) deleteNotifications(notificationToDelete []*deleteNotificationConfig) error {
  37. for _, notification := range notificationToDelete {
  38. dc.log.Info("Deleting alert notification", "name", notification.Name)
  39. if notification.OrgId == 0 && notification.OrgName != "" {
  40. getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName}
  41. if err := bus.Dispatch(getOrg); err != nil {
  42. return err
  43. }
  44. notification.OrgId = getOrg.Result.Id
  45. } else if notification.OrgId < 0 {
  46. notification.OrgId = 1
  47. }
  48. getNotification := &models.GetAlertNotificationsQuery{Name: notification.Name, OrgId: notification.OrgId}
  49. if err := bus.Dispatch(getNotification); err != nil {
  50. return err
  51. }
  52. if getNotification.Result != nil {
  53. cmd := &models.DeleteAlertNotificationCommand{Id: getNotification.Result.Id, OrgId: getNotification.OrgId}
  54. if err := bus.Dispatch(cmd); err != nil {
  55. return err
  56. }
  57. }
  58. }
  59. return nil
  60. }
  61. func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*notificationFromConfig) error {
  62. for _, notification := range notificationToMerge {
  63. if notification.OrgId == 0 && notification.OrgName != "" {
  64. getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName}
  65. if err := bus.Dispatch(getOrg); err != nil {
  66. return err
  67. }
  68. notification.OrgId = getOrg.Result.Id
  69. } else if notification.OrgId < 0 {
  70. notification.OrgId = 1
  71. }
  72. cmd := &models.GetAlertNotificationsQuery{OrgId: notification.OrgId, Name: notification.Name}
  73. err := bus.Dispatch(cmd)
  74. if err != nil {
  75. return err
  76. }
  77. settings := simplejson.New()
  78. if len(notification.Settings) > 0 {
  79. for k, v := range notification.Settings {
  80. settings.Set(k, v)
  81. }
  82. }
  83. if cmd.Result == nil {
  84. dc.log.Info("Inserting alert notification from configuration ", "name", notification.Name)
  85. insertCmd := &models.CreateAlertNotificationCommand{
  86. Name: notification.Name,
  87. Type: notification.Type,
  88. IsDefault: notification.IsDefault,
  89. Settings: settings,
  90. OrgId: notification.OrgId,
  91. }
  92. if err := bus.Dispatch(insertCmd); err != nil {
  93. return err
  94. }
  95. } else {
  96. dc.log.Info("Updating alert notification from configuration", "name", notification.Name)
  97. updateCmd := &models.UpdateAlertNotificationCommand{
  98. Id: cmd.Result.Id,
  99. Name: notification.Name,
  100. Type: notification.Type,
  101. IsDefault: notification.IsDefault,
  102. Settings: settings,
  103. OrgId: notification.OrgId,
  104. }
  105. if err := bus.Dispatch(updateCmd); err != nil {
  106. return err
  107. }
  108. }
  109. }
  110. return nil
  111. }
  112. func (cfg *notificationsAsConfig) mapToNotificationFromConfig() *notificationsAsConfig {
  113. r := &notificationsAsConfig{}
  114. if cfg == nil {
  115. return r
  116. }
  117. for _, notification := range cfg.Notifications {
  118. r.Notifications = append(r.Notifications, &notificationFromConfig{
  119. OrgId: notification.OrgId,
  120. OrgName: notification.OrgName,
  121. Name: notification.Name,
  122. Type: notification.Type,
  123. IsDefault: notification.IsDefault,
  124. Settings: notification.Settings,
  125. })
  126. }
  127. for _, notification := range cfg.DeleteNotifications {
  128. r.DeleteNotifications = append(r.DeleteNotifications, &deleteNotificationConfig{
  129. OrgId: notification.OrgId,
  130. OrgName: notification.OrgName,
  131. Name: notification.Name,
  132. })
  133. }
  134. return r
  135. }
  136. func (dc *NotificationProvisioner) applyChanges(configPath string) error {
  137. configs, err := dc.cfgProvider.readConfig(configPath)
  138. if err != nil {
  139. return err
  140. }
  141. for _, cfg := range configs {
  142. if err := dc.apply(cfg); err != nil {
  143. return err
  144. }
  145. }
  146. return nil
  147. }