alert_notifications.go 5.3 KB

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