Support delete endpoint for folders (#96573)
* Support delete endpoint for folders * Include authorizer * Add test for delete verb * Add delete command to delete options * Pass query string to context to admission * Dont support nested folder deletion for now * Skip test if feature flag is present * Add test case * Remove comment * Only rely on the storage type config to run alerting tests * Dont change legacy subpath * Remove unised function * Add test case when an editor can delete alert rules * Lint
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/options"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@@ -694,15 +695,18 @@ func TestIntegrationRulerAccess(t *testing.T) {
|
||||
func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
opts := testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
EnableQuota: true,
|
||||
DisableAnonymous: true,
|
||||
ViewersCanEdit: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
APIServerStorageType: options.StorageTypeLegacy,
|
||||
}
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, path := testinfra.CreateGrafDir(t, opts)
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
@@ -725,8 +729,7 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
|
||||
createRule(t, apiClient, "default")
|
||||
|
||||
// First, let's have an editor create a rule within the folder/namespace.
|
||||
{
|
||||
t.Run("editor create a rule within the folder/namespace", func(t *testing.T) {
|
||||
u := fmt.Sprintf("http://editor:editor@%s/api/ruler/grafana/api/v1/rules", grafanaListedAddr)
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(u)
|
||||
@@ -746,68 +749,66 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
b = re.ReplaceAll(b, []byte(`"updated":"2021-05-19T19:47:55Z"`))
|
||||
|
||||
expectedGetRulesResponseBody := fmt.Sprintf(`{
|
||||
"default": [
|
||||
{
|
||||
"name": "arulegroup",
|
||||
"interval": "1m",
|
||||
"rules": [
|
||||
{
|
||||
"expr": "",
|
||||
"for": "2m",
|
||||
"labels": {
|
||||
"label1": "val1"
|
||||
},
|
||||
"annotations": {
|
||||
"annotation1": "val1"
|
||||
},
|
||||
"grafana_alert": {
|
||||
"id": 1,
|
||||
"orgId": 1,
|
||||
"title": "rule under folder default",
|
||||
"condition": "A",
|
||||
"data": [
|
||||
{
|
||||
"refId": "A",
|
||||
"queryType": "",
|
||||
"relativeTimeRange": {
|
||||
"from": 18000,
|
||||
"to": 10800
|
||||
},
|
||||
"datasourceUid": "__expr__",
|
||||
"model": {
|
||||
"expression": "2 + 3 > 1",
|
||||
"intervalMs": 1000,
|
||||
"maxDataPoints": 43200,
|
||||
"type": "math"
|
||||
"default": [
|
||||
{
|
||||
"name": "arulegroup",
|
||||
"interval": "1m",
|
||||
"rules": [
|
||||
{
|
||||
"expr": "",
|
||||
"for": "2m",
|
||||
"labels": {
|
||||
"label1": "val1"
|
||||
},
|
||||
"annotations": {
|
||||
"annotation1": "val1"
|
||||
},
|
||||
"grafana_alert": {
|
||||
"id": 1,
|
||||
"orgId": 1,
|
||||
"title": "rule under folder default",
|
||||
"condition": "A",
|
||||
"data": [
|
||||
{
|
||||
"refId": "A",
|
||||
"queryType": "",
|
||||
"relativeTimeRange": {
|
||||
"from": 18000,
|
||||
"to": 10800
|
||||
},
|
||||
"datasourceUid": "__expr__",
|
||||
"model": {
|
||||
"expression": "2 + 3 > 1",
|
||||
"intervalMs": 1000,
|
||||
"maxDataPoints": 43200,
|
||||
"type": "math"
|
||||
}
|
||||
}
|
||||
],
|
||||
"updated": "2021-05-19T19:47:55Z",
|
||||
"intervalSeconds": 60,
|
||||
"is_paused": false,
|
||||
"version": 1,
|
||||
"uid": "",
|
||||
"namespace_uid": %q,
|
||||
"rule_group": "arulegroup",
|
||||
"no_data_state": "NoData",
|
||||
"exec_err_state": "Alerting",
|
||||
"metadata": {
|
||||
"editor_settings": {
|
||||
"simplified_query_and_expressions_section": false,
|
||||
"simplified_notifications_section": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"updated": "2021-05-19T19:47:55Z",
|
||||
"intervalSeconds": 60,
|
||||
"is_paused": false,
|
||||
"version": 1,
|
||||
"uid": "",
|
||||
"namespace_uid": %q,
|
||||
"rule_group": "arulegroup",
|
||||
"no_data_state": "NoData",
|
||||
"exec_err_state": "Alerting",
|
||||
"metadata": {
|
||||
"editor_settings": {
|
||||
"simplified_query_and_expressions_section": false,
|
||||
"simplified_notifications_section": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`, namespaceUID)
|
||||
]
|
||||
}
|
||||
]
|
||||
}`, namespaceUID)
|
||||
assert.JSONEq(t, expectedGetRulesResponseBody, string(b))
|
||||
}
|
||||
|
||||
// Next, the editor can not delete the folder because it contains Grafana 8 alerts.
|
||||
{
|
||||
})
|
||||
t.Run("editor can not delete the folder because it contains Grafana 8 alerts", func(t *testing.T) {
|
||||
u := fmt.Sprintf("http://editor:editor@%s/api/folders/%s", grafanaListedAddr, namespaceUID)
|
||||
req, err := http.NewRequest(http.MethodDelete, u, nil)
|
||||
require.NoError(t, err)
|
||||
@@ -825,10 +826,8 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
err = json.Unmarshal(b, &errutilErr)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Folder cannot be deleted: folder is not empty", errutilErr.Message)
|
||||
}
|
||||
|
||||
// Next, the editor can delete the folder if forceDeleteRules is true.
|
||||
{
|
||||
})
|
||||
t.Run("editor can delete the folder if forceDeleteRules is true", func(t *testing.T) {
|
||||
u := fmt.Sprintf("http://editor:editor@%s/api/folders/%s?forceDeleteRules=true", grafanaListedAddr, namespaceUID)
|
||||
req, err := http.NewRequest(http.MethodDelete, u, nil)
|
||||
require.NoError(t, err)
|
||||
@@ -842,10 +841,8 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
_, err = io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
|
||||
// Finally, we ensure the rules were deleted.
|
||||
{
|
||||
})
|
||||
t.Run("editor can delete rules", func(t *testing.T) {
|
||||
u := fmt.Sprintf("http://editor:editor@%s/api/ruler/grafana/api/v1/rules", grafanaListedAddr)
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(u)
|
||||
@@ -859,7 +856,8 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
|
||||
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
assert.JSONEq(t, "{}", string(b))
|
||||
}
|
||||
})
|
||||
// TODO(@leonorfmartins): write tests for uni store when we are able to support it
|
||||
}
|
||||
|
||||
func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user