Alerting: Copy alert rule metadata when the rule is updated via provisioning API (#93723)

Alerting: Copy alert rule metadata when the rule is updated
This commit is contained in:
Alexander Akhmetov
2024-09-25 22:31:02 +02:00
committed by GitHub
parent 277d82db9a
commit b9964865cb
4 changed files with 91 additions and 1 deletions
@@ -795,6 +795,13 @@ func PatchPartialAlertRule(existingRule *AlertRule, ruleToPatch *AlertRuleWithOp
if !ruleToPatch.HasPause {
ruleToPatch.IsPaused = existingRule.IsPaused
}
// Currently metadata contains only editor settings, so we can just copy it.
// If we add more fields to metadata, we might need to handle them separately,
// and/or merge or update their values.
if ruleToPatch.Metadata == (AlertRuleMetadata{}) {
ruleToPatch.Metadata = existingRule.Metadata
}
}
func ValidateRuleGroupInterval(intervalSeconds, baseIntervalSeconds int64) error {
@@ -253,10 +253,17 @@ func TestPatchPartialAlertRule(t *testing.T) {
r.IsPaused = true
},
},
{
name: "No metadata",
mutator: func(r *AlertRuleWithOptionals) {
r.Metadata = AlertRuleMetadata{}
},
},
}
gen := RuleGen.With(
RuleMuts.WithFor(time.Duration(rand.Int63n(1000) + 1)),
RuleMuts.WithFor(time.Duration(rand.Int63n(1000)+1)),
RuleMuts.WithEditorSettingsSimplifiedQueryAndExpressionsSection(true),
)
for _, testCase := range testCases {
@@ -598,6 +598,14 @@ func (service *AlertRuleService) UpdateAlertRule(ctx context.Context, user ident
rule.Updated = time.Now()
rule.ID = storedRule.ID
rule.IntervalSeconds = storedRule.IntervalSeconds
// Currently metadata contains only editor settings, so we can just copy it.
// If we add more fields to metadata, we might need to handle them separately,
// and/or merge or update their values.
if rule.Metadata == (models.AlertRuleMetadata{}) {
rule.Metadata = storedRule.Metadata
}
err = rule.SetDashboardAndPanelFromAnnotations()
if err != nil {
return models.AlertRule{}, err
@@ -183,6 +183,74 @@ func TestAlertRuleService(t *testing.T) {
require.Equal(t, int64(2), readGroup.Rules[0].Version)
})
t.Run("updating a group should not override its rules editor settings", func(t *testing.T) {
namespaceUID := "my-namespace"
groupTitle := "test-group-123"
// create the rule group via the rule store, to persist the editor settings
rule := createTestRule(util.GenerateShortUID(), groupTitle, orgID, namespaceUID)
ruleMetadata := models.AlertRuleMetadata{
EditorSettings: models.EditorSettings{
SimplifiedQueryAndExpressionsSection: true,
},
}
rule.Metadata = ruleMetadata
r, err := ruleService.ruleStore.InsertAlertRules(context.Background(), []models.AlertRule{rule})
require.NoError(t, err)
require.Len(t, r, 1)
// Set the UID for the rule to update it
rule.UID = r[0].UID
// clear the metadata to check that the existing metadata is not overridden
rule.Metadata = models.AlertRuleMetadata{}
// Now update the rule group with the rule to update its metadata
group := models.AlertRuleGroup{
Title: groupTitle,
Interval: 60,
FolderUID: namespaceUID,
Rules: []models.AlertRule{rule},
}
err = ruleService.ReplaceRuleGroup(context.Background(), u, group, models.ProvenanceAPI)
require.NoError(t, err)
readGroup, err := ruleService.GetRuleGroup(context.Background(), u, namespaceUID, groupTitle)
require.NoError(t, err)
require.NotEmpty(t, readGroup.Rules)
require.Len(t, readGroup.Rules, 1)
// check that the metadata is still there
require.Equal(t, ruleMetadata, readGroup.Rules[0].Metadata)
})
t.Run("updating a rule should not override its editor settings", func(t *testing.T) {
rule := createTestRule(util.GenerateShortUID(), "my-group", orgID, "my-folder")
ruleMetadata := models.AlertRuleMetadata{
EditorSettings: models.EditorSettings{
SimplifiedQueryAndExpressionsSection: true,
},
}
rule.Metadata = ruleMetadata
r, err := ruleService.ruleStore.InsertAlertRules(context.Background(), []models.AlertRule{rule})
require.NoError(t, err)
require.Len(t, r, 1)
// Set the UID for the rule to update it
rule.UID = r[0].UID
// clear the metadata to check that the existing metadata is not overridden
rule.Metadata = models.AlertRuleMetadata{}
// Update the rule
_, err = ruleService.UpdateAlertRule(context.Background(), u, rule, models.ProvenanceAPI)
require.NoError(t, err)
// Read the rule and check that the editor settings are preserved
readRule, _, err := ruleService.GetAlertRule(context.Background(), u, rule.UID)
require.NoError(t, err)
require.Equal(t, ruleMetadata, readRule.Metadata)
})
t.Run("updating a group to temporarily overlap rule names should not throw unique constraint", func(t *testing.T) {
var orgID int64 = 1
group := models.AlertRuleGroup{