diff --git a/pkg/services/sqlstore/migrations/ualert/alert_rule.go b/pkg/services/sqlstore/migrations/ualert/alert_rule.go index 1778a415ade..e56f7c30ffa 100644 --- a/pkg/services/sqlstore/migrations/ualert/alert_rule.go +++ b/pkg/services/sqlstore/migrations/ualert/alert_rule.go @@ -6,6 +6,7 @@ import ( "time" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/infra/log" legacymodels "github.com/grafana/grafana/pkg/services/alerting/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/tsdb/graphite" @@ -105,7 +106,7 @@ func addMigrationInfo(da *dashAlert) (map[string]string, map[string]string) { return lbls, annotations } -func (m *migration) makeAlertRule(cond condition, da dashAlert, folderUID string) (*alertRule, error) { +func (m *migration) makeAlertRule(l log.Logger, cond condition, da dashAlert, folderUID string) (*alertRule, error) { lbls, annotations := addMigrationInfo(&da) annotations["message"] = da.Message var err error @@ -143,16 +144,8 @@ func (m *migration) makeAlertRule(cond condition, da dashAlert, folderUID string Labels: lbls, RuleGroupIndex: 1, IsPaused: isPaused, - } - - ar.NoDataState, err = transNoData(da.ParsedSettings.NoDataState) - if err != nil { - return nil, err - } - - ar.ExecErrState, err = transExecErr(da.ParsedSettings.ExecutionErrorState) - if err != nil { - return nil, err + NoDataState: transNoData(l, da.ParsedSettings.NoDataState), + ExecErrState: transExecErr(l, da.ParsedSettings.ExecutionErrorState), } // Label for routing and silences. @@ -271,32 +264,36 @@ func ruleAdjustInterval(freq int64) int64 { return freq - (freq % baseFreq) } -func transNoData(s string) (string, error) { +func transNoData(l log.Logger, s string) string { switch legacymodels.NoDataOption(s) { case legacymodels.NoDataSetOK: - return string(ngmodels.OK), nil // values from ngalert/models/rule + return string(ngmodels.OK) // values from ngalert/models/rule case "", legacymodels.NoDataSetNoData: - return string(ngmodels.NoData), nil + return string(ngmodels.NoData) case legacymodels.NoDataSetAlerting: - return string(ngmodels.Alerting), nil + return string(ngmodels.Alerting) case legacymodels.NoDataKeepState: - return string(ngmodels.NoData), nil // "keep last state" translates to no data because we now emit a special alert when the state is "noData". The result is that the evaluation will not return firing and instead we'll raise the special alert. + return string(ngmodels.NoData) // "keep last state" translates to no data because we now emit a special alert when the state is "noData". The result is that the evaluation will not return firing and instead we'll raise the special alert. + default: + l.Warn("Unable to translate execution of NoData state. Using default execution", "old", s, "new", ngmodels.NoData) + return string(ngmodels.NoData) } - return "", fmt.Errorf("unrecognized No Data setting %v", s) } -func transExecErr(s string) (string, error) { +func transExecErr(l log.Logger, s string) string { switch legacymodels.ExecutionErrorOption(s) { case "", legacymodels.ExecutionErrorSetAlerting: - return string(ngmodels.AlertingErrState), nil + return string(ngmodels.AlertingErrState) case legacymodels.ExecutionErrorKeepState: // Keep last state is translated to error as we now emit a // DatasourceError alert when the state is error - return string(ngmodels.ErrorErrState), nil + return string(ngmodels.ErrorErrState) case legacymodels.ExecutionErrorSetOk: - return string(ngmodels.OkErrState), nil + return string(ngmodels.OkErrState) + default: + l.Warn("Unable to translate execution of Error state. Using default execution", "old", s, "new", ngmodels.ErrorErrState) + return string(ngmodels.ErrorErrState) } - return "", fmt.Errorf("unrecognized Execution Error setting %v", s) } func normalizeRuleName(daName string, uid string) string { diff --git a/pkg/services/sqlstore/migrations/ualert/alert_rule_test.go b/pkg/services/sqlstore/migrations/ualert/alert_rule_test.go index 1e730fc8465..1938c51d892 100644 --- a/pkg/services/sqlstore/migrations/ualert/alert_rule_test.go +++ b/pkg/services/sqlstore/migrations/ualert/alert_rule_test.go @@ -5,9 +5,12 @@ import ( "strings" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/infra/log/logtest" + "github.com/grafana/grafana/pkg/services/ngalert/models" ) func TestMigrateAlertRuleQueries(t *testing.T) { @@ -93,7 +96,7 @@ func TestMakeAlertRule(t *testing.T) { da := createTestDashAlert() cnd := createTestDashAlertCondition() - ar, err := m.makeAlertRule(cnd, da, "folder") + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") require.NoError(t, err) require.Equal(t, da.Name, ar.Title) @@ -106,7 +109,7 @@ func TestMakeAlertRule(t *testing.T) { da.Name = strings.Repeat("a", DefaultFieldMaxLength+1) cnd := createTestDashAlertCondition() - ar, err := m.makeAlertRule(cnd, da, "folder") + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") require.NoError(t, err) require.Len(t, ar.Title, DefaultFieldMaxLength) @@ -123,7 +126,7 @@ func TestMakeAlertRule(t *testing.T) { da := createTestDashAlert() cnd := createTestDashAlertCondition() - ar, err := m.makeAlertRule(cnd, da, "folder") + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") require.NoError(t, err) require.False(t, ar.IsPaused) }) @@ -134,10 +137,32 @@ func TestMakeAlertRule(t *testing.T) { da.State = "paused" cnd := createTestDashAlertCondition() - ar, err := m.makeAlertRule(cnd, da, "folder") + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") require.NoError(t, err) require.True(t, ar.IsPaused) }) + + t.Run("use default if execution of NoData is not known", func(t *testing.T) { + m := newTestMigration(t) + da := createTestDashAlert() + da.ParsedSettings.NoDataState = uuid.NewString() + cnd := createTestDashAlertCondition() + + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") + require.Nil(t, err) + require.Equal(t, string(models.NoData), ar.NoDataState) + }) + + t.Run("use default if execution of Error is not known", func(t *testing.T) { + m := newTestMigration(t) + da := createTestDashAlert() + da.ParsedSettings.ExecutionErrorState = uuid.NewString() + cnd := createTestDashAlertCondition() + + ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder") + require.Nil(t, err) + require.Equal(t, string(models.ErrorErrState), ar.ExecErrState) + }) } func createTestDashAlert() dashAlert { diff --git a/pkg/services/sqlstore/migrations/ualert/ualert.go b/pkg/services/sqlstore/migrations/ualert/ualert.go index ecef514ef16..df8951c5022 100644 --- a/pkg/services/sqlstore/migrations/ualert/ualert.go +++ b/pkg/services/sqlstore/migrations/ualert/ualert.go @@ -377,7 +377,7 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { AlertId: da.Id, } } - rule, err := m.makeAlertRule(*newCond, da, folder.Uid) + rule, err := m.makeAlertRule(l, *newCond, da, folder.Uid) if err != nil { return err }