Alerting: Distinguish conflict violation errors (#86634)
* update generator to set ID = 0 and do not set 0 if unique is needed * return proper message when the constraint violation
This commit is contained in:
@@ -169,7 +169,7 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
|
||||
for i := range newRules {
|
||||
if _, err := sess.Insert(&newRules[i]); err != nil {
|
||||
if st.SQLStore.GetDialect().IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleConflict(newRules[i], ngmodels.ErrAlertRuleUniqueConstraintViolation)
|
||||
return ruleConstraintViolationToErr(newRules[i], err)
|
||||
}
|
||||
return fmt.Errorf("failed to create new rules: %w", err)
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []ngmodels.UpdateR
|
||||
if updated, err := sess.ID(r.Existing.ID).AllCols().Update(r.New); err != nil || updated == 0 {
|
||||
if err != nil {
|
||||
if st.SQLStore.GetDialect().IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleConflict(r.New, ngmodels.ErrAlertRuleUniqueConstraintViolation)
|
||||
return ruleConstraintViolationToErr(r.New, err)
|
||||
}
|
||||
return fmt.Errorf("failed to update rule [%s] %s: %w", r.New.UID, r.New.Title, err)
|
||||
}
|
||||
@@ -758,3 +758,14 @@ func (st DBstore) RenameReceiverInNotificationSettings(ctx context.Context, orgI
|
||||
}
|
||||
return len(updates), st.UpdateAlertRules(ctx, updates)
|
||||
}
|
||||
|
||||
func ruleConstraintViolationToErr(rule ngmodels.AlertRule, err error) error {
|
||||
msg := err.Error()
|
||||
if strings.Contains(msg, "UQE_alert_rule_org_id_namespace_uid_title") || strings.Contains(msg, "alert_rule.org_id, alert_rule.namespace_uid, alert_rule.title") {
|
||||
return ngmodels.ErrAlertRuleConflict(rule, ngmodels.ErrAlertRuleUniqueConstraintViolation)
|
||||
} else if strings.Contains(msg, "UQE_alert_rule_org_id_uid") || strings.Contains(msg, "alert_rule.org_id, alert_rule.uid") {
|
||||
return ngmodels.ErrAlertRuleConflict(rule, errors.New("rule UID under the same organisation should be unique"))
|
||||
} else {
|
||||
return ngmodels.ErrAlertRuleConflict(rule, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,6 +603,7 @@ func TestIntegrationInsertAlertRules(t *testing.T) {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
orgID := int64(1)
|
||||
sqlStore := db.InitTestDB(t)
|
||||
cfg := setting.NewCfg()
|
||||
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
|
||||
@@ -613,7 +614,7 @@ func TestIntegrationInsertAlertRules(t *testing.T) {
|
||||
Cfg: cfg.UnifiedAlerting,
|
||||
}
|
||||
|
||||
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(1), withIntervalMatching(store.Cfg.BaseInterval)))
|
||||
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(orgID), withIntervalMatching(store.Cfg.BaseInterval)))
|
||||
deref := make([]models.AlertRule, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
deref = append(deref, *rule)
|
||||
@@ -641,14 +642,30 @@ func TestIntegrationInsertAlertRules(t *testing.T) {
|
||||
require.Truef(t, found, "Rule with key %#v was not found in database", keyWithID)
|
||||
}
|
||||
|
||||
_, err = store.InsertAlertRules(context.Background(), []models.AlertRule{deref[0]})
|
||||
require.ErrorIs(t, err, models.ErrAlertRuleUniqueConstraintViolation)
|
||||
require.NotEqual(t, deref[0].UID, "")
|
||||
require.NotEqual(t, deref[0].Title, "")
|
||||
require.NotEqual(t, deref[0].NamespaceUID, "")
|
||||
require.ErrorContains(t, err, deref[0].UID)
|
||||
require.ErrorContains(t, err, deref[0].Title)
|
||||
require.ErrorContains(t, err, deref[0].NamespaceUID)
|
||||
t.Run("fail to insert rules with same ID", func(t *testing.T) {
|
||||
_, err = store.InsertAlertRules(context.Background(), []models.AlertRule{deref[0]})
|
||||
require.ErrorIs(t, err, models.ErrAlertRuleConflictBase)
|
||||
})
|
||||
t.Run("fail insert rules with the same title in a folder", func(t *testing.T) {
|
||||
cp := models.CopyRule(&deref[0])
|
||||
cp.UID = cp.UID + "-new"
|
||||
_, err = store.InsertAlertRules(context.Background(), []models.AlertRule{*cp})
|
||||
require.ErrorIs(t, err, models.ErrAlertRuleConflictBase)
|
||||
require.ErrorIs(t, err, models.ErrAlertRuleUniqueConstraintViolation)
|
||||
require.NotEqual(t, deref[0].UID, "")
|
||||
require.NotEqual(t, deref[0].Title, "")
|
||||
require.NotEqual(t, deref[0].NamespaceUID, "")
|
||||
require.ErrorContains(t, err, deref[0].UID)
|
||||
require.ErrorContains(t, err, deref[0].Title)
|
||||
require.ErrorContains(t, err, deref[0].NamespaceUID)
|
||||
})
|
||||
t.Run("should not let insert rules with the same UID", func(t *testing.T) {
|
||||
cp := models.CopyRule(&deref[0])
|
||||
cp.Title = "unique-test-title"
|
||||
_, err = store.InsertAlertRules(context.Background(), []models.AlertRule{*cp})
|
||||
require.ErrorIs(t, err, models.ErrAlertRuleConflictBase)
|
||||
require.ErrorContains(t, err, "rule UID under the same organisation should be unique")
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationAlertRulesNotificationSettings(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user