Export: Fix export/import of dash with library panels (#49319)
This commit is contained in:
@@ -31,7 +31,12 @@ type Service interface {
|
||||
LoadLibraryPanelsForDashboard(c context.Context, dash *models.Dashboard) error
|
||||
CleanLibraryPanelsForDashboard(dash *models.Dashboard) error
|
||||
ConnectLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard) error
|
||||
ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard, folderID int64) error
|
||||
ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, libraryPanels *simplejson.Json, panels []interface{}, folderID int64) error
|
||||
}
|
||||
|
||||
type LibraryInfo struct {
|
||||
Panels []*interface{}
|
||||
LibraryPanels *simplejson.Json
|
||||
}
|
||||
|
||||
// LibraryPanelService is the service for the Panel Library feature.
|
||||
@@ -89,7 +94,6 @@ func loadLibraryPanelsRecursively(elements map[string]libraryelements.LibraryEle
|
||||
elem.Set("gridPos", gridPos)
|
||||
}
|
||||
elem.Set("id", panelAsJSON.Get("id").MustInt64())
|
||||
elem.Set("type", fmt.Sprintf("Library panel with UID: \"%s\"", UID))
|
||||
elem.Set("libraryPanel", map[string]interface{}{
|
||||
"uid": UID,
|
||||
})
|
||||
@@ -253,12 +257,11 @@ func connectLibraryPanelsRecursively(c context.Context, panels []interface{}, li
|
||||
}
|
||||
|
||||
// ImportLibraryPanelsForDashboard loops through all panels in dashboard JSON and creates any missing library panels in the database.
|
||||
func (lps *LibraryPanelService) ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard, folderID int64) error {
|
||||
return importLibraryPanelsRecursively(c, lps.LibraryElementService, signedInUser, dash.Data, folderID)
|
||||
func (lps *LibraryPanelService) ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, libraryPanels *simplejson.Json, panels []interface{}, folderID int64) error {
|
||||
return importLibraryPanelsRecursively(c, lps.LibraryElementService, signedInUser, libraryPanels, panels, folderID)
|
||||
}
|
||||
|
||||
func importLibraryPanelsRecursively(c context.Context, service libraryelements.Service, signedInUser *models.SignedInUser, parent *simplejson.Json, folderID int64) error {
|
||||
panels := parent.Get("panels").MustArray()
|
||||
func importLibraryPanelsRecursively(c context.Context, service libraryelements.Service, signedInUser *models.SignedInUser, libraryPanels *simplejson.Json, panels []interface{}, folderID int64) error {
|
||||
for _, panel := range panels {
|
||||
panelAsJSON := simplejson.NewFromAny(panel)
|
||||
libraryPanel := panelAsJSON.Get("libraryPanel")
|
||||
@@ -269,7 +272,7 @@ func importLibraryPanelsRecursively(c context.Context, service libraryelements.S
|
||||
|
||||
// we have a row
|
||||
if panelType == "row" {
|
||||
err := importLibraryPanelsRecursively(c, service, signedInUser, panelAsJSON, folderID)
|
||||
err := importLibraryPanelsRecursively(c, service, signedInUser, libraryPanels, panelAsJSON.Get("panels").MustArray(), folderID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -281,22 +284,24 @@ func importLibraryPanelsRecursively(c context.Context, service libraryelements.S
|
||||
if len(UID) == 0 {
|
||||
return errLibraryPanelHeaderUIDMissing
|
||||
}
|
||||
name := libraryPanel.Get("name").MustString()
|
||||
if len(name) == 0 {
|
||||
return errLibraryPanelHeaderNameMissing
|
||||
}
|
||||
|
||||
_, err := service.GetElement(c, signedInUser, UID)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if errors.Is(err, libraryelements.ErrLibraryElementNotFound) {
|
||||
panelAsJSON.Set("libraryPanel",
|
||||
map[string]interface{}{
|
||||
"uid": UID,
|
||||
"name": name,
|
||||
})
|
||||
Model, err := json.Marshal(&panelAsJSON)
|
||||
name := libraryPanel.Get("name").MustString()
|
||||
if len(name) == 0 {
|
||||
return errLibraryPanelHeaderNameMissing
|
||||
}
|
||||
|
||||
elementModel := libraryPanels.Get(UID).Get("model")
|
||||
elementModel.Set("libraryPanel", map[string]interface{}{
|
||||
"uid": UID,
|
||||
})
|
||||
|
||||
Model, err := json.Marshal(&elementModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package librarypanels
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -439,7 +438,6 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) {
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": sc.initialResult.Result.UID,
|
||||
},
|
||||
"type": fmt.Sprintf("Library panel with UID: \"%s\"", sc.initialResult.Result.UID),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1021,30 +1019,35 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
}
|
||||
|
||||
dashJSON := map[string]interface{}{
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
missingModel,
|
||||
var libraryElements = map[string]interface{}{
|
||||
missingUID: map[string]interface{}{
|
||||
"model": missingModel,
|
||||
},
|
||||
}
|
||||
dash := models.Dashboard{
|
||||
Title: "Testing ImportLibraryPanelsForDashboard",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
|
||||
panels := []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": missingUID,
|
||||
"name": missingName,
|
||||
},
|
||||
},
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
|
||||
_, err := sc.elementService.GetElement(sc.ctx, sc.user, missingUID)
|
||||
|
||||
require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error())
|
||||
|
||||
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, 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, missingUID)
|
||||
@@ -1061,39 +1064,28 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
|
||||
var existingUID = sc.initialResult.Result.UID
|
||||
var existingName = sc.initialResult.Result.Name
|
||||
|
||||
dashJSON := map[string]interface{}{
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
panels := []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"description": "Updated description",
|
||||
"datasource": "Updated datasource",
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": sc.initialResult.Result.UID,
|
||||
"name": sc.initialResult.Result.Name,
|
||||
},
|
||||
"title": "Updated Title",
|
||||
"type": "stat",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": sc.initialResult.Result.UID,
|
||||
"name": sc.initialResult.Result.Name,
|
||||
},
|
||||
},
|
||||
}
|
||||
dash := models.Dashboard{
|
||||
Title: "Testing ImportLibraryPanelsForDashboard",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
|
||||
_, err := sc.elementService.GetElement(sc.ctx, sc.user, existingUID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, sc.folder.Id)
|
||||
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)
|
||||
@@ -1129,6 +1121,7 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
|
||||
"title": "Outside row",
|
||||
"type": "text",
|
||||
}
|
||||
|
||||
var insideUID = "iK7NsyDNz"
|
||||
var insideName = "Inside Library Panel"
|
||||
var insideModel = map[string]interface{}{
|
||||
@@ -1148,54 +1141,67 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) {
|
||||
"type": "text",
|
||||
}
|
||||
|
||||
dashJSON := map[string]interface{}{
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"collapsed": true,
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
},
|
||||
"id": int64(2),
|
||||
"type": "row",
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(3),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 7,
|
||||
},
|
||||
},
|
||||
insideModel,
|
||||
},
|
||||
},
|
||||
outsideModel,
|
||||
var libraryElements = map[string]interface{}{
|
||||
outsideUID: map[string]interface{}{
|
||||
"model": outsideModel,
|
||||
},
|
||||
insideUID: map[string]interface{}{
|
||||
"model": insideModel,
|
||||
},
|
||||
}
|
||||
dash := models.Dashboard{
|
||||
Title: "Testing ImportLibraryPanelsForDashboard",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
|
||||
panels := []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": outsideUID,
|
||||
"name": outsideName,
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"collapsed": true,
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
},
|
||||
"id": int64(2),
|
||||
"type": "row",
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": int64(3),
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 7,
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": insideUID,
|
||||
"name": insideName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
|
||||
_, err := sc.elementService.GetElement(sc.ctx, sc.user, outsideUID)
|
||||
require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error())
|
||||
_, err = sc.elementService.GetElement(sc.ctx, sc.user, insideUID)
|
||||
require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error())
|
||||
|
||||
err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, 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, outsideUID)
|
||||
|
||||
Reference in New Issue
Block a user