Add alert store to folder api builder

pull/97466/head
leonorfmartins 7 months ago
parent 9dc7722a96
commit 1cffc51ba0
No known key found for this signature in database
  1. 56
      pkg/api/folder.go
  2. 10
      pkg/services/ngalert/store/alert_rule.go

@ -19,7 +19,6 @@ import (
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
folderalpha1 "github.com/grafana/grafana/pkg/apis/folder/v0alpha1"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/slugify"
internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders"
@ -33,6 +32,7 @@ import (
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/libraryelements/model"
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
@ -645,7 +645,7 @@ type folderK8sHandler struct {
// #TODO check if it makes more sense to move this to FolderAPIBuilder
accesscontrolService accesscontrol.Service
userService user.Service
kvstore *kvstore.NamespacedKVStore
ngAlertSvc ngstore.DBstore
}
//-----------------------------------------------------------------------------------------
@ -653,13 +653,14 @@ type folderK8sHandler struct {
//-----------------------------------------------------------------------------------------
func newFolderK8sHandler(hs *HTTPServer) *folderK8sHandler {
return &folderK8sHandler{
gvr: folderalpha1.FolderResourceInfo.GroupVersionResource(),
namespacer: request.GetNamespaceMapper(hs.Cfg),
clientConfigProvider: hs.clientConfigProvider,
accesscontrolService: hs.accesscontrolService,
userService: hs.userService,
kvstore: kvstore.WithNamespace(hs.kvStore, 0, "storage.dualwriting"),
ngAlertSvc: hs.ngAlertSvc,
}
}
@ -780,16 +781,11 @@ func (fk8s *folderK8sHandler) deleteFolder(c *contextmodel.ReqContext) {
ctx := c.Req.Context()
hasDependants, err := hasDependants(ctx, fk8s.kvstore)
err := fk8s.checkForAlertRules()
if err != nil {
fk8s.writeError(c, err)
return
}
if hasDependants {
fk8s.writeError(c, folder.ErrFolderNotEmpty.Errorf("this folder is not empty. Please make sure it does not contain any dashboards, alerts, library panels or SLOs"))
return
}
if err := client.Delete(ctx, uid, v1.DeleteOptions{}); err != nil {
fk8s.writeError(c, err)
return
@ -838,40 +834,6 @@ func (fk8s *folderK8sHandler) updateFolder(c *contextmodel.ReqContext) {
// Utility functions
//-----------------------------------------------------------------------------------------
func hasDependants(ctx context.Context, kvstore *kvstore.NamespacedKVStore) (bool, error) {
// TODO: how can we check for alert rules and library panels?
var folderDependants = []string{
folderalpha1.RESOURCEGROUP,
"dashboards.dashboard.grafana.app",
"librarypanels.librarypanel.grafana.app",
"alertrules.alertmanager.grafana.app",
}
var hasDependants bool
for _, resource := range folderDependants {
item, found, err := kvstore.Get(ctx, resource)
if err != nil {
return false, err
}
if found {
mode, err := strconv.Atoi(item)
if err != nil {
return false, err
}
// if dual writer mode > 2, it means the source of truth is unified store
if mode > 2 {
// call unified store count
fmt.Println("counting dependants in unified store")
}
// if not found or mode < 3 call legacy store count
} else {
fmt.Println("counting dependants in legacy store")
}
}
// TODO: also check for SLORules in another store
return hasDependants, nil
}
func (fk8s *folderK8sHandler) getClient(c *contextmodel.ReqContext) (dynamic.ResourceInterface, bool) {
dyn, err := dynamic.NewForConfig(fk8s.clientConfigProvider.GetDirectRestConfig(c))
if err != nil {
@ -1037,7 +999,7 @@ func (fk8s *folderK8sHandler) getFolderACMetadata(c *contextmodel.ReqContext, f
return nil, nil
}
folderIDs, err := fk8s.getParents(f)
folderIDs, err := getParents(f)
if err != nil {
return nil, err
}
@ -1053,7 +1015,11 @@ func (fk8s *folderK8sHandler) getFolderACMetadata(c *contextmodel.ReqContext, f
return metadata, nil
}
func (fk8s *folderK8sHandler) getParents(f *folder.Folder) (map[string]bool, error) {
func (fk8s *folderK8sHandler) checkForAlertRules() error {
return folder.ErrFolderNotEmpty.Errorf("folder contains alert rules, please delete them first.")
}
func getParents(f *folder.Folder) (map[string]bool, error) {
folderIDs := map[string]bool{f.UID: true}
if (f.UID == accesscontrol.GeneralFolderUID) || (f.UID == folder.SharedWithMeFolderUID) {
return folderIDs, nil

@ -445,6 +445,16 @@ func (st DBstore) CountInFolders(ctx context.Context, orgID int64, folderUIDs []
return count, err
}
func (st DBstore) FolderHasAlertRules(ctx context.Context, orgID int64, folderUID string) (bool, error) {
var count int64
var err error
err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
count, err = sess.Table("alert_rule").Where("org_id = ?", orgID).Where("namespace_uid = ?", folderUID).Count()
return err
})
return count > 0, err
}
// ListAlertRules is a handler for retrieving alert rules of specific organisation.
func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (result ngmodels.RulesGroup, err error) {
err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {

Loading…
Cancel
Save