diff --git a/pkg/api/api.go b/pkg/api/api.go index 0915bbd678d..44b56ea62f6 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -126,10 +126,6 @@ func Register(r *macaron.Macaron) { r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite)) r.Patch("/invites/:code/revoke", wrap(RevokeInvite)) - // apps - r.Get("/plugins", wrap(GetPluginList)) - r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById)) - r.Post("/plugins/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting)) }, reqOrgAdmin) // create new org @@ -177,6 +173,16 @@ func Register(r *macaron.Macaron) { r.Get("/", wrap(GetDataSourceByName)) }, reqOrgAdmin) + r.Group("/plugins", func() { + r.Get("/", wrap(GetPluginList)) + + r.Get("/dashboards/:pluginId", wrap(GetPluginDashboards)) + r.Post("/dashboards/install", bind(dtos.InstallPluginDashboardCmd{}), wrap(InstallPluginDashboard)) + + r.Get("/:pluginId/settings", wrap(GetPluginSettingById)) + r.Post("/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting)) + }, reqOrgAdmin) + r.Get("/frontend/settings/", GetFrontendSettings) r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest) r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest) diff --git a/pkg/api/dtos/plugins.go b/pkg/api/dtos/plugins.go index 61b149d73e4..144b9b09755 100644 --- a/pkg/api/dtos/plugins.go +++ b/pkg/api/dtos/plugins.go @@ -25,3 +25,9 @@ type PluginListItem struct { Pinned bool `json:"pinned"` Info *plugins.PluginInfo `json:"info"` } + +type InstallPluginDashboardCmd struct { + PluginId string `json:"pluginId"` + Path string `json:"path"` + Inputs map[string]interface{} `json:"inputs"` +} diff --git a/pkg/api/plugin_setting.go b/pkg/api/plugins.go similarity index 77% rename from pkg/api/plugin_setting.go rename to pkg/api/plugins.go index 1ceecdfac18..1ba0dde6c9f 100644 --- a/pkg/api/plugin_setting.go +++ b/pkg/api/plugins.go @@ -107,3 +107,34 @@ func UpdatePluginSetting(c *middleware.Context, cmd m.UpdatePluginSettingCmd) Re return ApiSuccess("Plugin settings updated") } + +func GetPluginDashboards(c *middleware.Context) Response { + pluginId := c.Params(":pluginId") + + if list, err := plugins.GetPluginDashboards(c.OrgId, pluginId); err != nil { + if notfound, ok := err.(plugins.PluginNotFoundError); ok { + return ApiError(404, notfound.Error(), nil) + } + + return ApiError(500, "Failed to get plugin dashboards", err) + } else { + return Json(200, list) + } +} + +func InstallPluginDashboard(c *middleware.Context, apiCmd dtos.InstallPluginDashboardCmd) Response { + + cmd := plugins.InstallPluginDashboardCommand{ + OrgId: c.OrgId, + UserId: c.UserId, + PluginId: apiCmd.PluginId, + Path: apiCmd.Path, + Inputs: apiCmd.Inputs, + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to install dashboard", err) + } + + return Json(200, cmd.Result) +} diff --git a/pkg/models/plugin_setting.go b/pkg/models/plugin_settings.go similarity index 100% rename from pkg/models/plugin_setting.go rename to pkg/models/plugin_settings.go diff --git a/pkg/plugins/dashboard_installer.go b/pkg/plugins/dashboard_installer.go new file mode 100644 index 00000000000..9f52b518d70 --- /dev/null +++ b/pkg/plugins/dashboard_installer.go @@ -0,0 +1,56 @@ +package plugins + +import ( + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +type InstallPluginDashboardCommand struct { + Path string `json:"string"` + Inputs map[string]interface{} `json:"inputs"` + + OrgId int64 `json:"-"` + UserId int64 `json:"-"` + PluginId string `json:"-"` + Result *PluginDashboardInfoDTO +} + +func init() { + bus.AddHandler("plugins", InstallPluginDashboard) +} + +func InstallPluginDashboard(cmd *InstallPluginDashboardCommand) error { + plugin, exists := Plugins[cmd.PluginId] + + if !exists { + return PluginNotFoundError{cmd.PluginId} + } + + var dashboard *m.Dashboard + var err error + + if dashboard, err = loadPluginDashboard(plugin, cmd.Path); err != nil { + return err + } + + saveCmd := m.SaveDashboardCommand{ + Dashboard: dashboard.Data, + OrgId: cmd.OrgId, + UserId: cmd.UserId, + } + + if err := bus.Dispatch(&saveCmd); err != nil { + return err + } + + cmd.Result = &PluginDashboardInfoDTO{ + PluginId: cmd.PluginId, + Title: dashboard.Title, + Path: cmd.Path, + Revision: dashboard.GetString("revision", "1.0"), + InstalledURI: "db/" + saveCmd.Result.Slug, + InstalledRevision: dashboard.GetString("revision", "1.0"), + } + + return nil +} diff --git a/pkg/plugins/dashboards.go b/pkg/plugins/dashboards.go index f253db480a0..9acb64cec1b 100644 --- a/pkg/plugins/dashboards.go +++ b/pkg/plugins/dashboards.go @@ -10,25 +10,27 @@ import ( ) type PluginDashboardInfoDTO struct { - Title string - InstalledURI string - InstalledRevision string - Revision string - Description string + PluginId string `json:"pluginId"` + Title string `json:"title"` + InstalledURI string `json:"installedURI"` + InstalledRevision string `json:"installedRevision"` + Revision string `json:"revision"` + Description string `json:"description"` + Path string `json:"path"` } func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDTO, error) { plugin, exists := Plugins[pluginId] if !exists { - return nil, &PluginNotFoundError{pluginId} + return nil, PluginNotFoundError{pluginId} } result := make([]*PluginDashboardInfoDTO, 0) for _, include := range plugin.Includes { if include.Type == PluginTypeDashboard { - if dashInfo, err := getDashboardImportStatus(orgId, plugin, include); err != nil { + if dashInfo, err := getDashboardImportStatus(orgId, plugin, include.Path); err != nil { return nil, err } else { result = append(result, dashInfo) @@ -39,10 +41,9 @@ func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDT return result, nil } -func getDashboardImportStatus(orgId int64, plugin *PluginBase, dashInclude *PluginInclude) (*PluginDashboardInfoDTO, error) { - res := &PluginDashboardInfoDTO{} +func loadPluginDashboard(plugin *PluginBase, path string) (*m.Dashboard, error) { - dashboardFilePath := filepath.Join(plugin.PluginDir, dashInclude.Path) + dashboardFilePath := filepath.Join(plugin.PluginDir, path) reader, err := os.Open(dashboardFilePath) if err != nil { return nil, err @@ -57,8 +58,21 @@ func getDashboardImportStatus(orgId int64, plugin *PluginBase, dashInclude *Plug return nil, err } - dashboard := m.NewDashboardFromJson(data) + return m.NewDashboardFromJson(data), nil +} +func getDashboardImportStatus(orgId int64, plugin *PluginBase, path string) (*PluginDashboardInfoDTO, error) { + res := &PluginDashboardInfoDTO{} + + var dashboard *m.Dashboard + var err error + + if dashboard, err = loadPluginDashboard(plugin, path); err != nil { + return nil, err + } + + res.Path = path + res.PluginId = plugin.Id res.Title = dashboard.Title res.Revision = dashboard.GetString("revision", "1.0") diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index ac9fb5e04dc..502c355eda8 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -21,7 +21,7 @@ type PluginNotFoundError struct { PluginId string } -func (e *PluginNotFoundError) Error() string { +func (e PluginNotFoundError) Error() string { return fmt.Sprintf("Plugin with id %s not found", e.PluginId) } diff --git a/public/app/features/dashboard/import_list/import_list.ts b/public/app/features/dashboard/import_list/import_list.ts index 09a5b65de76..7d88d7f9f0a 100644 --- a/public/app/features/dashboard/import_list/import_list.ts +++ b/public/app/features/dashboard/import_list/import_list.ts @@ -11,29 +11,26 @@ export class DashImportListCtrl { dashboards: any[]; plugin: any; - constructor(private $http) { + constructor(private $http, private backendSrv, private $rootScope) { this.dashboards = []; - this.plugin.includes - .filter(val => val.type === 'dashboard') - .forEach(this.getDashbordImportStatus.bind(this)); - } - - getDashbordImportStatus(dash) { - var dashUrl = this.plugin.baseUrl + '/' + dash.path; - this.$http.get(dashUrl).then(res => { - this.load(res.data); - + backendSrv.get(`/api/plugins/dashboards/${this.plugin.id}`).then(dashboards => { + this.dashboards = dashboards; }); } - load(json) { - var model = angular.fromJson(json); - console.log(model); + import(dash) { + var installCmd = { + pluginId: this.plugin.id, + path: dash.path, + inputs: {} + }; + + this.backendSrv.post(`/api/plugins/dashboards/install`, installCmd).then(res => { + console.log(res); + }); } - import(dash) { - } } var template = ` @@ -45,11 +42,17 @@ var template = `