Alerting: Rule version history API (#99041)
* implement store method to read rule versions * implement request handler * declare a new endpoint * fix fake to return correct response * add tests * add integration tests * rename history to versions * apply diff from swagger CI step Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com> --------- Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
@@ -241,6 +241,18 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
||||
require.Len(t, export.Groups, 1)
|
||||
require.Equal(t, expected, export.Groups[0])
|
||||
})
|
||||
|
||||
t.Run("Get versions of any rule", func(t *testing.T) {
|
||||
for _, groups := range allRules { // random rule from each folder
|
||||
group := groups[rand.Intn(len(groups))]
|
||||
rule := group.Rules[rand.Intn(len(group.Rules))]
|
||||
versions, status, raw := apiClient.GetRuleVersionsWithStatus(t, rule.GrafanaManagedAlert.UID)
|
||||
if assert.Equalf(t, http.StatusOK, status, "Expected status 200, got %d: %s", status, raw) {
|
||||
assert.NotEmpty(t, versions)
|
||||
assert.Equal(t, rule, versions[0]) // the first version in the collection should always be the current
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("when permissions for folder2 removed", func(t *testing.T) {
|
||||
@@ -310,6 +322,12 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
||||
require.Equal(t, http.StatusForbidden, status)
|
||||
})
|
||||
|
||||
t.Run("Versions of rule", func(t *testing.T) {
|
||||
uid := allRules["folder2"][0].Rules[0].GrafanaManagedAlert.UID
|
||||
_, status, raw := apiClient.GetRuleVersionsWithStatus(t, uid)
|
||||
require.Equalf(t, http.StatusForbidden, status, "Expected status 403, got %d: %s", status, raw)
|
||||
})
|
||||
|
||||
t.Run("when all permissions are revoked", func(t *testing.T) {
|
||||
removeFolderPermission(t, permissionsStore, 1, userID, org.RoleEditor, "folder1")
|
||||
apiClient.ReloadCachedPermissions(t)
|
||||
@@ -4315,6 +4333,95 @@ func TestIntegrationRuleUpdateAllDatabases(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationRuleVersions(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
EnableQuota: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p)
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleEditor),
|
||||
Password: "password",
|
||||
Login: "grafana",
|
||||
})
|
||||
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "grafana", "password")
|
||||
|
||||
// Create the namespace we'll save our alerts to.
|
||||
apiClient.CreateFolder(t, "folder1", "folder1")
|
||||
|
||||
postGroupRaw, err := testData.ReadFile(path.Join("test-data", "rulegroup-1-post.json"))
|
||||
require.NoError(t, err)
|
||||
var group1 apimodels.PostableRuleGroupConfig
|
||||
require.NoError(t, json.Unmarshal(postGroupRaw, &group1))
|
||||
|
||||
// Create rule under folder1
|
||||
response := apiClient.PostRulesGroup(t, "folder1", &group1)
|
||||
|
||||
require.NotEmptyf(t, response.Created, "Expected created to be set")
|
||||
uid := response.Created[0]
|
||||
|
||||
ruleV1 := apiClient.GetRuleByUID(t, uid)
|
||||
|
||||
t.Run("should return 1 version right after creation", func(t *testing.T) {
|
||||
versions, status, raw := apiClient.GetRuleVersionsWithStatus(t, uid)
|
||||
require.Equalf(t, http.StatusOK, status, "Expected status 200, got %d: %s", status, raw)
|
||||
require.Lenf(t, versions, 1, "Expected 1 version, got %d", len(versions))
|
||||
assert.Equal(t, ruleV1, versions[0])
|
||||
})
|
||||
|
||||
group1Gettable := apiClient.GetRulesGroup(t, "folder1", group1.Name)
|
||||
group1 = convertGettableRuleGroupToPostable(group1Gettable.GettableRuleGroupConfig)
|
||||
group1.Rules[0].Annotations[util.GenerateShortUID()] = util.GenerateShortUID()
|
||||
|
||||
_ = apiClient.PostRulesGroup(t, "folder1", &group1)
|
||||
|
||||
ruleV2 := apiClient.GetRuleByUID(t, uid)
|
||||
|
||||
t.Run("should return previous versions after update", func(t *testing.T) {
|
||||
versions, status, raw := apiClient.GetRuleVersionsWithStatus(t, uid)
|
||||
require.Equalf(t, http.StatusOK, status, "Expected status 200, got %d: %s", status, raw)
|
||||
require.Lenf(t, versions, 2, "Expected 2 versions, got %d", len(versions))
|
||||
|
||||
pathsToIgnore := []string{
|
||||
"GrafanaManagedAlert.ID", // In versions ID has different value
|
||||
}
|
||||
// compare expected and actual and ignore the dynamic fields
|
||||
diff := cmp.Diff(apimodels.GettableRuleVersions{ruleV2, ruleV1}, versions, cmp.FilterPath(func(path cmp.Path) bool {
|
||||
for _, s := range pathsToIgnore {
|
||||
if strings.Contains(path.String(), s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}, cmp.Ignore()))
|
||||
assert.Empty(t, diff)
|
||||
})
|
||||
|
||||
_ = apiClient.PostRulesGroup(t, "folder1", &group1) // Noop update
|
||||
|
||||
t.Run("should not add new version if rule was not changed", func(t *testing.T) {
|
||||
versions, status, raw := apiClient.GetRuleVersionsWithStatus(t, uid)
|
||||
require.Equalf(t, http.StatusOK, status, "Expected status 200, got %d: %s", status, raw)
|
||||
require.Lenf(t, versions, 2, "Expected 2 versions, got %d", len(versions))
|
||||
})
|
||||
|
||||
apiClient.DeleteRulesGroup(t, "folder1", group1.Name)
|
||||
|
||||
t.Run("should NotFound after rule was deleted", func(t *testing.T) {
|
||||
_, status, raw := apiClient.GetRuleVersionsWithStatus(t, uid)
|
||||
require.Equalf(t, http.StatusNotFound, status, "Expected status 404, got %d: %s", status, raw)
|
||||
})
|
||||
}
|
||||
|
||||
func newTestingRuleConfig(t *testing.T) apimodels.PostableRuleGroupConfig {
|
||||
interval, err := model.ParseDuration("1m")
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user