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:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user