Add FolderUID for library elements (#79572)

* Add FolderUID in missing places for libraryelements

* Add migration for FolderUID in library elements table

* Add Folder UIDs tolibrary panels

* Adjust dashboard import with folder uid

* Fix lint

* Rename back FolderUID to UID

* Remove default

* Check if folderUID is nil

* Add unique indes on org_id,folder_uid,name and kind

* Update pkg/services/libraryelements/database.go

Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com>

* Fix folder integration test, with unique index on library elements

* Make folder uids nullable and rewrite migration query

* Use dashboard uid instead of folder_uid

* Adjust test

---------

Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com>
This commit is contained in:
idafurjes
2024-03-01 10:16:33 +01:00
committed by GitHub
parent 2182cc47ac
commit 2532047e7a
17 changed files with 229 additions and 157 deletions

View File

@@ -86,8 +86,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
Title: "Testing ConnectLibraryPanelsForDashboard",
Data: simplejson.NewFromAny(dashJSON),
}
// nolint:staticcheck
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash)
err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB)
require.NoError(t, err)
@@ -101,8 +100,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
scenarioWithLibraryPanel(t, "When an admin tries to store a dashboard with library panels inside and outside of rows, it should connect all",
func(t *testing.T, sc scenarioContext) {
cmd := model.CreateLibraryElementCommand{
FolderID: sc.initialResult.Result.FolderID, // nolint:staticcheck
Name: "Outside row",
Name: "Outside row",
Model: []byte(`
{
"datasource": "${DS_GDEV-TESTDATA}",
@@ -112,7 +110,8 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
"description": "A description"
}
`),
Kind: int64(model.PanelElement),
Kind: int64(model.PanelElement),
FolderUID: &sc.folder.UID,
}
outsidePanel, err := sc.elementService.CreateElement(sc.ctx, sc.user, cmd)
require.NoError(t, err)
@@ -185,8 +184,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
Title: "Testing ConnectLibraryPanelsForDashboard",
Data: simplejson.NewFromAny(dashJSON),
}
// nolint:staticcheck
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash)
err = sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB)
require.NoError(t, err)
@@ -232,8 +230,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
Title: "Testing ConnectLibraryPanelsForDashboard",
Data: simplejson.NewFromAny(dashJSON),
}
// nolint:staticcheck
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash)
err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB)
require.EqualError(t, err, errLibraryPanelHeaderUIDMissing.Error())
@@ -242,8 +239,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
scenarioWithLibraryPanel(t, "When an admin tries to store a dashboard with unused/removed library panels, it should disconnect unused/removed library panels",
func(t *testing.T, sc scenarioContext) {
unused, err := sc.elementService.CreateElement(sc.ctx, sc.user, model.CreateLibraryElementCommand{
FolderID: sc.folder.ID, // nolint:staticcheck
Name: "Unused Libray Panel",
Name: "Unused Libray Panel",
Model: []byte(`
{
"datasource": "${DS_GDEV-TESTDATA}",
@@ -253,7 +249,8 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
"description": "Unused description"
}
`),
Kind: int64(model.PanelElement),
Kind: int64(model.PanelElement),
FolderUID: &sc.folder.UID,
})
require.NoError(t, err)
dashJSON := map[string]any{
@@ -289,8 +286,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) {
Title: "Testing ConnectLibraryPanelsForDashboard",
Data: simplejson.NewFromAny(dashJSON),
}
// nolint:staticcheck
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash)
err = sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{sc.initialResult.Result.UID}, dashInDB.ID)
require.NoError(t, err)
@@ -399,7 +395,7 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
require.EqualError(t, err, model.ErrLibraryElementNotFound.Error())
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.NewFromAny(libraryElements), panels, 0)
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,
@@ -440,14 +436,14 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
require.NoError(t, err)
// nolint:staticcheck
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.New(), panels, sc.folder.ID)
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, simplejson.New(), panels, sc.folder.ID, sc.folder.UID)
require.NoError(t, err)
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
expected.FolderUID = sc.initialResult.Result.FolderUID
expected.Description = sc.initialResult.Result.Description
expected.Meta.FolderUID = sc.folder.UID
expected.Meta.FolderName = sc.folder.Title
@@ -556,7 +552,7 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
_, 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)
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, model.GetLibraryElementCommand{UID: outsideUID, FolderName: dashboards.RootFolderName})
@@ -578,9 +574,11 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
}
type libraryPanel struct {
ID int64
OrgID int64
ID int64
OrgID int64
// Deprecated: use FolderUID instead
FolderID int64
FolderUID string
UID string
Name string
Type string
@@ -616,6 +614,7 @@ type libraryElement struct {
ID int64 `json:"id"`
OrgID int64 `json:"orgId"`
FolderID int64 `json:"folderId"`
FolderUID string `json:"folderUid"`
UID string `json:"uid"`
Name string `json:"name"`
Kind int64 `json:"kind"`
@@ -649,7 +648,6 @@ func toLibraryElement(t *testing.T, res model.LibraryElementDTO) libraryElement
return libraryElement{
ID: res.ID,
OrgID: res.OrgID,
FolderID: res.FolderID, // nolint:staticcheck
UID: res.UID,
Name: res.Name,
Type: res.Type,
@@ -715,9 +713,7 @@ func getExpected(t *testing.T, res model.LibraryElementDTO, UID string, name str
}
}
func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash *dashboards.Dashboard, folderID int64) *dashboards.Dashboard {
// nolint:staticcheck
dash.FolderID = folderID
func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash *dashboards.Dashboard) *dashboards.Dashboard {
dashItem := &dashboards.SaveDashboardDTO{
Dashboard: dash,
Message: "",
@@ -774,8 +770,9 @@ func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, s
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
command := model.CreateLibraryElementCommand{
FolderID: sc.folder.ID, // nolint:staticcheck
Name: "Text - Library Panel",
FolderID: sc.folder.ID, // nolint:staticcheck
FolderUID: &sc.folder.UID,
Name: "Text - Library Panel",
Model: []byte(`
{
"datasource": "${DS_GDEV-TESTDATA}",
@@ -797,7 +794,7 @@ func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, s
Result: libraryPanel{
ID: resp.ID,
OrgID: resp.OrgID,
FolderID: resp.FolderID, // nolint:staticcheck
FolderUID: resp.FolderUID,
UID: resp.UID,
Name: resp.Name,
Type: resp.Type,