Alerting: Expose updated_by in rules GET APIs (#99525)
--------- Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@@ -53,6 +54,7 @@ type RulerSrv struct {
|
||||
cfg *setting.UnifiedAlertingSettings
|
||||
conditionValidator ConditionValidator
|
||||
authz RuleAccessControlService
|
||||
userService user.Service
|
||||
|
||||
amConfigStore AMConfigStore
|
||||
amRefresher AMRefresher
|
||||
@@ -211,7 +213,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *contextmodel.ReqContext, nam
|
||||
result := apimodels.NamespaceConfigResponse{}
|
||||
|
||||
for groupKey, rules := range ruleGroups {
|
||||
result[namespace.Fullpath] = append(result[namespace.Fullpath], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, provenanceRecords))
|
||||
result[namespace.Fullpath] = append(result[namespace.Fullpath], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, provenanceRecords, srv.resolveUserIdToNameFn(c.Req.Context())))
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
@@ -246,7 +248,7 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *contextmodel.ReqContext, namespa
|
||||
|
||||
result := apimodels.RuleGroupConfigResponse{
|
||||
// nolint:staticcheck
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(finalRuleGroup, rules, provenanceRecords),
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(finalRuleGroup, rules, provenanceRecords, srv.resolveUserIdToNameFn(c.Req.Context())),
|
||||
}
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
}
|
||||
@@ -300,7 +302,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *contextmodel.ReqContext) response.Res
|
||||
srv.log.Error("Namespace not visible to the user", "user", id, "userNamespace", userNamespace, "namespace", groupKey.NamespaceUID)
|
||||
continue
|
||||
}
|
||||
result[folder.Fullpath] = append(result[folder.Fullpath], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, provenanceRecords))
|
||||
result[folder.Fullpath] = append(result[folder.Fullpath], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, provenanceRecords, srv.resolveUserIdToNameFn(c.Req.Context())))
|
||||
}
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
@@ -323,7 +325,7 @@ func (srv RulerSrv) RouteGetRuleByUID(c *contextmodel.ReqContext, ruleUID string
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "failed to get rule provenance", err)
|
||||
}
|
||||
|
||||
result := toGettableExtendedRuleNode(rule, map[string]ngmodels.Provenance{rule.ResourceID(): provenance})
|
||||
result := toGettableExtendedRuleNode(rule, map[string]ngmodels.Provenance{rule.ResourceID(): provenance}, srv.resolveUserIdToNameFn(ctx))
|
||||
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
@@ -533,7 +535,7 @@ func changesToResponse(finalChanges *store.GroupDelta) response.Response {
|
||||
return response.JSON(http.StatusAccepted, body)
|
||||
}
|
||||
|
||||
func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableRuleGroupConfig {
|
||||
func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, provenanceRecords map[string]ngmodels.Provenance, userIdToName userIDToUserInfoFn) apimodels.GettableRuleGroupConfig {
|
||||
rules.SortByGroupIndex()
|
||||
ruleNodes := make([]apimodels.GettableExtendedRuleNode, 0, len(rules))
|
||||
var interval time.Duration
|
||||
@@ -541,7 +543,7 @@ func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, prov
|
||||
interval = time.Duration(rules[0].IntervalSeconds) * time.Second
|
||||
}
|
||||
for _, r := range rules {
|
||||
ruleNodes = append(ruleNodes, toGettableExtendedRuleNode(*r, provenanceRecords))
|
||||
ruleNodes = append(ruleNodes, toGettableExtendedRuleNode(*r, provenanceRecords, userIdToName))
|
||||
}
|
||||
return apimodels.GettableRuleGroupConfig{
|
||||
Name: groupName,
|
||||
@@ -550,7 +552,7 @@ func toGettableRuleGroupConfig(groupName string, rules ngmodels.RulesGroup, prov
|
||||
}
|
||||
}
|
||||
|
||||
func toGettableExtendedRuleNode(r ngmodels.AlertRule, provenanceRecords map[string]ngmodels.Provenance) apimodels.GettableExtendedRuleNode {
|
||||
func toGettableExtendedRuleNode(r ngmodels.AlertRule, provenanceRecords map[string]ngmodels.Provenance, userIdToName userIDToUserInfoFn) apimodels.GettableExtendedRuleNode {
|
||||
provenance := ngmodels.ProvenanceNone
|
||||
if prov, exists := provenanceRecords[r.ResourceID()]; exists {
|
||||
provenance = prov
|
||||
@@ -564,6 +566,7 @@ func toGettableExtendedRuleNode(r ngmodels.AlertRule, provenanceRecords map[stri
|
||||
Condition: r.Condition,
|
||||
Data: ApiAlertQueriesFromAlertQueries(r.Data),
|
||||
Updated: r.Updated,
|
||||
UpdatedBy: userIdToName(r.UpdatedBy),
|
||||
IntervalSeconds: r.IntervalSeconds,
|
||||
Version: r.Version,
|
||||
UID: r.UID,
|
||||
@@ -724,3 +727,28 @@ func (srv RulerSrv) searchAuthorizedAlertRules(ctx context.Context, q authorized
|
||||
}
|
||||
return byGroupKey, totalGroups, nil
|
||||
}
|
||||
|
||||
type userIDToUserInfoFn func(id *ngmodels.UserUID) *apimodels.UserInfo
|
||||
|
||||
// getIdentityName returns name of either user or service account
|
||||
func (srv RulerSrv) resolveUserIdToNameFn(ctx context.Context) userIDToUserInfoFn {
|
||||
return func(id *ngmodels.UserUID) *apimodels.UserInfo {
|
||||
if id == nil {
|
||||
return nil
|
||||
}
|
||||
u, err := srv.userService.GetByUID(ctx, &user.GetUserByUIDQuery{
|
||||
UID: string(*id),
|
||||
})
|
||||
var result string
|
||||
if err != nil {
|
||||
srv.log.FromContext(ctx).Warn("Failed to get user by uid. Defaulting to an empty name", "uid", id, "error", err)
|
||||
}
|
||||
if u != nil {
|
||||
result = u.NameOrFallback()
|
||||
}
|
||||
return &apimodels.UserInfo{
|
||||
UID: string(*id),
|
||||
Name: result,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user