diff --git a/pkg/services/ngalert/models/alert_rule.go b/pkg/services/ngalert/models/alert_rule.go index 69219b8b09f..14f999202e3 100644 --- a/pkg/services/ngalert/models/alert_rule.go +++ b/pkg/services/ngalert/models/alert_rule.go @@ -624,7 +624,7 @@ func (alertRule *AlertRule) ValidateAlertRule(cfg setting.UnifiedAlertingSetting err = validateAlertRuleFields(alertRule) } if err != nil { - return err + return fmt.Errorf("%w: %s", ErrAlertRuleFailedValidation, err) } if alertRule.For < 0 { @@ -665,10 +665,10 @@ func validateAlertRuleFields(rule *AlertRule) error { func validateRecordingRuleFields(rule *AlertRule) error { metricName := prommodels.LabelValue(rule.Record.Metric) if !metricName.IsValid() { - return fmt.Errorf("%w: %s", ErrAlertRuleFailedValidation, "metric name for recording rule must be a valid utf8 string") + return errors.New("metric name for recording rule must be a valid utf8 string") } if !prommodels.IsValidMetricName(metricName) { - return fmt.Errorf("%w: %s", ErrAlertRuleFailedValidation, "metric name for recording rule must be a valid Prometheus metric name") + return errors.New("metric name for recording rule must be a valid Prometheus metric name") } ClearRecordingRuleIgnoredFields(rule) diff --git a/pkg/services/ngalert/models/alert_rule_test.go b/pkg/services/ngalert/models/alert_rule_test.go index b8e47df7bbf..2a2dd0abf66 100644 --- a/pkg/services/ngalert/models/alert_rule_test.go +++ b/pkg/services/ngalert/models/alert_rule_test.go @@ -18,6 +18,7 @@ import ( "golang.org/x/exp/maps" "gopkg.in/yaml.v3" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util/cmputil" ) @@ -1018,6 +1019,53 @@ func TestGeneratorFillsAllFields(t *testing.T) { require.FailNow(t, "AlertRule generator does not populate fields", "skipped fields: %v", maps.Keys(fields)) } +func TestValidateAlertRule(t *testing.T) { + t.Run("ExecErrState & NoDataState", func(t *testing.T) { + testCases := []struct { + name string + execErrState string + noDataState string + error bool + }{ + { + name: "invalid error state", + execErrState: "invalid", + error: true, + }, + { + name: "invalid no data state", + noDataState: "invalid", + error: true, + }, + { + name: "valid states", + error: false, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rule := RuleGen.With( + RuleMuts.WithIntervalSeconds(10), + ).Generate() + if tc.execErrState != "" { + rule.ExecErrState = ExecutionErrorState(tc.execErrState) + } + if tc.noDataState != "" { + rule.NoDataState = NoDataState(tc.noDataState) + } + + err := rule.ValidateAlertRule(setting.UnifiedAlertingSettings{BaseInterval: 10 * time.Second}) + if tc.error { + require.Error(t, err) + require.ErrorIs(t, err, ErrAlertRuleFailedValidation) + } else { + require.NoError(t, err) + } + }) + } + }) +} + func TestAlertRule_PrometheusRuleDefinition(t *testing.T) { tests := []struct { name string