mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Panel ID annotation cannot be set without Dashboard UID (#40019)
This commit is contained in:
parent
2f731d42f3
commit
935bd34a30
@ -503,6 +503,10 @@ func (st DBstore) validateAlertRule(alertRule ngmodels.AlertRule) error {
|
||||
return fmt.Errorf("%w: no organisation is found", ngmodels.ErrAlertRuleFailedValidation)
|
||||
}
|
||||
|
||||
if alertRule.DashboardUID == nil && alertRule.PanelID != nil {
|
||||
return fmt.Errorf("%w: cannot have Panel ID without a Dashboard UID", ngmodels.ErrAlertRuleFailedValidation)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -158,11 +158,17 @@ func (m *updateDashboardUIDPanelIDMigration) Exec(sess *xorm.Session, mg *migrat
|
||||
}
|
||||
panelID = &i
|
||||
}
|
||||
if _, err := sess.Exec(`UPDATE alert_rule SET dashboard_uid = ?, panel_id = ? WHERE id = ?`,
|
||||
dashboardUID,
|
||||
panelID,
|
||||
next.ID); err != nil {
|
||||
return fmt.Errorf("failed to set dashboard_uid and panel_id for alert rule: %w", err)
|
||||
// We do not want to set panel_id to a non-nil value when dashboard_uid is nil
|
||||
// as panel_id is not unique and so cannot be queried without its dashboard_uid.
|
||||
// This can happen where users have deleted the dashboard_uid annotation but kept
|
||||
// the panel_id annotation.
|
||||
if dashboardUID != nil {
|
||||
if _, err := sess.Exec(`UPDATE alert_rule SET dashboard_uid = ?, panel_id = ? WHERE id = ?`,
|
||||
dashboardUID,
|
||||
panelID,
|
||||
next.ID); err != nil {
|
||||
return fmt.Errorf("failed to set dashboard_uid and panel_id for alert rule: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -150,6 +150,60 @@ func TestPrometheusRules(t *testing.T) {
|
||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, string(b))
|
||||
}
|
||||
|
||||
// Check that we cannot create a rule that has a panel_id and no dashboard_uid
|
||||
{
|
||||
rules := apimodels.PostableRuleGroupConfig{
|
||||
Name: "anotherrulegroup",
|
||||
Rules: []apimodels.PostableExtendedRuleNode{
|
||||
{
|
||||
ApiRuleNode: &apimodels.ApiRuleNode{
|
||||
For: interval,
|
||||
Labels: map[string]string{},
|
||||
Annotations: map[string]string{"__panelId__": "1"},
|
||||
},
|
||||
// this rule does not explicitly set no data and error states
|
||||
// therefore it should get the default values
|
||||
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
|
||||
Title: "NeverCreated",
|
||||
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)
|
||||
require.NoError(t, err)
|
||||
|
||||
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", 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, 400, resp.StatusCode)
|
||||
require.JSONEq(t, `{"message":"failed to update rule group: invalid alert rule: cannot have Panel ID without a Dashboard UID"}`, string(b))
|
||||
}
|
||||
|
||||
// Now, let's see how this looks like.
|
||||
{
|
||||
promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules", grafanaListedAddr)
|
||||
|
Loading…
Reference in New Issue
Block a user