diff --git a/pkg/services/ngalert/api/api_ruler.go b/pkg/services/ngalert/api/api_ruler.go index c122a19c1be..8e2ff91d57b 100644 --- a/pkg/services/ngalert/api/api_ruler.go +++ b/pkg/services/ngalert/api/api_ruler.go @@ -226,9 +226,6 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext) response.Resp return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules") } - var ruleGroupInterval model.Duration - ruleNodes := make([]apimodels.GettableExtendedRuleNode, 0, len(q.Result)) - hasAccess := func(evaluator accesscontrol.Evaluator) bool { return accesscontrol.HasAccess(srv.ac, c)(accesscontrol.ReqSignedIn, evaluator) } @@ -238,20 +235,16 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext) response.Resp return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules") } + groupRules := make([]*ngmodels.AlertRule, 0, len(q.Result)) for _, r := range q.Result { if !authorizeDatasourceAccessForRule(r, hasAccess) { continue } - ruleGroupInterval = model.Duration(time.Duration(r.IntervalSeconds) * time.Second) - ruleNodes = append(ruleNodes, toGettableExtendedRuleNode(*r, namespace.Id, provenanceRecords)) + groupRules = append(groupRules, r) } result := apimodels.RuleGroupConfigResponse{ - GettableRuleGroupConfig: apimodels.GettableRuleGroupConfig{ - Name: ruleGroup, - Interval: ruleGroupInterval, - Rules: ruleNodes, - }, + GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, groupRules, namespace.Id, provenanceRecords), } return response.JSON(http.StatusAccepted, result) } @@ -293,7 +286,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response return ErrResp(http.StatusInternalServerError, err, "failed to get alert rules") } - configs := make(map[string]map[string]apimodels.GettableRuleGroupConfig) + configs := make(map[string]map[string][]*ngmodels.AlertRule) hasAccess := func(evaluator accesscontrol.Evaluator) bool { return accesscontrol.HasAccess(srv.ac, c)(accesscontrol.ReqSignedIn, evaluator) @@ -308,44 +301,25 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response if !authorizeDatasourceAccessForRule(r, hasAccess) { continue } - folder, ok := namespaceMap[r.NamespaceUID] + namespaceCfgs, ok := configs[r.NamespaceUID] if !ok { - srv.log.Error("namespace not visible to the user", "user", c.SignedInUser.UserId, "namespace", r.NamespaceUID, "rule", r.UID) + namespaceCfgs = make(map[string][]*ngmodels.AlertRule) + configs[r.NamespaceUID] = namespaceCfgs + } + group := namespaceCfgs[r.RuleGroup] + group = append(group, r) + namespaceCfgs[r.RuleGroup] = group + } + + for namespaceUID, m := range configs { + folder, ok := namespaceMap[namespaceUID] + if !ok { + srv.log.Error("namespace not visible to the user", "user", c.SignedInUser.UserId, "namespace", namespaceUID) continue } namespace := folder.Title - _, ok = configs[namespace] - if !ok { - ruleGroupInterval := model.Duration(time.Duration(r.IntervalSeconds) * time.Second) - configs[namespace] = make(map[string]apimodels.GettableRuleGroupConfig) - configs[namespace][r.RuleGroup] = apimodels.GettableRuleGroupConfig{ - Name: r.RuleGroup, - Interval: ruleGroupInterval, - Rules: []apimodels.GettableExtendedRuleNode{ - toGettableExtendedRuleNode(*r, folder.Id, provenanceRecords), - }, - } - } else { - ruleGroupConfig, ok := configs[namespace][r.RuleGroup] - if !ok { - ruleGroupInterval := model.Duration(time.Duration(r.IntervalSeconds) * time.Second) - configs[namespace][r.RuleGroup] = apimodels.GettableRuleGroupConfig{ - Name: r.RuleGroup, - Interval: ruleGroupInterval, - Rules: []apimodels.GettableExtendedRuleNode{ - toGettableExtendedRuleNode(*r, folder.Id, provenanceRecords), - }, - } - } else { - ruleGroupConfig.Rules = append(ruleGroupConfig.Rules, toGettableExtendedRuleNode(*r, folder.Id, provenanceRecords)) - configs[namespace][r.RuleGroup] = ruleGroupConfig - } - } - } - - for namespace, m := range configs { - for _, ruleGroupConfig := range m { - result[namespace] = append(result[namespace], ruleGroupConfig) + for groupName, groupRules := range m { + result[namespace] = append(result[namespace], toGettableRuleGroupConfig(groupName, groupRules, folder.Id, provenanceRecords)) } } return response.JSON(http.StatusOK, result) @@ -526,6 +500,22 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *models.ReqContext, namespace *mod return response.JSON(http.StatusAccepted, util.DynMap{"message": "rule group updated successfully"}) } +func toGettableRuleGroupConfig(groupName string, rules []*ngmodels.AlertRule, namespaceID int64, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableRuleGroupConfig { + ruleNodes := make([]apimodels.GettableExtendedRuleNode, 0, len(rules)) + var interval time.Duration + if len(rules) > 0 { + interval = time.Duration(rules[0].IntervalSeconds) * time.Second + } + for _, r := range rules { + ruleNodes = append(ruleNodes, toGettableExtendedRuleNode(*r, namespaceID, provenanceRecords)) + } + return apimodels.GettableRuleGroupConfig{ + Name: groupName, + Interval: model.Duration(interval), + Rules: ruleNodes, + } +} + func toGettableExtendedRuleNode(r ngmodels.AlertRule, namespaceID int64, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableExtendedRuleNode { provenance := ngmodels.ProvenanceNone if prov, exists := provenanceRecords[r.ResourceID()]; exists {