mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 19:52:38 +08:00
feat(plugins): progress on dashboard installs , #4298
This commit is contained in:
@ -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)
|
||||||
|
@ -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"`
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
56
pkg/plugins/dashboard_installer.go
Normal file
56
pkg/plugins/dashboard_installer.go
Normal 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
|
||||||
|
}
|
@ -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")
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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'});
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user