NestedFolders: Add folder service registry with dashboard service implementation (#65033)

* Delete folders, dashboards with registry service
Co-authored-by: Serge Zaitsev <hello@zserge.com>
* Update signature of ProvideDashboardServiceImpl
* Regenerate mockery file
* Add test for DeleteInFolder
* Add test for DeleteDashboardsInFolder
* Delete child dashboard associations via registry
* Add validation of folder uid and org id

---------

Co-authored-by: Serge Zaitsev <hello@zserge.com>
This commit is contained in:
Arati R
2023-04-14 11:17:23 +02:00
committed by GitHub
parent 4abe0249ba
commit cab3ba519a
19 changed files with 1039 additions and 116 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"strings"
"sync"
"time"
"github.com/grafana/grafana/pkg/bus"
@@ -36,6 +37,9 @@ type Service struct {
// bus is currently used to publish event in case of title change
bus bus.Bus
mutex sync.RWMutex
registry map[string]folder.RegistryService
}
func ProvideService(
@@ -58,6 +62,7 @@ func ProvideService(
accessControl: ac,
bus: bus,
db: db,
registry: make(map[string]folder.RegistryService),
}
if features.IsEnabled(featuremgmt.FlagNestedFolders) {
srv.DBMigration(db)
@@ -437,6 +442,12 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
if cmd.SignedInUser == nil {
return folder.ErrBadRequest.Errorf("missing signed in user")
}
if cmd.UID == "" {
return folder.ErrBadRequest.Errorf("missing UID")
}
if cmd.OrgID < 1 {
return folder.ErrBadRequest.Errorf("invalid orgID")
}
result := []string{cmd.UID}
err := s.db.InTransaction(ctx, func(ctx context.Context) error {
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
@@ -466,6 +477,11 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
}
return dashboards.ErrFolderAccessDenied
}
if err := s.deleteChildrenInFolder(ctx, dashFolder.OrgID, dashFolder.UID); err != nil {
return err
}
err = s.legacyDelete(ctx, cmd, dashFolder)
if err != nil {
return err
@@ -477,6 +493,15 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
return err
}
func (s *Service) deleteChildrenInFolder(ctx context.Context, orgID int64, UID string) error {
for _, v := range s.registry {
if err := v.DeleteInFolder(ctx, orgID, UID); err != nil {
return err
}
}
return nil
}
func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderCommand, dashFolder *folder.Folder) error {
deleteCmd := dashboards.DeleteDashboardCommand{OrgID: cmd.OrgID, ID: dashFolder.ID, ForceDeleteFolderRules: cmd.ForceDeleteRules}
@@ -588,7 +613,8 @@ func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFold
}
result = append(result, subfolders...)
}
logger.Info("deleting folder", "org_id", cmd.OrgID, "uid", cmd.UID)
logger.Info("deleting folder and its contents", "org_id", cmd.OrgID, "uid", cmd.UID)
err = s.store.Delete(ctx, cmd.UID, cmd.OrgID)
if err != nil {
logger.Info("failed deleting folder", "org_id", cmd.OrgID, "uid", cmd.UID, "err", err)
@@ -794,3 +820,17 @@ func toFolderError(err error) error {
return err
}
func (s *Service) RegisterService(r folder.RegistryService) error {
s.mutex.Lock()
defer s.mutex.Unlock()
_, ok := s.registry[r.Kind()]
if ok {
return folder.ErrTargetRegistrySrvConflict.Errorf("target registry service: %s already exists", r.Kind())
}
s.registry[r.Kind()] = r
return nil
}