mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add UID of rules to response that were affected by update group request (#75985)
* update storage's method InstertRules to return ids of added rules as slice to keep the same order as rules in the argument * schematize response of update rule group endpoint, add created, updated, deleted fields that contain UID of affected rules. * update integration tests to use the new fields
This commit is contained in:
parent
6086a0916b
commit
2497db4bd6
@ -328,10 +328,18 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *contextmodel.ReqContext, groupKey
|
|||||||
for _, rule := range finalChanges.New {
|
for _, rule := range finalChanges.New {
|
||||||
inserts = append(inserts, *rule)
|
inserts = append(inserts, *rule)
|
||||||
}
|
}
|
||||||
_, err = srv.store.InsertAlertRules(tranCtx, inserts)
|
added, err := srv.store.InsertAlertRules(tranCtx, inserts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to add rules: %w", err)
|
return fmt.Errorf("failed to add rules: %w", err)
|
||||||
}
|
}
|
||||||
|
if len(added) != len(finalChanges.New) {
|
||||||
|
logger.Error("Cannot match inserted rules with final changes", "insertedCount", len(added), "changes", len(finalChanges.New))
|
||||||
|
} else {
|
||||||
|
for i, newRule := range finalChanges.New {
|
||||||
|
newRule.ID = added[i].ID
|
||||||
|
newRule.UID = added[i].UID
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(finalChanges.New) > 0 {
|
if len(finalChanges.New) > 0 {
|
||||||
@ -363,12 +371,30 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *contextmodel.ReqContext, groupKey
|
|||||||
}
|
}
|
||||||
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
|
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
|
||||||
}
|
}
|
||||||
|
return changesToResponse(finalChanges)
|
||||||
|
}
|
||||||
|
|
||||||
if finalChanges.IsEmpty() {
|
func changesToResponse(finalChanges *store.GroupDelta) response.Response {
|
||||||
return response.JSON(http.StatusAccepted, util.DynMap{"message": "no changes detected in the rule group"})
|
body := apimodels.UpdateRuleGroupResponse{
|
||||||
|
Message: "rule group updated successfully",
|
||||||
|
Created: make([]string, 0, len(finalChanges.New)),
|
||||||
|
Updated: make([]string, 0, len(finalChanges.Update)),
|
||||||
|
Deleted: make([]string, 0, len(finalChanges.Delete)),
|
||||||
}
|
}
|
||||||
|
if finalChanges.IsEmpty() {
|
||||||
return response.JSON(http.StatusAccepted, util.DynMap{"message": "rule group updated successfully"})
|
body.Message = "no changes detected in the rule group"
|
||||||
|
} else {
|
||||||
|
for _, r := range finalChanges.New {
|
||||||
|
body.Created = append(body.Created, r.UID)
|
||||||
|
}
|
||||||
|
for _, r := range finalChanges.Update {
|
||||||
|
body.Updated = append(body.Updated, r.Existing.UID)
|
||||||
|
}
|
||||||
|
for _, r := range finalChanges.Delete {
|
||||||
|
body.Deleted = append(body.Deleted, r.UID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response.JSON(http.StatusAccepted, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, namespaceID int64, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableRuleGroupConfig {
|
func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, namespaceID int64, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableRuleGroupConfig {
|
||||||
|
@ -18,7 +18,7 @@ type RuleStore interface {
|
|||||||
|
|
||||||
// InsertAlertRules will insert all alert rules passed into the function
|
// InsertAlertRules will insert all alert rules passed into the function
|
||||||
// and return the map of uuid to id.
|
// and return the map of uuid to id.
|
||||||
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) (map[string]int64, error)
|
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) ([]ngmodels.AlertRuleKeyWithId, error)
|
||||||
UpdateAlertRules(ctx context.Context, rule []ngmodels.UpdateRule) error
|
UpdateAlertRules(ctx context.Context, rule []ngmodels.UpdateRule) error
|
||||||
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
|
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
|
||||||
|
|
||||||
|
@ -3921,6 +3921,32 @@
|
|||||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"UpdateRuleGroupResponse": {
|
||||||
|
"properties": {
|
||||||
|
"created": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"deleted": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updated": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Userinfo": {
|
"Userinfo": {
|
||||||
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -51,7 +51,7 @@ import (
|
|||||||
// - application/yaml
|
// - application/yaml
|
||||||
//
|
//
|
||||||
// Responses:
|
// Responses:
|
||||||
// 202: Ack
|
// 202: UpdateRuleGroupResponse
|
||||||
//
|
//
|
||||||
|
|
||||||
// swagger:route POST /api/ruler/grafana/api/v1/rules/{Namespace}/export ruler RoutePostRulesGroupForExport
|
// swagger:route POST /api/ruler/grafana/api/v1/rules/{Namespace}/export ruler RoutePostRulesGroupForExport
|
||||||
@ -486,3 +486,11 @@ func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error {
|
|||||||
return fmt.Errorf("invalid duration %v", v)
|
return fmt.Errorf("invalid duration %v", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swagger:model
|
||||||
|
type UpdateRuleGroupResponse struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Created []string `json:"created,omitempty"`
|
||||||
|
Updated []string `json:"updated,omitempty"`
|
||||||
|
Deleted []string `json:"deleted,omitempty"`
|
||||||
|
}
|
||||||
|
@ -3920,6 +3920,32 @@
|
|||||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"UpdateRuleGroupResponse": {
|
||||||
|
"properties": {
|
||||||
|
"created": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"deleted": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updated": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Userinfo": {
|
"Userinfo": {
|
||||||
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@ -5992,9 +6018,9 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"202": {
|
"202": {
|
||||||
"description": "Ack",
|
"description": "UpdateRuleGroupResponse",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/Ack"
|
"$ref": "#/definitions/UpdateRuleGroupResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1345,9 +1345,9 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"202": {
|
"202": {
|
||||||
"description": "Ack",
|
"description": "UpdateRuleGroupResponse",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/Ack"
|
"$ref": "#/definitions/UpdateRuleGroupResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6902,6 +6902,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"UpdateRuleGroupResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"created": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deleted": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updated": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Userinfo": {
|
"Userinfo": {
|
||||||
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -356,6 +356,11 @@ type AlertRuleKeyWithVersionAndPauseStatus struct {
|
|||||||
AlertRuleKeyWithVersion `xorm:"extends"`
|
AlertRuleKeyWithVersion `xorm:"extends"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlertRuleKeyWithId struct {
|
||||||
|
AlertRuleKey
|
||||||
|
ID int64
|
||||||
|
}
|
||||||
|
|
||||||
// AlertRuleGroupKey is the identifier of a group of alerts
|
// AlertRuleGroupKey is the identifier of a group of alerts
|
||||||
type AlertRuleGroupKey struct {
|
type AlertRuleGroupKey struct {
|
||||||
OrgID int64
|
OrgID int64
|
||||||
|
@ -134,9 +134,15 @@ func (service *AlertRuleService) CreateAlertRule(ctx context.Context, rule model
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if id, ok := ids[rule.UID]; ok {
|
var fixed bool
|
||||||
rule.ID = id
|
for _, key := range ids {
|
||||||
} else {
|
if key.UID == rule.UID {
|
||||||
|
rule.ID = key.ID
|
||||||
|
fixed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !fixed {
|
||||||
return errors.New("couldn't find newly created id")
|
return errors.New("couldn't find newly created id")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,8 +315,8 @@ func (service *AlertRuleService) ReplaceRuleGroup(ctx context.Context, orgID int
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to insert alert rules: %w", err)
|
return fmt.Errorf("failed to insert alert rules: %w", err)
|
||||||
}
|
}
|
||||||
for uid := range uids {
|
for _, key := range uids {
|
||||||
if err := service.provenanceStore.SetProvenance(ctx, &models.AlertRule{UID: uid}, orgID, provenance); err != nil {
|
if err := service.provenanceStore.SetProvenance(ctx, &models.AlertRule{UID: key.UID}, orgID, provenance); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ type RuleStore interface {
|
|||||||
GetAlertRuleByUID(ctx context.Context, query *models.GetAlertRuleByUIDQuery) (*models.AlertRule, error)
|
GetAlertRuleByUID(ctx context.Context, query *models.GetAlertRuleByUIDQuery) (*models.AlertRule, error)
|
||||||
ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) (models.RulesGroup, error)
|
ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) (models.RulesGroup, error)
|
||||||
GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error)
|
GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error)
|
||||||
InsertAlertRules(ctx context.Context, rule []models.AlertRule) (map[string]int64, error)
|
InsertAlertRules(ctx context.Context, rule []models.AlertRule) ([]models.AlertRuleKeyWithId, error)
|
||||||
UpdateAlertRules(ctx context.Context, rule []models.UpdateRule) error
|
UpdateAlertRules(ctx context.Context, rule []models.UpdateRule) error
|
||||||
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
|
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
|
||||||
GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) ([]*models.AlertRule, error)
|
GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) ([]*models.AlertRule, error)
|
||||||
|
@ -116,8 +116,9 @@ func (st DBstore) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertAlertRules is a handler for creating/updating alert rules.
|
// InsertAlertRules is a handler for creating/updating alert rules.
|
||||||
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) (map[string]int64, error) {
|
// Returns the UID and ID of rules that were created in the same order as the input rules.
|
||||||
ids := make(map[string]int64, len(rules))
|
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) ([]ngmodels.AlertRuleKeyWithId, error) {
|
||||||
|
ids := make([]ngmodels.AlertRuleKeyWithId, 0, len(rules))
|
||||||
return ids, st.SQLStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
return ids, st.SQLStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
||||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||||
@ -167,7 +168,10 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("failed to create new rules: %w", err)
|
return fmt.Errorf("failed to create new rules: %w", err)
|
||||||
}
|
}
|
||||||
ids[newRules[i].UID] = newRules[i].ID
|
ids = append(ids, ngmodels.AlertRuleKeyWithId{
|
||||||
|
AlertRuleKey: newRules[i].GetKey(),
|
||||||
|
ID: newRules[i].ID,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +514,50 @@ func TestIntegration_GetNamespaceByUID(t *testing.T) {
|
|||||||
require.Equal(t, uid, actual.UID)
|
require.Equal(t, uid, actual.UID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntegrationInsertAlertRules(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping integration test")
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlStore := db.InitTestDB(t)
|
||||||
|
cfg := setting.NewCfg()
|
||||||
|
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
|
||||||
|
store := &DBstore{
|
||||||
|
SQLStore: sqlStore,
|
||||||
|
FolderService: setupFolderService(t, sqlStore, cfg),
|
||||||
|
Logger: log.New("test-dbstore"),
|
||||||
|
Cfg: cfg.UnifiedAlerting,
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(1), withIntervalMatching(store.Cfg.BaseInterval)))
|
||||||
|
deref := make([]models.AlertRule, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
deref = append(deref, *rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
ids, err := store.InsertAlertRules(context.Background(), deref)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, ids, len(rules))
|
||||||
|
|
||||||
|
dbRules, err := store.ListAlertRules(context.Background(), &models.ListAlertRulesQuery{
|
||||||
|
OrgID: 1,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
for idx, keyWithID := range ids {
|
||||||
|
found := false
|
||||||
|
for _, rule := range dbRules {
|
||||||
|
if rule.GetKey() == keyWithID.AlertRuleKey {
|
||||||
|
expected := rules[idx]
|
||||||
|
require.Equal(t, keyWithID.ID, rule.ID)
|
||||||
|
require.Equal(t, expected.Title, rule.Title)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.Truef(t, found, "Rule with key %#v was not found in database", keyWithID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createRule(t *testing.T, store *DBstore, generate func() *models.AlertRule) *models.AlertRule {
|
func createRule(t *testing.T, store *DBstore, generate func() *models.AlertRule) *models.AlertRule {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if generate == nil {
|
if generate == nil {
|
||||||
|
@ -281,11 +281,11 @@ func (f *RuleStore) UpdateAlertRules(_ context.Context, q []models.UpdateRule) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *RuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) (map[string]int64, error) {
|
func (f *RuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) ([]models.AlertRuleKeyWithId, error) {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.RecordedOps = append(f.RecordedOps, q)
|
f.RecordedOps = append(f.RecordedOps, q)
|
||||||
ids := make(map[string]int64, len(q))
|
ids := make([]models.AlertRuleKeyWithId, 0, len(q))
|
||||||
if err := f.Hook(q); err != nil {
|
if err := f.Hook(q); err != nil {
|
||||||
return ids, err
|
return ids, err
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,7 @@ func TestIntegrationAlertAndGroupsQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
status, _ := apiClient.PostRulesGroup(t, "default", &rules)
|
_, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,7 +664,7 @@ func TestIntegrationRulerAccess(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := tc.client.PostRulesGroup(t, "default", &rules)
|
_, status, body := tc.client.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, tc.expStatus, status)
|
assert.Equal(t, tc.expStatus, status)
|
||||||
res := &Response{}
|
res := &Response{}
|
||||||
err = json.Unmarshal([]byte(body), &res)
|
err = json.Unmarshal([]byte(body), &res)
|
||||||
@ -1097,7 +1097,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
tc.rule,
|
tc.rule,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
res := &Response{}
|
res := &Response{}
|
||||||
err = json.Unmarshal([]byte(body), &res)
|
err = json.Unmarshal([]byte(body), &res)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -1170,9 +1170,12 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
resp, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Equal(t, "rule group updated successfully", resp.Message)
|
||||||
|
assert.Len(t, resp.Created, 2)
|
||||||
|
assert.Empty(t, resp.Updated)
|
||||||
|
assert.Empty(t, resp.Deleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the rules created, let's make sure that rule definition is stored correctly.
|
// With the rules created, let's make sure that rule definition is stored correctly.
|
||||||
@ -1339,7 +1342,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
Interval: interval,
|
Interval: interval,
|
||||||
}
|
}
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusNotFound, status)
|
assert.Equal(t, http.StatusNotFound, status)
|
||||||
var res map[string]any
|
var res map[string]any
|
||||||
assert.NoError(t, json.Unmarshal([]byte(body), &res))
|
assert.NoError(t, json.Unmarshal([]byte(body), &res))
|
||||||
@ -1445,7 +1448,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusBadRequest, status)
|
assert.Equal(t, http.StatusBadRequest, status)
|
||||||
var res map[string]any
|
var res map[string]any
|
||||||
require.NoError(t, json.Unmarshal([]byte(body), &res))
|
require.NoError(t, json.Unmarshal([]byte(body), &res))
|
||||||
@ -1519,9 +1522,10 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
respModel, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Equal(t, respModel.Updated, []string{ruleUID})
|
||||||
|
require.Len(t, respModel.Deleted, 1)
|
||||||
|
|
||||||
// let's make sure that rule definitions are updated correctly.
|
// let's make sure that rule definitions are updated correctly.
|
||||||
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
||||||
@ -1637,9 +1641,9 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
respModel, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Equal(t, respModel.Updated, []string{ruleUID})
|
||||||
|
|
||||||
// let's make sure that rule definitions are updated correctly.
|
// let's make sure that rule definitions are updated correctly.
|
||||||
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
||||||
@ -1723,9 +1727,12 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
respModel, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"no changes detected in the rule group"}`, body)
|
require.Equal(t, "no changes detected in the rule group", respModel.Message)
|
||||||
|
assert.Empty(t, respModel.Created)
|
||||||
|
assert.Empty(t, respModel.Updated)
|
||||||
|
assert.Empty(t, respModel.Deleted)
|
||||||
|
|
||||||
// let's make sure that rule definitions are updated correctly.
|
// let's make sure that rule definitions are updated correctly.
|
||||||
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
||||||
@ -1993,7 +2000,7 @@ func TestIntegrationQuota(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusForbidden, status)
|
assert.Equal(t, http.StatusForbidden, status)
|
||||||
var res map[string]any
|
var res map[string]any
|
||||||
require.NoError(t, json.Unmarshal([]byte(body), &res))
|
require.NoError(t, json.Unmarshal([]byte(body), &res))
|
||||||
@ -2030,9 +2037,9 @@ func TestIntegrationQuota(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
respModel, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, respModel.Updated, 1)
|
||||||
|
|
||||||
// let's make sure that rule definitions are updated correctly.
|
// let's make sure that rule definitions are updated correctly.
|
||||||
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default", grafanaListedAddr)
|
||||||
|
@ -11,11 +11,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/expr"
|
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/expr"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
@ -155,8 +156,10 @@ func TestIntegrationPrometheusRules(t *testing.T) {
|
|||||||
b, err := io.ReadAll(resp.Body)
|
b, err := io.ReadAll(resp.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, resp.StatusCode, 202)
|
assert.Equal(t, http.StatusAccepted, resp.StatusCode)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, string(b))
|
var respModel apimodels.UpdateRuleGroupResponse
|
||||||
|
require.NoError(t, json.Unmarshal(b, &respModel))
|
||||||
|
require.Len(t, respModel.Created, len(rules.Rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that we cannot create a rule that has a panel_id and no dashboard_uid
|
// Check that we cannot create a rule that has a panel_id and no dashboard_uid
|
||||||
@ -434,8 +437,10 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
|
|||||||
b, err := io.ReadAll(resp.Body)
|
b, err := io.ReadAll(resp.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, resp.StatusCode, 202)
|
assert.Equal(t, http.StatusAccepted, resp.StatusCode)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, string(b))
|
var respModel apimodels.UpdateRuleGroupResponse
|
||||||
|
require.NoError(t, json.Unmarshal(b, &respModel))
|
||||||
|
require.Len(t, respModel.Created, len(rules.Rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedAllJSON := fmt.Sprintf(`
|
expectedAllJSON := fmt.Sprintf(`
|
||||||
|
@ -71,7 +71,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
|||||||
require.NoError(t, json.Unmarshal(postGroupRaw, &group1))
|
require.NoError(t, json.Unmarshal(postGroupRaw, &group1))
|
||||||
|
|
||||||
// Create rule under folder1
|
// Create rule under folder1
|
||||||
status, response := apiClient.PostRulesGroup(t, "folder1", &group1)
|
_, status, response := apiClient.PostRulesGroupWithStatus(t, "folder1", &group1)
|
||||||
require.Equalf(t, http.StatusAccepted, status, response)
|
require.Equalf(t, http.StatusAccepted, status, response)
|
||||||
|
|
||||||
postGroupRaw, err = testData.ReadFile(path.Join("test-data", "rulegroup-2-post.json"))
|
postGroupRaw, err = testData.ReadFile(path.Join("test-data", "rulegroup-2-post.json"))
|
||||||
@ -80,7 +80,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
|||||||
require.NoError(t, json.Unmarshal(postGroupRaw, &group2))
|
require.NoError(t, json.Unmarshal(postGroupRaw, &group2))
|
||||||
|
|
||||||
// Create rule under folder2
|
// Create rule under folder2
|
||||||
status, response = apiClient.PostRulesGroup(t, "folder2", &group2)
|
_, status, response = apiClient.PostRulesGroupWithStatus(t, "folder2", &group2)
|
||||||
require.Equalf(t, http.StatusAccepted, status, response)
|
require.Equalf(t, http.StatusAccepted, status, response)
|
||||||
|
|
||||||
// With the rules created, let's make sure that rule definitions are stored.
|
// With the rules created, let's make sure that rule definitions are stored.
|
||||||
@ -322,7 +322,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRule(t *testing.T, client apiClient, folder string) apimodels.PostableRuleGroupConfig {
|
func createRule(t *testing.T, client apiClient, folder string) (apimodels.PostableRuleGroupConfig, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
interval, err := model.ParseDuration("1m")
|
interval, err := model.ParseDuration("1m")
|
||||||
@ -359,10 +359,10 @@ func createRule(t *testing.T, client apiClient, folder string) apimodels.Postabl
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := client.PostRulesGroup(t, folder, &rules)
|
resp, status, _ := client.PostRulesGroupWithStatus(t, folder, &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, resp.Created, 1)
|
||||||
return rules
|
return rules, resp.Created[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAlertRulePostExport(t *testing.T) {
|
func TestAlertRulePostExport(t *testing.T) {
|
||||||
@ -474,9 +474,9 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
|
|
||||||
rules := newTestingRuleConfig(t)
|
rules := newTestingRuleConfig(t)
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder1", &rules)
|
respModel, status, _ := apiClient.PostRulesGroupWithStatus(t, "folder1", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, respModel.Created, len(rules.Rules))
|
||||||
|
|
||||||
// fetch the created rules, so we can get the uid's and trigger
|
// fetch the created rules, so we can get the uid's and trigger
|
||||||
// and update by reusing the uid's
|
// and update by reusing the uid's
|
||||||
@ -487,7 +487,7 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
rulesWithUID := convertGettableRuleGroupToPostable(createdRuleGroup)
|
rulesWithUID := convertGettableRuleGroupToPostable(createdRuleGroup)
|
||||||
rulesWithUID.Rules = append(rulesWithUID.Rules, rules.Rules[0]) // Create new copy of first rule.
|
rulesWithUID.Rules = append(rulesWithUID.Rules, rules.Rules[0]) // Create new copy of first rule.
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder1", &rulesWithUID)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "folder1", &rulesWithUID)
|
||||||
assert.Equal(t, http.StatusInternalServerError, status)
|
assert.Equal(t, http.StatusInternalServerError, status)
|
||||||
|
|
||||||
var res map[string]any
|
var res map[string]any
|
||||||
@ -499,7 +499,7 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
rulesWithUID := convertGettableRuleGroupToPostable(createdRuleGroup)
|
rulesWithUID := convertGettableRuleGroupToPostable(createdRuleGroup)
|
||||||
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = "AlwaysFiring"
|
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = "AlwaysFiring"
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder1", &rulesWithUID)
|
_, status, body := apiClient.PostRulesGroupWithStatus(t, "folder1", &rulesWithUID)
|
||||||
assert.Equal(t, http.StatusInternalServerError, status)
|
assert.Equal(t, http.StatusInternalServerError, status)
|
||||||
|
|
||||||
var res map[string]any
|
var res map[string]any
|
||||||
@ -509,9 +509,9 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("trying to create alert with same title under another folder should succeed", func(t *testing.T) {
|
t.Run("trying to create alert with same title under another folder should succeed", func(t *testing.T) {
|
||||||
rules := newTestingRuleConfig(t)
|
rules := newTestingRuleConfig(t)
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder2", &rules)
|
resp, status, _ := apiClient.PostRulesGroupWithStatus(t, "folder2", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, resp.Created, len(rules.Rules))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("trying to swap titles of existing alerts in the same folder should work", func(t *testing.T) {
|
t.Run("trying to swap titles of existing alerts in the same folder should work", func(t *testing.T) {
|
||||||
@ -521,9 +521,9 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
rulesWithUID.Rules[0].GrafanaManagedAlert.Title = title1
|
rulesWithUID.Rules[0].GrafanaManagedAlert.Title = title1
|
||||||
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = title0
|
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = title0
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder1", &rulesWithUID)
|
resp, status, _ := apiClient.PostRulesGroupWithStatus(t, "folder1", &rulesWithUID)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, resp.Updated, 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("trying to update titles of existing alerts in a chain in the same folder should work", func(t *testing.T) {
|
t.Run("trying to update titles of existing alerts in a chain in the same folder should work", func(t *testing.T) {
|
||||||
@ -531,9 +531,9 @@ func TestIntegrationAlertRuleConflictingTitle(t *testing.T) {
|
|||||||
rulesWithUID.Rules[0].GrafanaManagedAlert.Title = rulesWithUID.Rules[1].GrafanaManagedAlert.Title
|
rulesWithUID.Rules[0].GrafanaManagedAlert.Title = rulesWithUID.Rules[1].GrafanaManagedAlert.Title
|
||||||
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = "something new"
|
rulesWithUID.Rules[1].GrafanaManagedAlert.Title = "something new"
|
||||||
|
|
||||||
status, body := apiClient.PostRulesGroup(t, "folder1", &rulesWithUID)
|
resp, status, _ := apiClient.PostRulesGroupWithStatus(t, "folder1", &rulesWithUID)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, resp.Updated, len(rulesWithUID.Rules))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,9 +621,9 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
status, body := apiClient.PostRulesGroup(t, "default", &rules)
|
resp, status, _ := apiClient.PostRulesGroupWithStatus(t, "default", &rules)
|
||||||
assert.Equal(t, http.StatusAccepted, status)
|
assert.Equal(t, http.StatusAccepted, status)
|
||||||
require.JSONEq(t, `{"message":"rule group updated successfully"}`, body)
|
require.Len(t, resp.Created, len(rules.Rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedAllJSON := fmt.Sprintf(`
|
expectedAllJSON := fmt.Sprintf(`
|
||||||
@ -905,9 +905,9 @@ func TestIntegrationRuleGroupSequence(t *testing.T) {
|
|||||||
group1 := generateAlertRuleGroup(5, alertRuleGen())
|
group1 := generateAlertRuleGroup(5, alertRuleGen())
|
||||||
group2 := generateAlertRuleGroup(5, alertRuleGen())
|
group2 := generateAlertRuleGroup(5, alertRuleGen())
|
||||||
|
|
||||||
status, _ := client.PostRulesGroup(t, folder1Title, &group1)
|
_, status, _ := client.PostRulesGroupWithStatus(t, folder1Title, &group1)
|
||||||
require.Equal(t, http.StatusAccepted, status)
|
require.Equal(t, http.StatusAccepted, status)
|
||||||
status, _ = client.PostRulesGroup(t, folder1Title, &group2)
|
_, status, _ = client.PostRulesGroupWithStatus(t, folder1Title, &group2)
|
||||||
require.Equal(t, http.StatusAccepted, status)
|
require.Equal(t, http.StatusAccepted, status)
|
||||||
|
|
||||||
t.Run("should persist order of the rules in a group", func(t *testing.T) {
|
t.Run("should persist order of the rules in a group", func(t *testing.T) {
|
||||||
@ -930,7 +930,7 @@ func TestIntegrationRuleGroupSequence(t *testing.T) {
|
|||||||
for _, rule := range postableGroup1.Rules {
|
for _, rule := range postableGroup1.Rules {
|
||||||
expectedUids = append(expectedUids, rule.GrafanaManagedAlert.UID)
|
expectedUids = append(expectedUids, rule.GrafanaManagedAlert.UID)
|
||||||
}
|
}
|
||||||
status, _ := client.PostRulesGroup(t, folder1Title, &postableGroup1)
|
_, status, _ := client.PostRulesGroupWithStatus(t, folder1Title, &postableGroup1)
|
||||||
require.Equal(t, http.StatusAccepted, status)
|
require.Equal(t, http.StatusAccepted, status)
|
||||||
|
|
||||||
group1Get = client.GetRulesGroup(t, folder1Title, group1.Name)
|
group1Get = client.GetRulesGroup(t, folder1Title, group1.Name)
|
||||||
@ -956,7 +956,7 @@ func TestIntegrationRuleGroupSequence(t *testing.T) {
|
|||||||
for _, rule := range postableGroup1.Rules {
|
for _, rule := range postableGroup1.Rules {
|
||||||
expectedUids = append(expectedUids, rule.GrafanaManagedAlert.UID)
|
expectedUids = append(expectedUids, rule.GrafanaManagedAlert.UID)
|
||||||
}
|
}
|
||||||
status, _ := client.PostRulesGroup(t, folder1Title, &postableGroup1)
|
_, status, _ := client.PostRulesGroupWithStatus(t, folder1Title, &postableGroup1)
|
||||||
require.Equal(t, http.StatusAccepted, status)
|
require.Equal(t, http.StatusAccepted, status)
|
||||||
|
|
||||||
group1Get = client.GetRulesGroup(t, folder1Title, group1.Name)
|
group1Get = client.GetRulesGroup(t, folder1Title, group1.Name)
|
||||||
@ -1031,7 +1031,7 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
expected := model.Duration(10 * time.Second)
|
expected := model.Duration(10 * time.Second)
|
||||||
group.Rules[0].ApiRuleNode.For = &expected
|
group.Rules[0].ApiRuleNode.For = &expected
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
require.Equal(t, expected, *getGroup.Rules[0].ApiRuleNode.For)
|
require.Equal(t, expected, *getGroup.Rules[0].ApiRuleNode.For)
|
||||||
@ -1039,7 +1039,7 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
expected = 0
|
expected = 0
|
||||||
group.Rules[0].ApiRuleNode.For = &expected
|
group.Rules[0].ApiRuleNode.For = &expected
|
||||||
status, body = client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body = client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
|
||||||
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
@ -1051,7 +1051,7 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
ds1 := adminClient.CreateTestDatasource(t)
|
ds1 := adminClient.CreateTestDatasource(t)
|
||||||
group := generateAlertRuleGroup(3, alertRuleGen(withDatasourceQuery(ds1.Body.Datasource.UID)))
|
group := generateAlertRuleGroup(3, alertRuleGen(withDatasourceQuery(ds1.Body.Datasource.UID)))
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
@ -1071,7 +1071,7 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
getGroup := client.GetRulesGroup(t, folder1Title, groupName)
|
getGroup := client.GetRulesGroup(t, folder1Title, groupName)
|
||||||
group := convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group := convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post noop rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post noop rule group. Response: %s", body)
|
||||||
})
|
})
|
||||||
t.Run("should not let update rule if it does not fix datasource", func(t *testing.T) {
|
t.Run("should not let update rule if it does not fix datasource", func(t *testing.T) {
|
||||||
@ -1079,9 +1079,10 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
group := convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group := convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
|
|
||||||
group.Rules[0].GrafanaManagedAlert.Title = uuid.NewString()
|
group.Rules[0].GrafanaManagedAlert.Title = uuid.NewString()
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
|
|
||||||
if status == http.StatusAccepted {
|
if status == http.StatusAccepted {
|
||||||
|
assert.Len(t, resp.Deleted, 1)
|
||||||
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
assert.NotEqualf(t, group.Rules[0].GrafanaManagedAlert.Title, getGroup.Rules[0].GrafanaManagedAlert.Title, "group was updated")
|
assert.NotEqualf(t, group.Rules[0].GrafanaManagedAlert.Title, getGroup.Rules[0].GrafanaManagedAlert.Title, "group was updated")
|
||||||
}
|
}
|
||||||
@ -1094,8 +1095,9 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
|
|
||||||
// remove the last rule.
|
// remove the last rule.
|
||||||
group.Rules = group.Rules[0 : len(group.Rules)-1]
|
group.Rules = group.Rules[0 : len(group.Rules)-1]
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to delete last rule from group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to delete last rule from group. Response: %s", body)
|
||||||
|
assert.Len(t, resp.Deleted, 1)
|
||||||
|
|
||||||
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
@ -1107,8 +1109,11 @@ func TestIntegrationRuleUpdate(t *testing.T) {
|
|||||||
|
|
||||||
ds2 := adminClient.CreateTestDatasource(t)
|
ds2 := adminClient.CreateTestDatasource(t)
|
||||||
withDatasourceQuery(ds2.Body.Datasource.UID)(&group.Rules[0])
|
withDatasourceQuery(ds2.Body.Datasource.UID)(&group.Rules[0])
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post noop rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post noop rule group. Response: %s", body)
|
||||||
|
assert.Len(t, resp.Deleted, 0)
|
||||||
|
assert.Len(t, resp.Updated, 2)
|
||||||
|
assert.Len(t, resp.Created, 0)
|
||||||
|
|
||||||
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
@ -1217,8 +1222,9 @@ func TestIntegrationRulePause(t *testing.T) {
|
|||||||
expectedIsPaused := true
|
expectedIsPaused := true
|
||||||
group.Rules[0].GrafanaManagedAlert.IsPaused = &expectedIsPaused
|
group.Rules[0].GrafanaManagedAlert.IsPaused = &expectedIsPaused
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
require.Len(t, resp.Created, 1)
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
||||||
require.Equal(t, expectedIsPaused, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
require.Equal(t, expectedIsPaused, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
||||||
@ -1229,8 +1235,9 @@ func TestIntegrationRulePause(t *testing.T) {
|
|||||||
expectedIsPaused := false
|
expectedIsPaused := false
|
||||||
group.Rules[0].GrafanaManagedAlert.IsPaused = &expectedIsPaused
|
group.Rules[0].GrafanaManagedAlert.IsPaused = &expectedIsPaused
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
require.Len(t, resp.Created, 1)
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
||||||
require.Equal(t, expectedIsPaused, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
require.Equal(t, expectedIsPaused, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
||||||
@ -1240,8 +1247,9 @@ func TestIntegrationRulePause(t *testing.T) {
|
|||||||
group := generateAlertRuleGroup(1, alertRuleGen())
|
group := generateAlertRuleGroup(1, alertRuleGen())
|
||||||
group.Rules[0].GrafanaManagedAlert.IsPaused = nil
|
group.Rules[0].GrafanaManagedAlert.IsPaused = nil
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
resp, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
require.Len(t, resp.Created, 1)
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
||||||
require.False(t, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
require.False(t, getGroup.Rules[0].GrafanaManagedAlert.IsPaused)
|
||||||
@ -1297,14 +1305,14 @@ func TestIntegrationRulePause(t *testing.T) {
|
|||||||
group := generateAlertRuleGroup(1, alertRuleGen())
|
group := generateAlertRuleGroup(1, alertRuleGen())
|
||||||
group.Rules[0].GrafanaManagedAlert.IsPaused = &tc.isPausedInDb
|
group.Rules[0].GrafanaManagedAlert.IsPaused = &tc.isPausedInDb
|
||||||
|
|
||||||
status, body := client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body := client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup := client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to get rule group. Response: %s", body)
|
||||||
|
|
||||||
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
group = convertGettableRuleGroupToPostable(getGroup.GettableRuleGroupConfig)
|
||||||
group.Rules[0].GrafanaManagedAlert.IsPaused = tc.isPausedInBody
|
group.Rules[0].GrafanaManagedAlert.IsPaused = tc.isPausedInBody
|
||||||
status, body = client.PostRulesGroup(t, folder1Title, &group)
|
_, status, body = client.PostRulesGroupWithStatus(t, folder1Title, &group)
|
||||||
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
require.Equalf(t, http.StatusAccepted, status, "failed to post rule group. Response: %s", body)
|
||||||
|
|
||||||
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
getGroup = client.GetRulesGroup(t, folder1Title, group.Name)
|
||||||
|
@ -328,7 +328,7 @@ func (a apiClient) UpdateAlertRuleOrgQuota(t *testing.T, orgID int64, limit int6
|
|||||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a apiClient) PostRulesGroup(t *testing.T, folder string, group *apimodels.PostableRuleGroupConfig) (int, string) {
|
func (a apiClient) PostRulesGroupWithStatus(t *testing.T, folder string, group *apimodels.PostableRuleGroupConfig) (apimodels.UpdateRuleGroupResponse, int, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
@ -344,7 +344,11 @@ func (a apiClient) PostRulesGroup(t *testing.T, folder string, group *apimodels.
|
|||||||
}()
|
}()
|
||||||
b, err := io.ReadAll(resp.Body)
|
b, err := io.ReadAll(resp.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return resp.StatusCode, string(b)
|
var m apimodels.UpdateRuleGroupResponse
|
||||||
|
if resp.StatusCode == http.StatusAccepted {
|
||||||
|
require.NoError(t, json.Unmarshal(b, &m))
|
||||||
|
}
|
||||||
|
return m, resp.StatusCode, string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a apiClient) PostRulesExportWithStatus(t *testing.T, folder string, group *apimodels.PostableRuleGroupConfig, params *apimodels.ExportQueryParams) (int, string) {
|
func (a apiClient) PostRulesExportWithStatus(t *testing.T, folder string, group *apimodels.PostableRuleGroupConfig, params *apimodels.ExportQueryParams) (int, string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user