Merge remote-tracking branch 'origin/main' into ensure-folder-annotation-when-supported
This commit is contained in:
@@ -1166,11 +1166,12 @@ func TestIntegrationConvertPrometheusEndpoints_Editor(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableRecordingRules: true,
|
||||
DisableAuthZClientCache: true,
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath)
|
||||
|
||||
@@ -137,7 +137,7 @@ func TestIntegrationTestReceivers(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -225,7 +225,7 @@ func TestIntegrationTestReceivers(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -307,7 +307,7 @@ func TestIntegrationTestReceivers(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -400,7 +400,7 @@ func TestIntegrationTestReceivers(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -506,7 +506,7 @@ func TestIntegrationTestReceivers(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -805,7 +805,7 @@ func TestIntegrationTestReceiversAlertCustomization(t *testing.T) {
|
||||
"__dashboardUid__": "dashboard_uid",
|
||||
"__orgId__": "1",
|
||||
"__panelId__": "1",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]",
|
||||
"__value_string__": "[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='reduce' value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} type='threshold' value=1 ]",
|
||||
"__values__": "{\"B\":22,\"C\":1}"
|
||||
},
|
||||
"labels": {
|
||||
@@ -2440,7 +2440,7 @@ var expEmailNotifications = []*notifications.SendEmailCommandSync{
|
||||
PanelURL: "",
|
||||
OrgID: util.Pointer(int64(1)),
|
||||
Values: map[string]float64{"A": 1},
|
||||
ValueString: "[ var='A' labels={} value=1 ]",
|
||||
ValueString: "[ var='A' labels={} type='math' value=1 ]",
|
||||
},
|
||||
},
|
||||
"GroupLabels": template.KV{"alertname": "EmailAlert"},
|
||||
@@ -2594,10 +2594,10 @@ var expNonEmailNotifications = map[string][]string{
|
||||
"grafana_folder": "default"
|
||||
},
|
||||
"annotations": {},
|
||||
"startsAt": "%s",
|
||||
"startsAt": "%s",
|
||||
"values": {"A": 1},
|
||||
"valueString": "[ var='A' labels={} value=1 ]",
|
||||
"endsAt": "0001-01-01T00:00:00Z",
|
||||
"valueString": "[ var='A' labels={} type='math' value=1 ]",
|
||||
"endsAt": "0001-01-01T00:00:00Z",
|
||||
"generatorURL": "http://localhost:3000/alerting/grafana/UID_WebhookAlert/view?orgId=1",
|
||||
"fingerprint": "15c59b0a380bd9f1",
|
||||
"silenceURL": "http://localhost:3000/alerting/silence/new?alertmanager=grafana&matcher=__alert_rule_uid__%%3DUID_WebhookAlert&orgId=1",
|
||||
@@ -2768,10 +2768,10 @@ var expNonEmailNotifications = map[string][]string{
|
||||
"alertname": "AlertmanagerAlert",
|
||||
"grafana_folder": "default"
|
||||
},
|
||||
"annotations": {
|
||||
"__orgId__":"1",
|
||||
"annotations": {
|
||||
"__orgId__":"1",
|
||||
"__values__": "{\"A\":1}",
|
||||
"__value_string__": "[ var='A' labels={} value=1 ]"
|
||||
"__value_string__": "[ var='A' labels={} type='math' value=1 ]"
|
||||
},
|
||||
"startsAt": "%s",
|
||||
"endsAt": "0001-01-01T00:00:00Z",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -364,8 +365,6 @@ func TestIntegrationPrometheusRules(t *testing.T) {
|
||||
func TestIntegrationPrometheusRulesPagination(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
@@ -388,23 +387,30 @@ func TestIntegrationPrometheusRulesPagination(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create 3 rule groups with different numbers of rules
|
||||
// Group 1: 5 rules, Group 2: 3 rules, Group 3: 2 rules (total: 10 rules)
|
||||
// Group 1: 5 rules with team=backend
|
||||
// Group 2: 3 rules with team=frontend
|
||||
// Group 3: 2 rules with team=platform
|
||||
for groupIdx := 1; groupIdx <= 3; groupIdx++ {
|
||||
var rulesCount int
|
||||
var team string
|
||||
switch groupIdx {
|
||||
case 1:
|
||||
rulesCount = 5
|
||||
team = "backend"
|
||||
case 2:
|
||||
rulesCount = 3
|
||||
team = "frontend"
|
||||
case 3:
|
||||
rulesCount = 2
|
||||
team = "platform"
|
||||
}
|
||||
|
||||
rules := make([]apimodels.PostableExtendedRuleNode, rulesCount)
|
||||
for i := 0; i < rulesCount; i++ {
|
||||
rules[i] = apimodels.PostableExtendedRuleNode{
|
||||
ApiRuleNode: &apimodels.ApiRuleNode{
|
||||
For: &interval,
|
||||
For: &interval,
|
||||
Labels: map[string]string{"team": team},
|
||||
},
|
||||
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
|
||||
Title: fmt.Sprintf("rule-%d-%d", groupIdx, i+1),
|
||||
@@ -514,6 +520,61 @@ func TestIntegrationPrometheusRulesPagination(t *testing.T) {
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
require.Len(t, result.Data.RuleGroups, 0, "should return no groups")
|
||||
})
|
||||
|
||||
t.Run("with rule_matcher filter returns only matching rules", func(t *testing.T) {
|
||||
matcher := url.QueryEscape(`{"name":"team","value":"frontend","isRegex":false,"isEqual":true}`)
|
||||
promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules?rule_matcher=%s", grafanaListedAddr, matcher)
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(promRulesURL)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
var result apimodels.RuleResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Should only return group-2 (team=frontend, 3 rules)
|
||||
foundGroups := []string{}
|
||||
total := 0
|
||||
for _, group := range result.Data.RuleGroups {
|
||||
foundGroups = append(foundGroups, group.Name)
|
||||
total += len(group.Rules)
|
||||
}
|
||||
require.Equal(t, []string{"group-2"}, foundGroups)
|
||||
require.Equal(t, 3, total)
|
||||
})
|
||||
|
||||
t.Run("with rule_matcher regex filter", func(t *testing.T) {
|
||||
// Filter with regex team=~plat.* (should match group-3 with team=platform)
|
||||
matcher := url.QueryEscape(`{"name":"team","value":"plat.*","isRegex":true,"isEqual":true}`)
|
||||
promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules?rule_matcher=%s", grafanaListedAddr, matcher)
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(promRulesURL)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
var result apimodels.RuleResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Should only return group-3 (team=platform matches plat.*)
|
||||
foundGroups := []string{}
|
||||
total := 0
|
||||
for _, group := range result.Data.RuleGroups {
|
||||
foundGroups = append(foundGroups, group.Name)
|
||||
total += len(group.Rules)
|
||||
}
|
||||
require.Equal(t, []string{"group-3"}, foundGroups)
|
||||
require.Equal(t, 2, total)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
|
||||
|
||||
@@ -1192,10 +1192,11 @@ func TestIntegrationExportFileProvisionContactPoints(t *testing.T) {
|
||||
|
||||
func TestIntegrationFullpath(t *testing.T) {
|
||||
dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
DisableAuthZClientCache: true,
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p)
|
||||
|
||||
@@ -53,10 +53,11 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
DisableAuthZClientCache: true,
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p)
|
||||
@@ -360,10 +361,11 @@ func TestIntegrationAlertRuleNestedPermissions(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
DisableAuthZClientCache: true,
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p)
|
||||
@@ -1429,10 +1431,11 @@ func TestIntegrationRuleGroupSequence(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
DisableAuthZClientCache: true,
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
|
||||
@@ -150,8 +150,8 @@ func TestGrafanaRuleConfig(t *testing.T) {
|
||||
for i, alert := range result {
|
||||
require.NotEmpty(t, alert.Annotations["values.B"])
|
||||
require.NotEmpty(t, alert.Annotations["values.C"])
|
||||
valueB := fmt.Sprintf("[ var='B' labels={state=%s} value=%s ]", dynamicLabels[i], alert.Annotations["values.B"])
|
||||
valueC := fmt.Sprintf("[ var='C' labels={state=%s} value=%s ]", dynamicLabels[i], alert.Annotations["values.C"])
|
||||
valueB := fmt.Sprintf("[ var='B' labels={state=%s} type='reduce' value=%s ]", dynamicLabels[i], alert.Annotations["values.B"])
|
||||
valueC := fmt.Sprintf("[ var='C' labels={state=%s} type='threshold' value=%s ]", dynamicLabels[i], alert.Annotations["values.C"])
|
||||
require.Contains(t, alert.Annotations["value"], valueB)
|
||||
require.Contains(t, alert.Annotations["value"], valueC)
|
||||
}
|
||||
@@ -172,8 +172,8 @@ func TestGrafanaRuleConfig(t *testing.T) {
|
||||
for i, alert := range result {
|
||||
require.NotEmpty(t, alert.Labels["values.B"])
|
||||
require.NotEmpty(t, alert.Labels["values.C"])
|
||||
valueB := fmt.Sprintf("[ var='B' labels={state=%s} value=%s ]", dynamicLabels[i], alert.Labels["values.B"])
|
||||
valueC := fmt.Sprintf("[ var='C' labels={state=%s} value=%s ]", dynamicLabels[i], alert.Labels["values.C"])
|
||||
valueB := fmt.Sprintf("[ var='B' labels={state=%s} type='reduce' value=%s ]", dynamicLabels[i], alert.Labels["values.B"])
|
||||
valueC := fmt.Sprintf("[ var='C' labels={state=%s} type='threshold' value=%s ]", dynamicLabels[i], alert.Labels["values.C"])
|
||||
require.Contains(t, alert.Labels["value"], valueB)
|
||||
require.Contains(t, alert.Labels["value"], valueC)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "",
|
||||
@@ -208,6 +209,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "",
|
||||
@@ -352,6 +354,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "",
|
||||
@@ -451,6 +454,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -748,6 +752,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -910,6 +915,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -1194,6 +1200,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -1392,6 +1399,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -1793,6 +1801,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": false,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -1820,6 +1829,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -2318,6 +2328,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -2610,6 +2621,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "token",
|
||||
@@ -2628,6 +2640,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": false,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -2953,6 +2966,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -3303,6 +3317,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "",
|
||||
@@ -3393,6 +3408,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": false,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -3474,6 +3490,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -3916,6 +3933,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -4114,6 +4132,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": false,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": false,
|
||||
"dependsOn": "",
|
||||
@@ -4201,6 +4220,7 @@
|
||||
"is": ""
|
||||
},
|
||||
"required": true,
|
||||
"protected": true,
|
||||
"validationRule": "",
|
||||
"secure": true,
|
||||
"dependsOn": "secret",
|
||||
|
||||
@@ -32,8 +32,9 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
EnableFeatureToggles: []string{featuremgmt.FlagAnnotationPermissionUpdate},
|
||||
DisableAuthZClientCache: true,
|
||||
DisableAnonymous: true,
|
||||
EnableFeatureToggles: []string{featuremgmt.FlagAnnotationPermissionUpdate},
|
||||
})
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
noneUserID := tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -38,8 +39,15 @@ func TestMain(m *testing.M) {
|
||||
func TestIntegrationDashboardServiceValidation(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
unifiedConfig := make(map[string]setting.UnifiedStorageConfig)
|
||||
for _, resource := range []string{"folders.folder.grafana.app", "dashboards.dashboard.grafana.app"} {
|
||||
unifiedConfig[resource] = setting.UnifiedStorageConfig{
|
||||
EnableMigration: true,
|
||||
}
|
||||
}
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
DisableAnonymous: true,
|
||||
UnifiedStorageConfig: unifiedConfig,
|
||||
})
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
@@ -218,11 +226,12 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("When updating uid with id", func(t *testing.T) {
|
||||
dashboardWithDuplicatedLegacyAnnotation := "new-uid"
|
||||
t.Run("When saving a dashboard with an already used legacy ID", func(t *testing.T) {
|
||||
resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
|
||||
"dashboard": map[string]interface{}{
|
||||
"id": savedDashInFolder.ID, // nolint:staticcheck
|
||||
"uid": "new-uid",
|
||||
"uid": dashboardWithDuplicatedLegacyAnnotation,
|
||||
"title": "Updated title",
|
||||
},
|
||||
"folderUid": savedDashInFolder.FolderUID,
|
||||
@@ -233,7 +242,49 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) {
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("When updating uid with a dashboard already using that uid", func(t *testing.T) {
|
||||
|
||||
t.Run("When updating a dashboard with legacy ID in multiple dashboards", func(t *testing.T) {
|
||||
resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
|
||||
"dashboard": map[string]interface{}{
|
||||
"id": savedDashInFolder.ID, // nolint:staticcheck
|
||||
"uid": savedDashInGeneralFolder.UID,
|
||||
"title": "Updated title",
|
||||
},
|
||||
"folderUid": savedDashInFolder.FolderUID,
|
||||
"overwrite": true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
// Delete the dashboard with duplicated legacy ID annotation
|
||||
u := fmt.Sprintf("http://admin:admin@%s/api/dashboards/uid/%s", grafanaListedAddr, dashboardWithDuplicatedLegacyAnnotation)
|
||||
req, err := http.NewRequest("DELETE", u, nil)
|
||||
require.NoError(t, err)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("When updating a dashboard already using that uid", func(t *testing.T) {
|
||||
resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
|
||||
"dashboard": map[string]interface{}{
|
||||
"id": savedDashInFolder.ID,
|
||||
"uid": savedDashInFolder.UID,
|
||||
"title": "Dashboard with existing UID",
|
||||
},
|
||||
"folderUid": savedDashInFolder.FolderUID,
|
||||
"overwrite": true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("When updating id with a dashboard already using that uid", func(t *testing.T) {
|
||||
resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
|
||||
"dashboard": map[string]interface{}{
|
||||
"id": savedDashInFolder.ID, // nolint:staticcheck
|
||||
@@ -266,6 +317,31 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) {
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
// Obs: in legacy, the dashboard request would fail
|
||||
// After the dashboard is created, the user can see that there is an error with the library panel and can remove them manually
|
||||
t.Run("When creating a dashboard that references a non-existent library panel", func(t *testing.T) {
|
||||
resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
|
||||
"dashboard": map[string]interface{}{
|
||||
"title": "Bad dashboard",
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"gridPos": map[string]int{"h": 0, "w": 0, "x": 0, "y": 0},
|
||||
"libraryPanel": map[string]string{
|
||||
"name": "Bad panel",
|
||||
"uid": "invalid-uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
_, err = io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
err = resp.Body.Close()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationDashboardQuota(t *testing.T) {
|
||||
@@ -303,7 +379,7 @@ func TestIntegrationDashboardQuota(t *testing.T) {
|
||||
dashboardDTO := &plugindashboards.PluginDashboard{}
|
||||
err = json.Unmarshal(b, dashboardDTO)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1, dashboardDTO.DashboardId)
|
||||
require.EqualValues(t, "just testing", dashboardDTO.Title)
|
||||
})
|
||||
|
||||
t.Run("when quota limit exceeds importing a dashboard should fail", func(t *testing.T) {
|
||||
@@ -392,7 +468,7 @@ providers:
|
||||
dashboardUID = d.UID
|
||||
dashboardID = d.ID // nolint:staticcheck
|
||||
}
|
||||
assert.Equal(t, int64(1), dashboardID)
|
||||
assert.Len(t, *dashboardList, 1)
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
@@ -752,7 +828,7 @@ func TestIntegrationImportDashboardWithLibraryPanels(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Library Panel 2",
|
||||
"title": "Library Panel 2",
|
||||
"type": "stat",
|
||||
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
|
||||
"libraryPanel": {
|
||||
@@ -776,7 +852,7 @@ func TestIntegrationImportDashboardWithLibraryPanels(t *testing.T) {
|
||||
}
|
||||
},
|
||||
"test-lib-panel-2": {
|
||||
"uid": "test-lib-panel-2",
|
||||
"uid": "test-lib-panel-2",
|
||||
"name": "Test Library Panel 2",
|
||||
"kind": 1,
|
||||
"type": "stat",
|
||||
@@ -986,7 +1062,8 @@ func TestIntegrationDashboardServicePermissions(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
DisableAnonymous: true,
|
||||
DisableAuthZClientCache: true,
|
||||
})
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
|
||||
Reference in New Issue
Block a user