mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(plugins): removed external plugins and bundle code, not ready for master yet, will revert this commit in seperate branch
This commit is contained in:
parent
2ec5bc77d7
commit
5eab5dc47b
@ -156,12 +156,6 @@ func Register(r *macaron.Macaron) {
|
|||||||
r.Get("/plugins", GetDataSourcePlugins)
|
r.Get("/plugins", GetDataSourcePlugins)
|
||||||
}, reqOrgAdmin)
|
}, reqOrgAdmin)
|
||||||
|
|
||||||
// PluginBundles
|
|
||||||
r.Group("/plugins", func() {
|
|
||||||
r.Get("/", wrap(GetPluginBundles))
|
|
||||||
r.Post("/", bind(m.UpdatePluginBundleCmd{}), wrap(UpdatePluginBundle))
|
|
||||||
}, 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)
|
||||||
@ -197,7 +191,5 @@ func Register(r *macaron.Macaron) {
|
|||||||
// rendering
|
// rendering
|
||||||
r.Get("/render/*", reqSignedIn, RenderToPng)
|
r.Get("/render/*", reqSignedIn, RenderToPng)
|
||||||
|
|
||||||
InitExternalPluginRoutes(r)
|
|
||||||
|
|
||||||
r.NotFound(NotFoundHandler)
|
r.NotFound(NotFoundHandler)
|
||||||
}
|
}
|
||||||
|
@ -117,14 +117,7 @@ func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) {
|
|||||||
func GetDataSourcePlugins(c *middleware.Context) {
|
func GetDataSourcePlugins(c *middleware.Context) {
|
||||||
dsList := make(map[string]interface{})
|
dsList := make(map[string]interface{})
|
||||||
|
|
||||||
orgBundles := m.GetPluginBundlesQuery{OrgId: c.OrgId}
|
for key, value := range plugins.DataSources {
|
||||||
err := bus.Dispatch(&orgBundles)
|
|
||||||
if err != nil {
|
|
||||||
c.JsonApiErr(500, "Failed to get org plugin Bundles", err)
|
|
||||||
}
|
|
||||||
enabledPlugins := plugins.GetEnabledPlugins(orgBundles.Result)
|
|
||||||
|
|
||||||
for key, value := range enabledPlugins.DataSourcePlugins {
|
|
||||||
if !value.BuiltIn {
|
if !value.BuiltIn {
|
||||||
dsList[key] = value
|
dsList[key] = value
|
||||||
}
|
}
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/Unknwon/macaron"
|
|
||||||
"github.com/grafana/grafana/pkg/log"
|
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitExternalPluginRoutes(r *macaron.Macaron) {
|
|
||||||
for _, plugin := range plugins.ExternalPlugins {
|
|
||||||
log.Info("Plugin: Adding proxy routes for backend plugin")
|
|
||||||
for _, route := range plugin.Routes {
|
|
||||||
url := util.JoinUrlFragments("/api/plugin-proxy/", route.Path)
|
|
||||||
handlers := make([]macaron.Handler, 0)
|
|
||||||
if route.ReqSignedIn {
|
|
||||||
handlers = append(handlers, middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true}))
|
|
||||||
}
|
|
||||||
if route.ReqGrafanaAdmin {
|
|
||||||
handlers = append(handlers, middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true}))
|
|
||||||
}
|
|
||||||
if route.ReqSignedIn && route.ReqRole != "" {
|
|
||||||
if route.ReqRole == m.ROLE_ADMIN {
|
|
||||||
handlers = append(handlers, middleware.RoleAuth(m.ROLE_ADMIN))
|
|
||||||
} else if route.ReqRole == m.ROLE_EDITOR {
|
|
||||||
handlers = append(handlers, middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handlers = append(handlers, ExternalPlugin(route.Url))
|
|
||||||
r.Route(url, route.Method, handlers...)
|
|
||||||
log.Info("Plugin: Adding route %s", url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExternalPlugin(routeUrl string) macaron.Handler {
|
|
||||||
return func(c *middleware.Context) {
|
|
||||||
path := c.Params("*")
|
|
||||||
|
|
||||||
//Create a HTTP header with the context in it.
|
|
||||||
ctx, err := json.Marshal(c.SignedInUser)
|
|
||||||
if err != nil {
|
|
||||||
c.JsonApiErr(500, "failed to marshal context to json.", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
targetUrl, _ := url.Parse(routeUrl)
|
|
||||||
proxy := NewExternalPluginProxy(string(ctx), path, targetUrl)
|
|
||||||
proxy.Transport = dataProxyTransport
|
|
||||||
proxy.ServeHTTP(c.RW(), c.Req.Request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewExternalPluginProxy(ctx string, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy {
|
|
||||||
director := func(req *http.Request) {
|
|
||||||
req.URL.Scheme = targetUrl.Scheme
|
|
||||||
req.URL.Host = targetUrl.Host
|
|
||||||
req.Host = targetUrl.Host
|
|
||||||
|
|
||||||
req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
|
|
||||||
|
|
||||||
// clear cookie headers
|
|
||||||
req.Header.Del("Cookie")
|
|
||||||
req.Header.Del("Set-Cookie")
|
|
||||||
req.Header.Add("Grafana-Context", ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &httputil.ReverseProxy{Director: director}
|
|
||||||
}
|
|
@ -29,13 +29,6 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
|||||||
datasources := make(map[string]interface{})
|
datasources := make(map[string]interface{})
|
||||||
var defaultDatasource string
|
var defaultDatasource string
|
||||||
|
|
||||||
orgBundles := m.GetPluginBundlesQuery{OrgId: c.OrgId}
|
|
||||||
err := bus.Dispatch(&orgBundles)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
enabledPlugins := plugins.GetEnabledPlugins(orgBundles.Result)
|
|
||||||
|
|
||||||
for _, ds := range orgDataSources {
|
for _, ds := range orgDataSources {
|
||||||
url := ds.Url
|
url := ds.Url
|
||||||
|
|
||||||
@ -49,7 +42,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
|||||||
"url": url,
|
"url": url,
|
||||||
}
|
}
|
||||||
|
|
||||||
meta, exists := enabledPlugins.DataSourcePlugins[ds.Type]
|
meta, exists := plugins.DataSources[ds.Type]
|
||||||
if !exists {
|
if !exists {
|
||||||
log.Error(3, "Could not find plugin definition for data source: %v", ds.Type)
|
log.Error(3, "Could not find plugin definition for data source: %v", ds.Type)
|
||||||
continue
|
continue
|
||||||
@ -117,7 +110,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
panels := map[string]interface{}{}
|
panels := map[string]interface{}{}
|
||||||
for _, panel := range enabledPlugins.PanelPlugins {
|
for _, panel := range plugins.Panels {
|
||||||
panels[panel.Type] = map[string]interface{}{
|
panels[panel.Type] = map[string]interface{}{
|
||||||
"module": panel.Module,
|
"module": panel.Module,
|
||||||
"name": panel.Name,
|
"name": panel.Name,
|
||||||
|
@ -2,10 +2,8 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,53 +58,9 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
|||||||
Text: "Data Sources",
|
Text: "Data Sources",
|
||||||
Icon: "fa fa-fw fa-database",
|
Icon: "fa fa-fw fa-database",
|
||||||
Href: "/datasources",
|
Href: "/datasources",
|
||||||
}, &dtos.NavLink{
|
|
||||||
Text: "Plugins",
|
|
||||||
Icon: "fa fa-fw fa-cubes",
|
|
||||||
Href: "/plugins",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
orgBundles := m.GetPluginBundlesQuery{OrgId: c.OrgId}
|
|
||||||
err = bus.Dispatch(&orgBundles)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
enabledPlugins := plugins.GetEnabledPlugins(orgBundles.Result)
|
|
||||||
|
|
||||||
for _, plugin := range enabledPlugins.ExternalPlugins {
|
|
||||||
for _, js := range plugin.Js {
|
|
||||||
data.PluginJs = append(data.PluginJs, js.Module)
|
|
||||||
}
|
|
||||||
for _, css := range plugin.Css {
|
|
||||||
data.PluginCss = append(data.PluginCss, &dtos.PluginCss{Light: css.Light, Dark: css.Dark})
|
|
||||||
}
|
|
||||||
for _, item := range plugin.MainNavLinks {
|
|
||||||
// only show menu items for the specified roles.
|
|
||||||
var validRoles []m.RoleType
|
|
||||||
if string(item.ReqRole) == "" || item.ReqRole == m.ROLE_VIEWER {
|
|
||||||
validRoles = []m.RoleType{m.ROLE_ADMIN, m.ROLE_EDITOR, m.ROLE_VIEWER}
|
|
||||||
} else if item.ReqRole == m.ROLE_EDITOR {
|
|
||||||
validRoles = []m.RoleType{m.ROLE_ADMIN, m.ROLE_EDITOR}
|
|
||||||
} else if item.ReqRole == m.ROLE_ADMIN {
|
|
||||||
validRoles = []m.RoleType{m.ROLE_ADMIN}
|
|
||||||
}
|
|
||||||
ok := true
|
|
||||||
if len(validRoles) > 0 {
|
|
||||||
ok = false
|
|
||||||
for _, role := range validRoles {
|
|
||||||
if role == c.OrgRole {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{Text: item.Text, Href: item.Href, Icon: item.Icon})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetPluginBundles(c *middleware.Context) Response {
|
|
||||||
query := m.GetPluginBundlesQuery{OrgId: c.OrgId}
|
|
||||||
|
|
||||||
if err := bus.Dispatch(&query); err != nil {
|
|
||||||
return ApiError(500, "Failed to list Plugin Bundles", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
installedBundlesMap := make(map[string]*dtos.PluginBundle)
|
|
||||||
for t, b := range plugins.Bundles {
|
|
||||||
installedBundlesMap[t] = &dtos.PluginBundle{
|
|
||||||
Type: b.Type,
|
|
||||||
Enabled: b.Enabled,
|
|
||||||
Module: b.Module,
|
|
||||||
JsonData: make(map[string]interface{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seenBundles := make(map[string]bool)
|
|
||||||
|
|
||||||
result := make([]*dtos.PluginBundle, 0)
|
|
||||||
for _, b := range query.Result {
|
|
||||||
if def, ok := installedBundlesMap[b.Type]; ok {
|
|
||||||
result = append(result, &dtos.PluginBundle{
|
|
||||||
Type: b.Type,
|
|
||||||
Enabled: b.Enabled,
|
|
||||||
Module: def.Module,
|
|
||||||
JsonData: b.JsonData,
|
|
||||||
})
|
|
||||||
seenBundles[b.Type] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for t, b := range installedBundlesMap {
|
|
||||||
if _, ok := seenBundles[t]; !ok {
|
|
||||||
result = append(result, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Json(200, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdatePluginBundle(c *middleware.Context, cmd m.UpdatePluginBundleCmd) Response {
|
|
||||||
cmd.OrgId = c.OrgId
|
|
||||||
|
|
||||||
if _, ok := plugins.Bundles[cmd.Type]; !ok {
|
|
||||||
return ApiError(404, "Bundle type not installed.", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := bus.Dispatch(&cmd)
|
|
||||||
if err != nil {
|
|
||||||
return ApiError(500, "Failed to update plugin bundle", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ApiSuccess("Plugin updated")
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import "github.com/grafana/grafana/pkg/models"
|
|
||||||
|
|
||||||
type DataSourcePlugin struct {
|
type DataSourcePlugin struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -26,60 +24,3 @@ type StaticRootConfig struct {
|
|||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExternalPluginRoute struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Method string `json:"method"`
|
|
||||||
ReqSignedIn bool `json:"reqSignedIn"`
|
|
||||||
ReqGrafanaAdmin bool `json:"reqGrafanaAdmin"`
|
|
||||||
ReqRole models.RoleType `json:"reqRole"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalPluginJs struct {
|
|
||||||
Module string `json:"module"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalPluginNavLink struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Href string `json:"href"`
|
|
||||||
ReqRole models.RoleType `json:"reqRole"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalPluginCss struct {
|
|
||||||
Light string `json:"light"`
|
|
||||||
Dark string `json:"dark"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalPlugin struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Routes []*ExternalPluginRoute `json:"routes"`
|
|
||||||
Js []*ExternalPluginJs `json:"js"`
|
|
||||||
Css []*ExternalPluginCss `json:"css"`
|
|
||||||
MainNavLinks []*ExternalPluginNavLink `json:"mainNavLinks"`
|
|
||||||
StaticRootConfig *StaticRootConfig `json:"staticRoot"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PluginBundle struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Enabled bool `json:"enabled"`
|
|
||||||
PanelPlugins []string `json:"panelPlugins"`
|
|
||||||
DatasourcePlugins []string `json:"datasourcePlugins"`
|
|
||||||
ExternalPlugins []string `json:"externalPlugins"`
|
|
||||||
Module string `json:"module"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type EnabledPlugins struct {
|
|
||||||
PanelPlugins []*PanelPlugin
|
|
||||||
DataSourcePlugins map[string]*DataSourcePlugin
|
|
||||||
ExternalPlugins []*ExternalPlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEnabledPlugins() EnabledPlugins {
|
|
||||||
return EnabledPlugins{
|
|
||||||
PanelPlugins: make([]*PanelPlugin, 0),
|
|
||||||
DataSourcePlugins: make(map[string]*DataSourcePlugin),
|
|
||||||
ExternalPlugins: make([]*ExternalPlugin, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -9,16 +9,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/log"
|
"github.com/grafana/grafana/pkg/log"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DataSources map[string]DataSourcePlugin
|
DataSources map[string]DataSourcePlugin
|
||||||
Panels map[string]PanelPlugin
|
Panels map[string]PanelPlugin
|
||||||
ExternalPlugins map[string]ExternalPlugin
|
|
||||||
StaticRoutes []*StaticRootConfig
|
StaticRoutes []*StaticRootConfig
|
||||||
Bundles map[string]PluginBundle
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PluginScanner struct {
|
type PluginScanner struct {
|
||||||
@ -28,37 +25,14 @@ type PluginScanner struct {
|
|||||||
|
|
||||||
func Init() error {
|
func Init() error {
|
||||||
DataSources = make(map[string]DataSourcePlugin)
|
DataSources = make(map[string]DataSourcePlugin)
|
||||||
ExternalPlugins = make(map[string]ExternalPlugin)
|
|
||||||
StaticRoutes = make([]*StaticRootConfig, 0)
|
StaticRoutes = make([]*StaticRootConfig, 0)
|
||||||
Panels = make(map[string]PanelPlugin)
|
Panels = make(map[string]PanelPlugin)
|
||||||
Bundles = make(map[string]PluginBundle)
|
|
||||||
|
|
||||||
scan(path.Join(setting.StaticRootPath, "app/plugins"))
|
scan(path.Join(setting.StaticRootPath, "app/plugins"))
|
||||||
checkExternalPluginPaths()
|
checkExternalPluginPaths()
|
||||||
checkDependencies()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkDependencies() {
|
|
||||||
for bundleType, bundle := range Bundles {
|
|
||||||
for _, reqPanel := range bundle.PanelPlugins {
|
|
||||||
if _, ok := Panels[reqPanel]; !ok {
|
|
||||||
log.Fatal(4, "Bundle %s requires Panel type %s, but it is not present.", bundleType, reqPanel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, reqDataSource := range bundle.DatasourcePlugins {
|
|
||||||
if _, ok := DataSources[reqDataSource]; !ok {
|
|
||||||
log.Fatal(4, "Bundle %s requires DataSource type %s, but it is not present.", bundleType, reqDataSource)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, reqExtPlugin := range bundle.ExternalPlugins {
|
|
||||||
if _, ok := ExternalPlugins[reqExtPlugin]; !ok {
|
|
||||||
log.Fatal(4, "Bundle %s requires DataSource type %s, but it is not present.", bundleType, reqExtPlugin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkExternalPluginPaths() error {
|
func checkExternalPluginPaths() error {
|
||||||
for _, section := range setting.Cfg.Sections() {
|
for _, section := range setting.Cfg.Sections() {
|
||||||
if strings.HasPrefix(section.Name(), "plugin.") {
|
if strings.HasPrefix(section.Name(), "plugin.") {
|
||||||
@ -165,66 +139,5 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
|||||||
addStaticRoot(p.StaticRootConfig, currentDir)
|
addStaticRoot(p.StaticRootConfig, currentDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pluginType == "external" {
|
|
||||||
p := ExternalPlugin{}
|
|
||||||
reader.Seek(0, 0)
|
|
||||||
if err := jsonParser.Decode(&p); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if p.Type == "" {
|
|
||||||
return errors.New("Did not find type property in plugin.json")
|
|
||||||
}
|
|
||||||
ExternalPlugins[p.Type] = p
|
|
||||||
addStaticRoot(p.StaticRootConfig, currentDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pluginType == "bundle" {
|
|
||||||
p := PluginBundle{}
|
|
||||||
reader.Seek(0, 0)
|
|
||||||
if err := jsonParser.Decode(&p); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if p.Type == "" {
|
|
||||||
return errors.New("Did not find type property in plugin.json")
|
|
||||||
}
|
|
||||||
Bundles[p.Type] = p
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEnabledPlugins(orgBundles []*models.PluginBundle) EnabledPlugins {
|
|
||||||
enabledPlugins := NewEnabledPlugins()
|
|
||||||
|
|
||||||
orgBundlesMap := make(map[string]*models.PluginBundle)
|
|
||||||
for _, orgBundle := range orgBundles {
|
|
||||||
orgBundlesMap[orgBundle.Type] = orgBundle
|
|
||||||
}
|
|
||||||
|
|
||||||
for bundleType, bundle := range Bundles {
|
|
||||||
enabled := bundle.Enabled
|
|
||||||
// check if the bundle is stored in the DB.
|
|
||||||
if b, ok := orgBundlesMap[bundleType]; ok {
|
|
||||||
enabled = b.Enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if enabled {
|
|
||||||
for _, d := range bundle.DatasourcePlugins {
|
|
||||||
if ds, ok := DataSources[d]; ok {
|
|
||||||
enabledPlugins.DataSourcePlugins[d] = &ds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, p := range bundle.PanelPlugins {
|
|
||||||
if panel, ok := Panels[p]; ok {
|
|
||||||
enabledPlugins.PanelPlugins = append(enabledPlugins.PanelPlugins, &panel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, e := range bundle.ExternalPlugins {
|
|
||||||
if external, ok := ExternalPlugins[e]; ok {
|
|
||||||
enabledPlugins.ExternalPlugins = append(enabledPlugins.ExternalPlugins, &external)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return enabledPlugins
|
|
||||||
}
|
|
||||||
|
13
public/app/plugins/external/example/readme.md
vendored
13
public/app/plugins/external/example/readme.md
vendored
@ -1,13 +0,0 @@
|
|||||||
Example app is available at https://github.com/raintank/grafana-plugin-example
|
|
||||||
|
|
||||||
* Clone plugin repo git@github.com:raintank/grafana-plugin-example.git
|
|
||||||
|
|
||||||
* Modify grafana.ini (or custom.ini if your developing Grafana locally)
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[plugin.external-test]
|
|
||||||
path = /<the_path_were_you_cloned_it>/grafana-plugin-example
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"pluginType": "bundle",
|
|
||||||
"type": "core",
|
|
||||||
"module": "",
|
|
||||||
"enabled": true,
|
|
||||||
"panelPlugins": ["graph", "singlestat", "text", "dashlist", "table"],
|
|
||||||
"datasourcePlugins": ["mixed", "grafana", "graphite", "cloudwatch", "elasticsearch", "influxdb", "influxdb_08", "kairosdb", "opentsdb", "prometheus"],
|
|
||||||
"externalPlugins": []
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user