2016-01-09 16:34:20 -06:00
|
|
|
package plugins
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2020-10-21 02:10:54 -05:00
|
|
|
"path/filepath"
|
2016-01-19 11:18:53 -06:00
|
|
|
"strings"
|
2016-01-09 16:34:20 -06:00
|
|
|
|
2016-02-09 04:17:49 -06:00
|
|
|
"github.com/gosimple/slug"
|
2016-01-09 16:34:20 -06:00
|
|
|
"github.com/grafana/grafana/pkg/models"
|
2020-01-13 13:18:45 -06:00
|
|
|
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
2020-10-21 02:10:54 -05:00
|
|
|
"github.com/grafana/grafana/pkg/plugins/backendplugin/grpcplugin"
|
2016-03-22 04:15:47 -05:00
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
2020-10-21 02:10:54 -05:00
|
|
|
"github.com/grafana/grafana/pkg/util/errutil"
|
2016-01-09 16:34:20 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type AppPlugin struct {
|
|
|
|
FrontendPluginBase
|
2021-02-25 03:00:21 -06:00
|
|
|
Routes []*AppPluginRoute `json:"routes"`
|
|
|
|
AutoEnabled bool `json:"autoEnabled"`
|
2016-01-11 03:44:04 -06:00
|
|
|
|
2016-03-08 11:17:47 -06:00
|
|
|
FoundChildPlugins []*PluginInclude `json:"-"`
|
|
|
|
Pinned bool `json:"-"`
|
2020-10-21 02:10:54 -05:00
|
|
|
|
|
|
|
Executable string `json:"executable,omitempty"`
|
2016-01-09 16:34:20 -06:00
|
|
|
}
|
|
|
|
|
2020-04-24 03:32:13 -05:00
|
|
|
// AppPluginRoute describes a plugin route that is defined in
|
|
|
|
// the plugin.json file for a plugin.
|
2016-01-21 11:15:04 -06:00
|
|
|
type AppPluginRoute struct {
|
2020-04-24 03:32:13 -05:00
|
|
|
Path string `json:"path"`
|
|
|
|
Method string `json:"method"`
|
|
|
|
ReqRole models.RoleType `json:"reqRole"`
|
|
|
|
URL string `json:"url"`
|
|
|
|
URLParams []AppPluginRouteURLParam `json:"urlParams"`
|
|
|
|
Headers []AppPluginRouteHeader `json:"headers"`
|
|
|
|
TokenAuth *JwtTokenAuth `json:"tokenAuth"`
|
|
|
|
JwtTokenAuth *JwtTokenAuth `json:"jwtTokenAuth"`
|
2021-03-31 09:38:35 -05:00
|
|
|
Body json.RawMessage `json:"body"`
|
2016-01-21 11:15:04 -06:00
|
|
|
}
|
|
|
|
|
2020-04-24 03:32:13 -05:00
|
|
|
// AppPluginRouteHeader describes an HTTP header that is forwarded with
|
|
|
|
// the proxied request for a plugin route
|
2016-01-21 11:15:04 -06:00
|
|
|
type AppPluginRouteHeader struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Content string `json:"content"`
|
|
|
|
}
|
|
|
|
|
2020-04-24 03:32:13 -05:00
|
|
|
// AppPluginRouteURLParam describes query string parameters for
|
|
|
|
// a url in a plugin route
|
|
|
|
type AppPluginRouteURLParam struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Content string `json:"content"`
|
|
|
|
}
|
|
|
|
|
2018-09-06 08:50:16 -05:00
|
|
|
// JwtTokenAuth struct is both for normal Token Auth and JWT Token Auth with
|
|
|
|
// an uploaded JWT file.
|
2017-08-23 10:18:43 -05:00
|
|
|
type JwtTokenAuth struct {
|
|
|
|
Url string `json:"url"`
|
2018-09-06 08:50:16 -05:00
|
|
|
Scopes []string `json:"scopes"`
|
2017-08-23 10:18:43 -05:00
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
}
|
|
|
|
|
2021-03-08 00:02:49 -06:00
|
|
|
func (app *AppPlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) (
|
|
|
|
interface{}, error) {
|
2020-01-13 10:13:17 -06:00
|
|
|
if err := decoder.Decode(app); err != nil {
|
2021-03-08 00:02:49 -06:00
|
|
|
return nil, err
|
2016-02-10 04:03:12 -06:00
|
|
|
}
|
2016-02-09 15:10:36 -06:00
|
|
|
|
2020-10-21 02:10:54 -05:00
|
|
|
if app.Backend {
|
|
|
|
cmd := ComposePluginStartCommand(app.Executable)
|
2021-03-08 00:02:49 -06:00
|
|
|
fullpath := filepath.Join(base.PluginDir, cmd)
|
2020-10-21 02:10:54 -05:00
|
|
|
factory := grpcplugin.NewBackendPlugin(app.Id, fullpath, grpcplugin.PluginStartFuncs{})
|
|
|
|
if err := backendPluginManager.Register(app.Id, factory); err != nil {
|
2021-03-08 00:02:49 -06:00
|
|
|
return nil, errutil.Wrapf(err, "failed to register backend plugin")
|
2020-10-21 02:10:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 00:02:49 -06:00
|
|
|
return app, nil
|
2016-02-09 15:10:36 -06:00
|
|
|
}
|
|
|
|
|
2021-03-10 05:41:29 -06:00
|
|
|
func (app *AppPlugin) InitApp(panels map[string]*PanelPlugin, dataSources map[string]*DataSourcePlugin,
|
|
|
|
cfg *setting.Cfg) []*PluginStaticRoute {
|
|
|
|
staticRoutes := app.InitFrontendPlugin(cfg)
|
2016-02-09 15:10:36 -06:00
|
|
|
|
2016-01-19 11:18:53 -06:00
|
|
|
// check if we have child panels
|
2021-03-08 00:02:49 -06:00
|
|
|
for _, panel := range panels {
|
2016-01-19 11:18:53 -06:00
|
|
|
if strings.HasPrefix(panel.PluginDir, app.PluginDir) {
|
2021-03-10 05:41:29 -06:00
|
|
|
panel.setPathsBasedOnApp(app, cfg)
|
2016-03-08 11:17:47 -06:00
|
|
|
app.FoundChildPlugins = append(app.FoundChildPlugins, &PluginInclude{
|
2016-01-19 11:18:53 -06:00
|
|
|
Name: panel.Name,
|
|
|
|
Id: panel.Id,
|
|
|
|
Type: panel.Type,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-09 11:37:08 -06:00
|
|
|
// check if we have child datasources
|
2021-03-08 00:02:49 -06:00
|
|
|
for _, ds := range dataSources {
|
2016-02-09 11:37:08 -06:00
|
|
|
if strings.HasPrefix(ds.PluginDir, app.PluginDir) {
|
2021-03-10 05:41:29 -06:00
|
|
|
ds.setPathsBasedOnApp(app, cfg)
|
2016-03-08 11:17:47 -06:00
|
|
|
app.FoundChildPlugins = append(app.FoundChildPlugins, &PluginInclude{
|
2016-02-09 11:37:08 -06:00
|
|
|
Name: ds.Name,
|
|
|
|
Id: ds.Id,
|
|
|
|
Type: ds.Type,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// slugify pages
|
2016-03-22 04:15:47 -05:00
|
|
|
for _, include := range app.Includes {
|
|
|
|
if include.Slug == "" {
|
|
|
|
include.Slug = slug.Make(include.Name)
|
|
|
|
}
|
|
|
|
if include.Type == "page" && include.DefaultNav {
|
2021-03-10 05:41:29 -06:00
|
|
|
app.DefaultNavUrl = cfg.AppSubURL + "/plugins/" + app.Id + "/page/" + include.Slug
|
2016-03-22 04:15:47 -05:00
|
|
|
}
|
|
|
|
if include.Type == "dashboard" && include.DefaultNav {
|
2021-03-10 05:41:29 -06:00
|
|
|
app.DefaultNavUrl = cfg.AppSubURL + "/dashboard/db/" + include.Slug
|
2016-02-09 04:17:49 -06:00
|
|
|
}
|
|
|
|
}
|
2021-03-08 00:02:49 -06:00
|
|
|
|
|
|
|
return staticRoutes
|
2016-01-09 16:34:20 -06:00
|
|
|
}
|