AlertNotifications: Translate notifications IDs to UIDs in Rule builder (#19882)

* AlertNotifications: Translate notifications IDs to UIDs in alert Rule builder

* Avoid shadowing errors, raise validation error on non-existing notification id

* create a cache for notification Uids to minimize db overhead

* add cache usage test

* avoid caching empty notification Uids

* isolate db in alert notificationUid caching tests
This commit is contained in:
Dima Ryskin
2020-03-18 15:00:56 +02:00
committed by GitHub
parent 492264abc3
commit 44b7f3ea1c
6 changed files with 198 additions and 8 deletions

View File

@@ -7,6 +7,7 @@ import (
"strconv"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
)
@@ -137,13 +138,15 @@ func NewRuleFromDBAlert(ruleDef *models.Alert) (*Rule, error) {
for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
jsonModel := simplejson.NewFromAny(v)
if id, err := jsonModel.Get("id").Int64(); err == nil {
model.Notifications = append(model.Notifications, fmt.Sprintf("%09d", id))
} else {
uid, err := jsonModel.Get("uid").String()
uid, err := translateNotificationIDToUID(id, ruleDef.OrgId)
if err != nil {
return nil, ValidationError{Reason: "Neither id nor uid is specified in 'notifications' block, " + err.Error(), DashboardID: model.DashboardID, AlertID: model.ID, PanelID: model.PanelID}
return nil, ValidationError{Reason: "Unable to translate notification id to uid, " + err.Error(), DashboardID: model.DashboardID, AlertID: model.ID, PanelID: model.PanelID}
}
model.Notifications = append(model.Notifications, uid)
} else if uid, err := jsonModel.Get("uid").String(); err == nil {
model.Notifications = append(model.Notifications, uid)
} else {
return nil, ValidationError{Reason: "Neither id nor uid is specified in 'notifications' block, " + err.Error(), DashboardID: model.DashboardID, AlertID: model.ID, PanelID: model.PanelID}
}
}
model.AlertRuleTags = ruleDef.GetTagsFromSettings()
@@ -169,6 +172,29 @@ func NewRuleFromDBAlert(ruleDef *models.Alert) (*Rule, error) {
return model, nil
}
func translateNotificationIDToUID(id int64, orgID int64) (string, error) {
notificationUid, err := getAlertNotificationUidByIDAndOrgID(id, orgID)
if err != nil {
logger.Debug("Failed to translate Notification Id to Uid", "orgID", orgID, "Id", id)
return "", err
}
return notificationUid, nil
}
func getAlertNotificationUidByIDAndOrgID(notificationID int64, orgID int64) (string, error) {
query := &models.GetAlertNotificationUidQuery{
OrgId: orgID,
Id: notificationID,
}
if err := bus.Dispatch(query); err != nil {
return "", err
}
return query.Result, nil
}
// ConditionFactory is the function signature for creating `Conditions`.
type ConditionFactory func(model *simplejson.Json, index int) (Condition, error)