grafana/pkg/services/dashboardimport/service/service.go
2022-11-23 11:13:47 +02:00

156 lines
4.9 KiB
Go

package service
import (
"context"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboardimport"
"github.com/grafana/grafana/pkg/services/dashboardimport/api"
"github.com/grafana/grafana/pkg/services/dashboardimport/utils"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/librarypanels"
"github.com/grafana/grafana/pkg/services/plugindashboards"
"github.com/grafana/grafana/pkg/services/quota"
)
func ProvideService(routeRegister routing.RouteRegister,
quotaService quota.Service,
pluginDashboardService plugindashboards.Service, pluginStore plugins.Store,
libraryPanelService librarypanels.Service, dashboardService dashboards.DashboardService,
ac accesscontrol.AccessControl, folderService folder.Service,
) *ImportDashboardService {
s := &ImportDashboardService{
pluginDashboardService: pluginDashboardService,
dashboardService: dashboardService,
libraryPanelService: libraryPanelService,
folderService: folderService,
}
dashboardImportAPI := api.New(s, quotaService, pluginStore, ac)
dashboardImportAPI.RegisterAPIEndpoints(routeRegister)
return s
}
type ImportDashboardService struct {
pluginDashboardService plugindashboards.Service
dashboardService dashboards.DashboardService
libraryPanelService librarypanels.Service
folderService folder.Service
}
func (s *ImportDashboardService) ImportDashboard(ctx context.Context, req *dashboardimport.ImportDashboardRequest) (*dashboardimport.ImportDashboardResponse, error) {
var draftDashboard *models.Dashboard
if req.PluginId != "" {
loadReq := &plugindashboards.LoadPluginDashboardRequest{
PluginID: req.PluginId,
Reference: req.Path,
}
if resp, err := s.pluginDashboardService.LoadPluginDashboard(ctx, loadReq); err != nil {
return nil, err
} else {
draftDashboard = resp.Dashboard
}
} else {
draftDashboard = models.NewDashboardFromJson(req.Dashboard)
}
evaluator := utils.NewDashTemplateEvaluator(draftDashboard.Data, req.Inputs)
generatedDash, err := evaluator.Eval()
if err != nil {
return nil, err
}
// Maintain backwards compatibility by transforming array of library elements to map
libraryElements := generatedDash.Get("__elements")
libElementsArr, err := libraryElements.Array()
if err == nil {
elementMap := map[string]interface{}{}
for _, el := range libElementsArr {
libElement := simplejson.NewFromAny(el)
elementMap[libElement.Get("uid").MustString()] = el
}
libraryElements = simplejson.NewFromAny(elementMap)
}
// No need to keep these in the stored dashboard JSON
generatedDash.Del("__elements")
generatedDash.Del("__inputs")
generatedDash.Del("__requires")
// here we need to get FolderId from FolderUID if it present in the request, if both exist, FolderUID would overwrite FolderID
if req.FolderUid != "" {
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
OrgID: req.User.OrgID,
UID: &req.FolderUid,
SignedInUser: req.User,
})
if err != nil {
return nil, err
}
req.FolderId = folder.ID
} else {
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
ID: &req.FolderId,
OrgID: req.User.OrgID,
SignedInUser: req.User,
})
if err != nil {
return nil, err
}
req.FolderUid = folder.UID
}
saveCmd := models.SaveDashboardCommand{
Dashboard: generatedDash,
OrgId: req.User.OrgID,
UserId: req.User.UserID,
Overwrite: req.Overwrite,
PluginId: req.PluginId,
FolderId: req.FolderId,
}
dto := &dashboards.SaveDashboardDTO{
OrgId: saveCmd.OrgId,
Dashboard: saveCmd.GetDashboardModel(),
Overwrite: saveCmd.Overwrite,
User: req.User,
}
savedDashboard, err := s.dashboardService.ImportDashboard(ctx, dto)
if err != nil {
return nil, err
}
err = s.libraryPanelService.ImportLibraryPanelsForDashboard(ctx, req.User, libraryElements, generatedDash.Get("panels").MustArray(), req.FolderId)
if err != nil {
return nil, err
}
err = s.libraryPanelService.ConnectLibraryPanelsForDashboard(ctx, req.User, savedDashboard)
if err != nil {
return nil, err
}
return &dashboardimport.ImportDashboardResponse{
UID: savedDashboard.Uid,
PluginId: req.PluginId,
Title: savedDashboard.Title,
Path: req.Path,
Revision: savedDashboard.Data.Get("revision").MustInt64(1),
FolderId: savedDashboard.FolderId,
FolderUID: req.FolderUid,
ImportedUri: "db/" + savedDashboard.Slug,
ImportedUrl: savedDashboard.GetUrl(),
ImportedRevision: savedDashboard.Data.Get("revision").MustInt64(1),
Imported: true,
DashboardId: savedDashboard.Id,
Slug: savedDashboard.Slug,
}, nil
}