NestedFolders: Add library panels counting and deletion to folder registry (#69149)

* Expose library element service's folder service
* Register library panels, add count implementation
* Expand folder counts test
* Update registry deletion method interface
* Allow getting library elements from any folder
* Add test for library panel deletion
* Add test for library panel counting
This commit is contained in:
Arati R
2023-07-25 13:05:53 +02:00
committed by GitHub
parent 32e2304f10
commit 20ffbbc41e
16 changed files with 305 additions and 182 deletions
+38 -3
View File
@@ -10,21 +10,30 @@ import (
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/libraryelements"
"github.com/grafana/grafana/pkg/services/libraryelements/model"
"github.com/grafana/grafana/pkg/services/store/entity"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister,
libraryElementService libraryelements.Service) *LibraryPanelService {
return &LibraryPanelService{
libraryElementService libraryelements.Service, folderService folder.Service) (*LibraryPanelService, error) {
lps := LibraryPanelService{
Cfg: cfg,
SQLStore: sqlStore,
RouteRegister: routeRegister,
LibraryElementService: libraryElementService,
FolderService: folderService,
log: log.New("library-panels"),
}
if err := folderService.RegisterService(lps); err != nil {
return nil, err
}
return &lps, nil
}
// Service is a service for operating on library panels.
@@ -44,6 +53,7 @@ type LibraryPanelService struct {
SQLStore db.DB
RouteRegister routing.RouteRegister
LibraryElementService libraryelements.Service
FolderService folder.Service
log log.Logger
}
@@ -130,7 +140,7 @@ func importLibraryPanelsRecursively(c context.Context, service libraryelements.S
return errLibraryPanelHeaderUIDMissing
}
_, err := service.GetElement(c, signedInUser, UID)
_, err := service.GetElement(c, signedInUser, model.GetLibraryElementCommand{UID: UID, FolderName: dashboards.RootFolderName})
if err == nil {
continue
}
@@ -171,3 +181,28 @@ func importLibraryPanelsRecursively(c context.Context, service libraryelements.S
return nil
}
// CountInFolder is a handler for retrieving the number of library panels contained
// within a given folder and for a specific organisation.
func (lps LibraryPanelService) CountInFolder(ctx context.Context, orgID int64, folderUID string, u *user.SignedInUser) (int64, error) {
var count int64
return count, lps.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
folder, err := lps.FolderService.Get(ctx, &folder.GetFolderQuery{UID: &folderUID, OrgID: orgID, SignedInUser: u})
if err != nil {
return err
}
q := sess.Table("library_element").Where("org_id = ?", u.OrgID).
Where("folder_id = ?", folder.ID).Where("kind = ?", int64(model.PanelElement))
count, err = q.Count()
return err
})
}
// DeleteInFolder deletes the library panels contained in a given folder.
func (lps LibraryPanelService) DeleteInFolder(ctx context.Context, orgID int64, folderUID string, user *user.SignedInUser) error {
return lps.LibraryElementService.DeleteLibraryElementsInFolder(ctx, user, folderUID)
}
// Kind returns the name of the library panel type of entity.
func (lps LibraryPanelService) Kind() string { return entity.StandardKindLibraryPanel }
@@ -319,6 +319,23 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
require.Len(t, elements, 1)
require.Equal(t, sc.initialResult.Result.UID, elements[sc.initialResult.Result.UID].UID)
})
scenarioWithLibraryPanel(t, "It should return the correct count of library panels in a folder",
func(t *testing.T, sc scenarioContext) {
count, err := sc.lps.CountInFolder(context.Background(), sc.user.OrgID, sc.folder.UID, sc.user)
require.NoError(t, err)
require.Equal(t, int64(1), count)
})
scenarioWithLibraryPanel(t, "It should delete library panels in a folder",
func(t *testing.T, sc scenarioContext) {
err := sc.lps.DeleteInFolder(context.Background(), sc.user.OrgID, sc.folder.UID, sc.user)
require.NoError(t, err)
_, err = sc.elementService.GetElement(sc.ctx, sc.user,
model.GetLibraryElementCommand{UID: sc.initialResult.Result.UID, FolderName: sc.folder.Title})
require.EqualError(t, err, model.ErrLibraryElementNotFound.Error())
})
}
func TestImportLibraryPanelsForDashboard(t *testing.T) {
@@ -367,14 +384,16 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
},
}
_, err := sc.elementService.GetElement(sc.ctx, sc.user, missingUID)
_, err := sc.elementService.GetElement(sc.ctx, sc.user,
model.GetLibraryElementCommand{UID: missingUID, FolderName: dashboards.RootFolderName})
require.EqualError(t, err, model.ErrLibraryElementNotFound.Error())
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.NewFromAny(libraryElements), panels, 0)
require.NoError(t, err)
element, err := sc.elementService.GetElement(sc.ctx, sc.user, missingUID)
element, err := sc.elementService.GetElement(sc.ctx, sc.user,
model.GetLibraryElementCommand{UID: missingUID, FolderName: dashboards.RootFolderName})
require.NoError(t, err)
var expected = getExpected(t, element, missingUID, missingName, missingModel)
var result = toLibraryElement(t, element)
@@ -406,13 +425,15 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
},
}
_, err := sc.elementService.GetElement(sc.ctx, sc.user, existingUID)
_, err := sc.elementService.GetElement(sc.ctx, sc.user,
model.GetLibraryElementCommand{UID: existingUID, FolderName: dashboards.RootFolderName})
require.NoError(t, err)
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.New(), panels, sc.folder.ID)
require.NoError(t, err)
element, err := sc.elementService.GetElement(sc.ctx, sc.user, existingUID)
element, err := sc.elementService.GetElement(sc.ctx, sc.user,
model.GetLibraryElementCommand{UID: existingUID, FolderName: dashboards.RootFolderName})
require.NoError(t, err)
var expected = getExpected(t, element, existingUID, existingName, sc.initialResult.Result.Model)
expected.FolderID = sc.initialResult.Result.FolderID
@@ -519,16 +540,15 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
},
},
}
_, err := sc.elementService.GetElement(sc.ctx, sc.user, outsideUID)
_, err := sc.elementService.GetElement(sc.ctx, sc.user, model.GetLibraryElementCommand{UID: outsideUID, FolderName: dashboards.RootFolderName})
require.EqualError(t, err, model.ErrLibraryElementNotFound.Error())
_, err = sc.elementService.GetElement(sc.ctx, sc.user, insideUID)
_, err = sc.elementService.GetElement(sc.ctx, sc.user, model.GetLibraryElementCommand{UID: insideUID, FolderName: dashboards.RootFolderName})
require.EqualError(t, err, model.ErrLibraryElementNotFound.Error())
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.NewFromAny(libraryElements), panels, 0)
require.NoError(t, err)
element, err := sc.elementService.GetElement(sc.ctx, sc.user, outsideUID)
element, err := sc.elementService.GetElement(sc.ctx, sc.user, model.GetLibraryElementCommand{UID: outsideUID, FolderName: dashboards.RootFolderName})
require.NoError(t, err)
expected := getExpected(t, element, outsideUID, outsideName, outsideModel)
result := toLibraryElement(t, element)
@@ -536,7 +556,7 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
}
element, err = sc.elementService.GetElement(sc.ctx, sc.user, insideUID)
element, err = sc.elementService.GetElement(sc.ctx, sc.user, model.GetLibraryElementCommand{UID: insideUID, FolderName: dashboards.RootFolderName})
require.NoError(t, err)
expected = getExpected(t, element, insideUID, insideName, insideModel)
result = toLibraryElement(t, element)
@@ -607,6 +627,7 @@ type scenarioContext struct {
folder *folder.Folder
initialResult libraryPanelResult
sqlStore db.DB
lps LibraryPanelService
}
func toLibraryElement(t *testing.T, res model.LibraryElementDTO) libraryElement {
@@ -814,6 +835,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
Cfg: cfg,
SQLStore: sqlStore,
LibraryElementService: elementService,
FolderService: folderService,
}
usr := &user.SignedInUser{
@@ -853,6 +875,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
service: &service,
elementService: elementService,
sqlStore: sqlStore,
lps: service,
}
foldr := createFolder(t, sc, "ScenarioFolder")