diff --git a/pkg/api/api.go b/pkg/api/api.go index c1c45181b29..839978845ab 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -156,12 +156,6 @@ func Register(r *macaron.Macaron) { r.Get("/plugins", GetDataSourcePlugins) }, reqOrgAdmin) - // PluginBundles - r.Group("/plugins", func() { - r.Get("/", wrap(GetPluginBundles)) - r.Post("/", bind(m.UpdatePluginBundleCmd{}), wrap(UpdatePluginBundle)) - }, reqOrgAdmin) - r.Get("/frontend/settings/", GetFrontendSettings) r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest) r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest) @@ -197,7 +191,5 @@ func Register(r *macaron.Macaron) { // rendering r.Get("/render/*", reqSignedIn, RenderToPng) - InitExternalPluginRoutes(r) - r.NotFound(NotFoundHandler) } diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 1ac241c69bf..bef24d61d24 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -117,14 +117,7 @@ func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { func GetDataSourcePlugins(c *middleware.Context) { dsList := make(map[string]interface{}) - orgBundles := m.GetPluginBundlesQuery{OrgId: c.OrgId} - 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 { + for key, value := range plugins.DataSources { if !value.BuiltIn { dsList[key] = value } diff --git a/pkg/api/externalplugin.go b/pkg/api/externalplugin.go deleted file mode 100644 index 331de160ec7..00000000000 --- a/pkg/api/externalplugin.go +++ /dev/null @@ -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} -} diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 80eed15324a..5cba3258122 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -29,13 +29,6 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro datasources := make(map[string]interface{}) 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 { url := ds.Url @@ -49,7 +42,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro "url": url, } - meta, exists := enabledPlugins.DataSourcePlugins[ds.Type] + meta, exists := plugins.DataSources[ds.Type] if !exists { log.Error(3, "Could not find plugin definition for data source: %v", ds.Type) continue @@ -117,7 +110,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro } panels := map[string]interface{}{} - for _, panel := range enabledPlugins.PanelPlugins { + for _, panel := range plugins.Panels { panels[panel.Type] = map[string]interface{}{ "module": panel.Module, "name": panel.Name, diff --git a/pkg/api/index.go b/pkg/api/index.go index a4f5ac69928..9a39837261f 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -2,10 +2,8 @@ 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" "github.com/grafana/grafana/pkg/setting" ) @@ -60,53 +58,9 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { Text: "Data Sources", Icon: "fa fa-fw fa-database", 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 } diff --git a/pkg/api/plugin_bundle.go b/pkg/api/plugin_bundle.go deleted file mode 100644 index 9378189af7d..00000000000 --- a/pkg/api/plugin_bundle.go +++ /dev/null @@ -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") -} diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 05b9492f4e5..889229e79b9 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -1,7 +1,5 @@ package plugins -import "github.com/grafana/grafana/pkg/models" - type DataSourcePlugin struct { Type string `json:"type"` Name string `json:"name"` @@ -26,60 +24,3 @@ type StaticRootConfig struct { Url string `json:"url"` 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), - } -} diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 3e3a9d85152..10adc6ba09b 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -9,16 +9,13 @@ import ( "strings" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) var ( - DataSources map[string]DataSourcePlugin - Panels map[string]PanelPlugin - ExternalPlugins map[string]ExternalPlugin - StaticRoutes []*StaticRootConfig - Bundles map[string]PluginBundle + DataSources map[string]DataSourcePlugin + Panels map[string]PanelPlugin + StaticRoutes []*StaticRootConfig ) type PluginScanner struct { @@ -28,37 +25,14 @@ type PluginScanner struct { func Init() error { DataSources = make(map[string]DataSourcePlugin) - ExternalPlugins = make(map[string]ExternalPlugin) StaticRoutes = make([]*StaticRootConfig, 0) Panels = make(map[string]PanelPlugin) - Bundles = make(map[string]PluginBundle) scan(path.Join(setting.StaticRootPath, "app/plugins")) checkExternalPluginPaths() - checkDependencies() 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 { for _, section := range setting.Cfg.Sections() { if strings.HasPrefix(section.Name(), "plugin.") { @@ -165,66 +139,5 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error { 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 } - -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 -} diff --git a/public/app/plugins/external/example/readme.md b/public/app/plugins/external/example/readme.md deleted file mode 100644 index 78a9eb686d0..00000000000 --- a/public/app/plugins/external/example/readme.md +++ /dev/null @@ -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 = //grafana-plugin-example -``` - - - diff --git a/public/app/plugins/plugin.json b/public/app/plugins/plugin.json deleted file mode 100644 index d7356c7b8ad..00000000000 --- a/public/app/plugins/plugin.json +++ /dev/null @@ -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": [] -}