[v10.3.x] Alerting: Don't validate rules on group update if they've only been reordered (#85374)

Alerting: Don't validate rules on group update if they've only been reordered (#81841)

---------

Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
(cherry picked from commit b7bbc5058f)

Co-authored-by: William Wernert <william.wernert@grafana.com>
This commit is contained in:
grafana-delivery-bot[bot]
2024-03-28 12:41:14 -04:00
committed by GitHub
co-authored by William Wernert
parent df26054967
commit 81a213ed3d
2 changed files with 42 additions and 3 deletions
+19
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/http"
"slices"
"strings"
"time"
@@ -48,6 +49,9 @@ var (
errProvisionedResource = errors.New("request affects resources created via provisioning API")
)
// ignore fields that are not part of the rule definition
var ignoreFieldsForValidate = [...]string{"RuleGroupIndex"}
// RouteDeleteAlertRules deletes all alert rules the user is authorized to access in the given namespace
// or, if non-empty, a specific group of rules in the namespace.
// Returns http.StatusForbidden if user does not have access to any of the rules that match the filter.
@@ -499,6 +503,9 @@ func validateQueries(ctx context.Context, groupChanges *store.GroupDelta, valida
}
if len(groupChanges.Update) > 0 {
for _, upd := range groupChanges.Update {
if !shouldValidate(upd) {
continue
}
err := validator.Validate(eval.NewContext(ctx, user), upd.New.GetEvalCondition())
if err != nil {
return fmt.Errorf("%w '%s' (UID: %s): %s", ngmodels.ErrAlertRuleFailedValidation, upd.New.Title, upd.New.UID, err.Error())
@@ -508,6 +515,18 @@ func validateQueries(ctx context.Context, groupChanges *store.GroupDelta, valida
return nil
}
// shouldValidate returns true if the rule is not paused and there are changes in the rule that are not ignored
func shouldValidate(delta store.RuleDelta) bool {
for _, diff := range delta.Diff {
if !slices.Contains(ignoreFieldsForValidate[:], diff.Path) {
return true
}
}
// TODO: consider also checking if rule will be paused after the update
return false
}
// getAuthorizedRuleByUid fetches all rules in group to which the specified rule belongs, and checks whether the user is authorized to access the group.
// A user is authorized to access a group of rules only when it has permission to query all data sources used by all rules in this group.
// Returns rule identified by provided UID or ErrAuthorization if user is not authorized to access the rule.
+23 -3
View File
@@ -9,6 +9,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"slices"
"testing"
"time"
@@ -30,6 +31,7 @@ import (
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/util/cmputil"
"github.com/grafana/grafana/pkg/web"
)
@@ -537,7 +539,24 @@ func TestValidateQueries(t *testing.T) {
New: models.AlertRuleGen(func(rule *models.AlertRule) {
rule.Condition = "Update_New"
})(),
Diff: nil,
Diff: cmputil.DiffReport{
cmputil.Diff{
Path: "SomeField",
},
},
},
{
Existing: models.AlertRuleGen(func(rule *models.AlertRule) {
rule.Condition = "Update_Index_Existing"
})(),
New: models.AlertRuleGen(func(rule *models.AlertRule) {
rule.Condition = "Update_Index_New"
})(),
Diff: cmputil.DiffReport{
cmputil.Diff{
Path: "RuleGroupIndex",
},
},
},
},
Delete: []*models.AlertRule{
@@ -547,12 +566,13 @@ func TestValidateQueries(t *testing.T) {
},
}
t.Run("should validate New and Updated only", func(t *testing.T) {
t.Run("should not validate deleted rules or updated rules with ignored fields", func(t *testing.T) {
validator := &recordingConditionValidator{}
err := validateQueries(context.Background(), &delta, validator, nil)
require.NoError(t, err)
noValidate := []string{"Deleted", "Update_Index_New"}
for _, condition := range validator.recorded {
if condition.Condition == "New" || condition.Condition == "Update_New" {
if !slices.Contains(noValidate, condition.Condition) {
continue
}
assert.Failf(t, "validated unexpected condition", "condition '%s' was validated but should not", condition.Condition)