mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Nested Folders: Support getting of nested folder in folder service wh… (#58597)
* Nested Folders: Support getting of nested folder in folder service when feature flag is set * Fix lint * Fix some tests * Fix ngalert test * ngalert fix * Fix API tests * Fix some tests and lint * Fix lint 2 * Fix library elements and panels * Add access control to get folder * Cleanup and minor test change
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
@@ -181,7 +182,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
|
||||
return response.JSON(http.StatusOK, ruleResponse)
|
||||
}
|
||||
|
||||
func (srv PrometheusSrv) toRuleGroup(groupName string, folder *models.Folder, rules []*ngmodels.AlertRule, labelOptions []ngmodels.LabelOption) *apimodels.RuleGroup {
|
||||
func (srv PrometheusSrv) toRuleGroup(groupName string, folder *folder.Folder, rules []*ngmodels.AlertRule, labelOptions []ngmodels.LabelOption) *apimodels.RuleGroup {
|
||||
newGroup := &apimodels.RuleGroup{
|
||||
Name: groupName,
|
||||
File: folder.Title, // file is what Prometheus uses for provisioning, we replace it with namespace.
|
||||
|
||||
@@ -83,7 +83,7 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *models.ReqContext, namespaceTitle s
|
||||
unauthz, provisioned := false, false
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
RuleGroup: ruleGroup,
|
||||
}
|
||||
if err = srv.store.ListAlertRules(ctx, &q); err != nil {
|
||||
@@ -163,7 +163,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext, namespace
|
||||
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
}
|
||||
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
|
||||
@@ -189,7 +189,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext, namespace
|
||||
if !authorizeAccessToRuleGroup(rules, hasAccess) {
|
||||
continue
|
||||
}
|
||||
result[namespaceTitle] = append(result[namespaceTitle], toGettableRuleGroupConfig(groupName, rules, namespace.Id, provenanceRecords))
|
||||
result[namespaceTitle] = append(result[namespaceTitle], toGettableRuleGroupConfig(groupName, rules, namespace.ID, provenanceRecords))
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
@@ -205,7 +205,7 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext, namespaceTitl
|
||||
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
RuleGroup: ruleGroup,
|
||||
}
|
||||
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
|
||||
@@ -226,7 +226,7 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext, namespaceTitl
|
||||
}
|
||||
|
||||
result := apimodels.RuleGroupConfigResponse{
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, q.Result, namespace.Id, provenanceRecords),
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, q.Result, namespace.ID, provenanceRecords),
|
||||
}
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
}
|
||||
@@ -296,7 +296,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
|
||||
continue
|
||||
}
|
||||
namespace := folder.Title
|
||||
result[namespace] = append(result[namespace], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, folder.Id, provenanceRecords))
|
||||
result[namespace] = append(result[namespace], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, folder.ID, provenanceRecords))
|
||||
}
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConf
|
||||
|
||||
groupKey := ngmodels.AlertRuleGroupKey{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUID: namespace.Uid,
|
||||
NamespaceUID: namespace.UID,
|
||||
RuleGroup: ruleGroupConfig.Name,
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
acMock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
||||
@@ -382,7 +383,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@@ -426,12 +427,12 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
folder1 := randFolder()
|
||||
folder2 := randFolder()
|
||||
ruleStore.Folders[orgID] = []*models2.Folder{folder1, folder2}
|
||||
ruleStore.Folders[orgID] = []*folder.Folder{folder1, folder2}
|
||||
|
||||
group1Key := models.GenerateGroupKey(orgID)
|
||||
group1Key.NamespaceUID = folder1.Uid
|
||||
group1Key.NamespaceUID = folder1.UID
|
||||
group2Key := models.GenerateGroupKey(orgID)
|
||||
group2Key.NamespaceUID = folder2.Uid
|
||||
group2Key.NamespaceUID = folder2.UID
|
||||
|
||||
group1 := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(group1Key)))
|
||||
group2 := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(group2Key)))
|
||||
@@ -464,7 +465,7 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@@ -509,7 +510,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(groupKey)))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@@ -544,7 +545,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@@ -699,9 +700,9 @@ func withGroup(groupName string) func(rule *models.AlertRule) {
|
||||
}
|
||||
}
|
||||
|
||||
func withNamespace(namespace *models2.Folder) func(rule *models.AlertRule) {
|
||||
func withNamespace(namespace *folder.Folder) func(rule *models.AlertRule) {
|
||||
return func(rule *models.AlertRule) {
|
||||
rule.NamespaceUID = namespace.Uid
|
||||
rule.NamespaceUID = namespace.UID
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@@ -18,7 +18,7 @@ func validateRuleNode(
|
||||
groupName string,
|
||||
interval time.Duration,
|
||||
orgId int64,
|
||||
namespace *models.Folder,
|
||||
namespace *folder.Folder,
|
||||
conditionValidator func(ngmodels.Condition) error,
|
||||
cfg *setting.UnifiedAlertingSettings) (*ngmodels.AlertRule, error) {
|
||||
intervalSeconds, err := validateInterval(cfg, interval)
|
||||
@@ -93,7 +93,7 @@ func validateRuleNode(
|
||||
Data: ruleNode.GrafanaManagedAlert.Data,
|
||||
UID: ruleNode.GrafanaManagedAlert.UID,
|
||||
IntervalSeconds: intervalSeconds,
|
||||
NamespaceUID: namespace.Uid,
|
||||
NamespaceUID: namespace.UID,
|
||||
RuleGroup: groupName,
|
||||
NoDataState: noDataState,
|
||||
ExecErrState: errorState,
|
||||
@@ -152,7 +152,7 @@ func validateForInterval(ruleNode *apimodels.PostableExtendedRuleNode) (time.Dur
|
||||
func validateRuleGroup(
|
||||
ruleGroupConfig *apimodels.PostableRuleGroupConfig,
|
||||
orgId int64,
|
||||
namespace *models.Folder,
|
||||
namespace *folder.Folder,
|
||||
conditionValidator func(ngmodels.Condition) error,
|
||||
cfg *setting.UnifiedAlertingSettings) ([]*ngmodels.AlertRule, error) {
|
||||
if ruleGroupConfig.Name == "" {
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/exp/rand"
|
||||
|
||||
models2 "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@@ -83,18 +83,18 @@ func validGroup(cfg *setting.UnifiedAlertingSettings, rules ...apimodels.Postabl
|
||||
}
|
||||
}
|
||||
|
||||
func randFolder() *models2.Folder {
|
||||
return &models2.Folder{
|
||||
Id: rand.Int63(),
|
||||
Uid: util.GenerateShortUID(),
|
||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||
Url: "",
|
||||
Version: 0,
|
||||
Created: time.Time{},
|
||||
Updated: time.Time{},
|
||||
UpdatedBy: 0,
|
||||
CreatedBy: 0,
|
||||
HasACL: false,
|
||||
func randFolder() *folder.Folder {
|
||||
return &folder.Folder{
|
||||
ID: rand.Int63(),
|
||||
UID: util.GenerateShortUID(),
|
||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||
// URL: "",
|
||||
// Version: 0,
|
||||
Created: time.Time{},
|
||||
Updated: time.Time{},
|
||||
// UpdatedBy: 0,
|
||||
// CreatedBy: 0,
|
||||
// HasACL: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
||||
require.Equal(t, int64(interval.Seconds()), alert.IntervalSeconds)
|
||||
require.Equal(t, int64(0), alert.Version)
|
||||
require.Equal(t, api.GrafanaManagedAlert.UID, alert.UID)
|
||||
require.Equal(t, folder.Uid, alert.NamespaceUID)
|
||||
require.Equal(t, folder.UID, alert.NamespaceUID)
|
||||
require.Nil(t, alert.DashboardUID)
|
||||
require.Nil(t, alert.PanelID)
|
||||
require.Equal(t, name, alert.RuleGroup)
|
||||
|
||||
@@ -3,15 +3,15 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
// RuleStore is the interface for persisting alert rules and instances
|
||||
type RuleStore interface {
|
||||
GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*models.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*models.Folder, error)
|
||||
GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*folder.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*folder.Folder, error)
|
||||
GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) error
|
||||
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user