Alerting: unwrap upsert into insert and update function (#47731)

* Alerting: unwrap upsert into insert and update function

* add changelog entry

* remove changelog entry

* rename upsertrule to updaterule

* use directly alertrule model for inserts

* add test for updating a rule with a conflicting name
This commit is contained in:
Jean-Philippe Quéméner
2022-04-14 14:21:36 +02:00
committed by GitHub
parent c63086822d
commit 060ccacbf9
6 changed files with 231 additions and 111 deletions

View File

@@ -356,41 +356,8 @@ func TestAlertRuleConflictingTitle(t *testing.T) {
Login: "admin",
})
interval, err := model.ParseDuration("1m")
require.NoError(t, err)
rules := newTestingRuleConfig(t)
rules := apimodels.PostableRuleGroupConfig{
Name: "arulegroup",
Rules: []apimodels.PostableExtendedRuleNode{
{
ApiRuleNode: &apimodels.ApiRuleNode{
For: interval,
Labels: map[string]string{"label1": "val1"},
Annotations: map[string]string{"annotation1": "val1"},
},
// this rule does not explicitly set no data and error states
// therefore it should get the default values
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
Title: "AlwaysFiring",
Condition: "A",
Data: []ngmodels.AlertQuery{
{
RefID: "A",
RelativeTimeRange: ngmodels.RelativeTimeRange{
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
}`),
},
},
},
},
},
}
buf := bytes.Buffer{}
enc := json.NewEncoder(&buf)
err = enc.Encode(&rules)
@@ -410,7 +377,22 @@ func TestAlertRuleConflictingTitle(t *testing.T) {
assert.Equal(t, http.StatusAccepted, resp.StatusCode)
require.JSONEq(t, `{"message":"rule group updated successfully"}`, string(b))
// fetch the created rules, so we can get the uid's and trigger
// and update by reusing the uid's
resp, err = http.Get(u + "/" + rules.Name)
require.NoError(t, err)
var createdRuleGroup apimodels.GettableRuleGroupConfig
data, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
err = json.Unmarshal(data, &createdRuleGroup)
require.NoError(t, err)
require.Len(t, createdRuleGroup.Rules, 2)
t.Run("trying to create alert with same title under same folder should fail", func(t *testing.T) {
rules := newTestingRuleConfig(t)
buf := bytes.Buffer{}
enc := json.NewEncoder(&buf)
err = enc.Encode(&rules)
@@ -428,10 +410,36 @@ func TestAlertRuleConflictingTitle(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
require.JSONEq(t, `{"message": "failed to update rule group: failed to add or update rules: a conflicting alert rule is found: rule title under the same organisation and folder should be unique"}`, string(b))
require.JSONEq(t, `{"message": "failed to update rule group: failed to add rules: a conflicting alert rule is found: rule title under the same organisation and folder should be unique"}`, string(b))
})
t.Run("trying to update an alert to the title of an existing alert in the same folder should fail", func(t *testing.T) {
rules := newTestingRuleConfig(t)
rules.Rules[0].GrafanaManagedAlert.UID = createdRuleGroup.Rules[0].GrafanaManagedAlert.UID
rules.Rules[1].GrafanaManagedAlert.UID = createdRuleGroup.Rules[1].GrafanaManagedAlert.UID
rules.Rules[1].GrafanaManagedAlert.Title = "AlwaysFiring"
buf := bytes.Buffer{}
enc := json.NewEncoder(&buf)
err = enc.Encode(&rules)
require.NoError(t, err)
u := fmt.Sprintf("http://admin:admin@%s/api/ruler/grafana/api/v1/rules/folder1", grafanaListedAddr)
// nolint:gosec
resp, err := http.Post(u, "application/json", &buf)
require.NoError(t, err)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
require.JSONEq(t, `{"message": "failed to update rule group: failed to update rules: a conflicting alert rule is found: rule title under the same organisation and folder should be unique"}`, string(b))
})
t.Run("trying to create alert with same title under another folder should succeed", func(t *testing.T) {
rules := newTestingRuleConfig(t)
buf := bytes.Buffer{}
enc := json.NewEncoder(&buf)
err = enc.Encode(&rules)
@@ -800,3 +808,71 @@ func TestRulerRulesFilterByDashboard(t *testing.T) {
require.JSONEq(t, `{"message": "panel_id must be set with dashboard_uid"}`, string(b))
}
}
func newTestingRuleConfig(t *testing.T) apimodels.PostableRuleGroupConfig {
interval, err := model.ParseDuration("1m")
require.NoError(t, err)
firstRule := apimodels.PostableExtendedRuleNode{
ApiRuleNode: &apimodels.ApiRuleNode{
For: interval,
Labels: map[string]string{"label1": "val1"},
Annotations: map[string]string{"annotation1": "val1"},
},
// this rule does not explicitly set no data and error states
// therefore it should get the default values
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
Title: "AlwaysFiring",
Condition: "A",
Data: []ngmodels.AlertQuery{
{
RefID: "A",
RelativeTimeRange: ngmodels.RelativeTimeRange{
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
}`),
},
},
},
}
secondRule := apimodels.PostableExtendedRuleNode{
ApiRuleNode: &apimodels.ApiRuleNode{
For: interval,
Labels: map[string]string{"label1": "val1"},
Annotations: map[string]string{"annotation1": "val1"},
},
// this rule does not explicitly set no data and error states
// therefore it should get the default values
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
Title: "AlwaysFiring2",
Condition: "A",
Data: []ngmodels.AlertQuery{
{
RefID: "A",
RelativeTimeRange: ngmodels.RelativeTimeRange{
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
}`),
},
},
},
}
return apimodels.PostableRuleGroupConfig{
Name: "arulegroup",
Rules: []apimodels.PostableExtendedRuleNode{
firstRule,
secondRule,
},
}
}