mirror of https://github.com/grafana/grafana
Merge branch 'externalPlugin' of https://github.com/raintank/grafana into external-plugins
commit
b21fa2daa0
@ -0,0 +1,74 @@ |
||||
package api |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"github.com/Unknwon/macaron" |
||||
"github.com/grafana/grafana/pkg/log" |
||||
"github.com/grafana/grafana/pkg/middleware" |
||||
"github.com/grafana/grafana/pkg/plugins" |
||||
"github.com/grafana/grafana/pkg/util" |
||||
"net/http" |
||||
"net/http/httputil" |
||||
"net/url" |
||||
) |
||||
|
||||
func InitExternalPluginRoutes(r *macaron.Macaron) { |
||||
/* |
||||
// Handle Auth and role requirements
|
||||
if route.ReqSignedIn { |
||||
c.Invoke(middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true})) |
||||
} |
||||
if route.ReqGrafanaAdmin { |
||||
c.Invoke(middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})) |
||||
} |
||||
if route.ReqRole != nil { |
||||
if *route.ReqRole == m.ROLE_EDITOR { |
||||
c.Invoke(middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)) |
||||
} |
||||
if *route.ReqRole == m.ROLE_ADMIN { |
||||
c.Invoke(middleware.RoleAuth(m.ROLE_ADMIN)) |
||||
} |
||||
} |
||||
*/ |
||||
for _, plugin := range plugins.ExternalPlugins { |
||||
log.Info("adding routes for external plugin") |
||||
for _, route := range plugin.Settings.Routes { |
||||
log.Info("adding route %s /plugins%s", route.Method, route.Path) |
||||
r.Route(util.JoinUrlFragments("/plugins/", route.Path), route.Method, ExternalPlugin(route.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} |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
Example app is available at https://github.com/raintank/grafana-plugin-example |
||||
|
||||
To use, download the example app from github and run it (requires python Flask). Then rename the "_plugin.json" file in this director to "plugin.json" and restart Grafana. |
||||
@ -0,0 +1,41 @@ |
||||
{ |
||||
"pluginType": "externalPlugin", |
||||
"settings": { |
||||
"routes": [ |
||||
{ |
||||
"path": "/example/static/*", |
||||
"method": "*", |
||||
"req_signed_in": false, |
||||
"req_grafana_admin": false, |
||||
"req_role": "Admin", |
||||
"url": "http://localhost:5000/static" |
||||
}, |
||||
{ |
||||
"path": "/example/api/*", |
||||
"method": "*", |
||||
"req_signed_in": true, |
||||
"req_grafana_admin": false, |
||||
"req_role": "Admin", |
||||
"url": "http://localhost:5000/api" |
||||
} |
||||
], |
||||
"css": [ |
||||
{ |
||||
"href": "/example/static/css/example.css" |
||||
} |
||||
], |
||||
"js": [ |
||||
{ |
||||
"src": "/example/static/js/app.js" |
||||
} |
||||
], |
||||
"menu_items": [ |
||||
{ |
||||
"text": "Example Plugin", |
||||
"icon": "fa fa-fw fa-smile-o", |
||||
"href": "/example/servers", |
||||
"adminOnly": false, |
||||
} |
||||
] |
||||
} |
||||
} |
||||
Loading…
Reference in new issue