Commit 2de439bd by Torkel Ödegaard

feat(plugins): progress on dashboard installs , #4298

parent 60adcede
......@@ -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)
......
......@@ -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"`
}
......@@ -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)
}
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
}
......@@ -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")
......
......@@ -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)
}
......
......@@ -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);
});
}
}
var template = `
......@@ -45,11 +42,17 @@ var template = `
<i class="icon-gf icon-gf-dashboard"></i>
</td>
<td>
{{dash.name}}</span>
{{dash.title}}
</td>
<td>
{{dash.revision}}
</td>
<td>
{{dash.installedRevision}}
</td>
<td class="width-2">
<button class="btn btn-secondary" ng-click="ctrl.import(dash)">Install</button>
</td
</td>
</tr>
</tbody>
</table>
......
......@@ -54,7 +54,7 @@ export class DataSourceEditCtrl {
return this.$q.when(null);
}
return this.backendSrv.get('/api/org/plugins', {enabled: 1, type: 'datasource'}).then(plugins => {
return this.backendSrv.get('/api/plugins', {enabled: 1, type: 'datasource'}).then(plugins => {
datasourceTypes = plugins;
this.types = plugins;
});
......@@ -70,7 +70,7 @@ export class DataSourceEditCtrl {
typeChanged() {
this.hasDashboards = false;
return this.backendSrv.get('/api/org/plugins/' + this.current.type + '/settings').then(pluginInfo => {
return this.backendSrv.get('/api/plugins/' + this.current.type + '/settings').then(pluginInfo => {
this.datasourceMeta = pluginInfo;
this.hasDashboards = _.findWhere(pluginInfo.includes, {type: 'dashboard'});
});
......
......@@ -22,7 +22,7 @@ export class PluginEditCtrl {
}
init() {
return this.backendSrv.get(`/api/org/plugins/${this.pluginId}/settings`).then(result => {
return this.backendSrv.get(`/api/plugins/${this.pluginId}/settings`).then(result => {
this.model = result;
this.pluginIcon = this.getPluginIcon(this.model.type);
......
......@@ -8,7 +8,7 @@ export class PluginListCtrl {
/** @ngInject */
constructor(private backendSrv: any) {
this.backendSrv.get('api/org/plugins').then(plugins => {
this.backendSrv.get('api/plugins', {embedded: 0}).then(plugins => {
this.plugins = plugins;
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment