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

This commit is contained in:
Torkel Ödegaard
2016-03-11 09:57:20 +01:00
parent 60adcedebe
commit 2de439bd1e
11 changed files with 154 additions and 38 deletions

View File

@ -126,10 +126,6 @@ func Register(r *macaron.Macaron) {
r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite)) r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite))
r.Patch("/invites/:code/revoke", wrap(RevokeInvite)) 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) }, reqOrgAdmin)
// create new org // create new org
@ -177,6 +173,16 @@ func Register(r *macaron.Macaron) {
r.Get("/", wrap(GetDataSourceByName)) r.Get("/", wrap(GetDataSourceByName))
}, reqOrgAdmin) }, 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.Get("/frontend/settings/", GetFrontendSettings)
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest) r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest) r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest)

View File

@ -25,3 +25,9 @@ type PluginListItem struct {
Pinned bool `json:"pinned"` Pinned bool `json:"pinned"`
Info *plugins.PluginInfo `json:"info"` Info *plugins.PluginInfo `json:"info"`
} }
type InstallPluginDashboardCmd struct {
PluginId string `json:"pluginId"`
Path string `json:"path"`
Inputs map[string]interface{} `json:"inputs"`
}

View File

@ -107,3 +107,34 @@ func UpdatePluginSetting(c *middleware.Context, cmd m.UpdatePluginSettingCmd) Re
return ApiSuccess("Plugin settings updated") 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)
}

View File

@ -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
}

View File

@ -10,25 +10,27 @@ import (
) )
type PluginDashboardInfoDTO struct { type PluginDashboardInfoDTO struct {
Title string PluginId string `json:"pluginId"`
InstalledURI string Title string `json:"title"`
InstalledRevision string InstalledURI string `json:"installedURI"`
Revision string InstalledRevision string `json:"installedRevision"`
Description string Revision string `json:"revision"`
Description string `json:"description"`
Path string `json:"path"`
} }
func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDTO, error) { func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDTO, error) {
plugin, exists := Plugins[pluginId] plugin, exists := Plugins[pluginId]
if !exists { if !exists {
return nil, &PluginNotFoundError{pluginId} return nil, PluginNotFoundError{pluginId}
} }
result := make([]*PluginDashboardInfoDTO, 0) result := make([]*PluginDashboardInfoDTO, 0)
for _, include := range plugin.Includes { for _, include := range plugin.Includes {
if include.Type == PluginTypeDashboard { 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 return nil, err
} else { } else {
result = append(result, dashInfo) result = append(result, dashInfo)
@ -39,10 +41,9 @@ func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDT
return result, nil return result, nil
} }
func getDashboardImportStatus(orgId int64, plugin *PluginBase, dashInclude *PluginInclude) (*PluginDashboardInfoDTO, error) { func loadPluginDashboard(plugin *PluginBase, path string) (*m.Dashboard, error) {
res := &PluginDashboardInfoDTO{}
dashboardFilePath := filepath.Join(plugin.PluginDir, dashInclude.Path) dashboardFilePath := filepath.Join(plugin.PluginDir, path)
reader, err := os.Open(dashboardFilePath) reader, err := os.Open(dashboardFilePath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -57,8 +58,21 @@ func getDashboardImportStatus(orgId int64, plugin *PluginBase, dashInclude *Plug
return nil, err 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.Title = dashboard.Title
res.Revision = dashboard.GetString("revision", "1.0") res.Revision = dashboard.GetString("revision", "1.0")

View File

@ -21,7 +21,7 @@ type PluginNotFoundError struct {
PluginId string PluginId string
} }
func (e *PluginNotFoundError) Error() string { func (e PluginNotFoundError) Error() string {
return fmt.Sprintf("Plugin with id %s not found", e.PluginId) return fmt.Sprintf("Plugin with id %s not found", e.PluginId)
} }

View File

@ -11,29 +11,26 @@ export class DashImportListCtrl {
dashboards: any[]; dashboards: any[];
plugin: any; plugin: any;
constructor(private $http) { constructor(private $http, private backendSrv, private $rootScope) {
this.dashboards = []; this.dashboards = [];
this.plugin.includes backendSrv.get(`/api/plugins/dashboards/${this.plugin.id}`).then(dashboards => {
.filter(val => val.type === 'dashboard') this.dashboards = dashboards;
.forEach(this.getDashbordImportStatus.bind(this));
}
getDashbordImportStatus(dash) {
var dashUrl = this.plugin.baseUrl + '/' + dash.path;
this.$http.get(dashUrl).then(res => {
this.load(res.data);
}); });
} }
load(json) { import(dash) {
var model = angular.fromJson(json); var installCmd = {
console.log(model); 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 = ` var template = `
@ -45,11 +42,17 @@ var template = `
<i class="icon-gf icon-gf-dashboard"></i> <i class="icon-gf icon-gf-dashboard"></i>
</td> </td>
<td> <td>
{{dash.name}}</span> {{dash.title}}
</td>
<td>
{{dash.revision}}
</td>
<td>
{{dash.installedRevision}}
</td> </td>
<td class="width-2"> <td class="width-2">
<button class="btn btn-secondary" ng-click="ctrl.import(dash)">Install</button> <button class="btn btn-secondary" ng-click="ctrl.import(dash)">Install</button>
</td </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -54,7 +54,7 @@ export class DataSourceEditCtrl {
return this.$q.when(null); 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; datasourceTypes = plugins;
this.types = plugins; this.types = plugins;
}); });
@ -70,7 +70,7 @@ export class DataSourceEditCtrl {
typeChanged() { typeChanged() {
this.hasDashboards = false; 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.datasourceMeta = pluginInfo;
this.hasDashboards = _.findWhere(pluginInfo.includes, {type: 'dashboard'}); this.hasDashboards = _.findWhere(pluginInfo.includes, {type: 'dashboard'});
}); });

View File

@ -22,7 +22,7 @@ export class PluginEditCtrl {
} }
init() { 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.model = result;
this.pluginIcon = this.getPluginIcon(this.model.type); this.pluginIcon = this.getPluginIcon(this.model.type);

View File

@ -8,7 +8,7 @@ export class PluginListCtrl {
/** @ngInject */ /** @ngInject */
constructor(private backendSrv: any) { constructor(private backendSrv: any) {
this.backendSrv.get('api/org/plugins').then(plugins => { this.backendSrv.get('api/plugins', {embedded: 0}).then(plugins => {
this.plugins = plugins; this.plugins = plugins;
}); });
} }