feat(plugin): more work on plugin schema

This commit is contained in:
Torkel Ödegaard 2016-01-09 08:12:27 +01:00
parent 3bb20dbf2e
commit 9943b9a226
5 changed files with 60 additions and 52 deletions

View File

@ -30,9 +30,9 @@ func newMacaron() *macaron.Macaron {
} }
for _, route := range plugins.StaticRoutes { for _, route := range plugins.StaticRoutes {
pluginRoute := path.Join("/public/plugins/", route.UrlFragment) pluginRoute := path.Join("/public/plugins/", route.PluginId)
log.Info("Plugin: Adding static route %s -> %s", pluginRoute, route.Dir) log.Info("Plugin: Adding static route %s -> %s", pluginRoute, route.Directory)
mapStatic(m, route.Dir, "", pluginRoute) mapStatic(m, route.Directory, "", pluginRoute)
} }
mapStatic(m, setting.StaticRootPath, "", "public") mapStatic(m, setting.StaticRootPath, "", "public")

View File

@ -8,6 +8,7 @@ type PluginCommon struct {
Type string `json:"type"` Type string `json:"type"`
Name string `json:"name"` Name string `json:"name"`
Id string `json:"id"` Id string `json:"id"`
StaticRoot string `json:"staticRoot"`
Info PluginInfo `json:"info"` Info PluginInfo `json:"info"`
} }
@ -38,21 +39,19 @@ type DataSourcePlugin struct {
Metrics bool `json:"metrics"` Metrics bool `json:"metrics"`
BuiltIn bool `json:"builtIn"` BuiltIn bool `json:"builtIn"`
App string `json:"app"` App string `json:"app"`
PublicContent *PublicContent `json:"public"` }
type PluginStaticRoute struct {
Directory string
PluginId string
} }
type PanelPlugin struct { type PanelPlugin struct {
PluginCommon PluginCommon
Module string `json:"module"` Module string `json:"module"`
PublicContent *PublicContent `json:"public"`
App string `json:"app"` App string `json:"app"`
} }
type PublicContent struct {
UrlFragment string `json:"urlFragment"`
Dir string `json:"dir"`
}
type ApiPluginRoute struct { type ApiPluginRoute struct {
Path string `json:"path"` Path string `json:"path"`
Method string `json:"method"` Method string `json:"method"`
@ -88,7 +87,6 @@ type AppPlugin struct {
Module string `json:"module"` Module string `json:"module"`
Css *AppPluginCss `json:"css"` Css *AppPluginCss `json:"css"`
Page *AppPluginPage `json:"page"` Page *AppPluginPage `json:"page"`
PublicContent *PublicContent `json:"public"`
} }
type EnabledPlugins struct { type EnabledPlugins struct {

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"io" "io"
"net/url"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -21,7 +22,7 @@ var (
DataSources map[string]*DataSourcePlugin DataSources map[string]*DataSourcePlugin
Panels map[string]*PanelPlugin Panels map[string]*PanelPlugin
ApiPlugins map[string]*ApiPlugin ApiPlugins map[string]*ApiPlugin
StaticRoutes []*PublicContent StaticRoutes []*PluginStaticRoute
Apps map[string]*AppPlugin Apps map[string]*AppPlugin
) )
@ -33,7 +34,7 @@ type PluginScanner struct {
func Init() error { func Init() error {
DataSources = make(map[string]*DataSourcePlugin) DataSources = make(map[string]*DataSourcePlugin)
ApiPlugins = make(map[string]*ApiPlugin) ApiPlugins = make(map[string]*ApiPlugin)
StaticRoutes = make([]*PublicContent, 0) StaticRoutes = make([]*PluginStaticRoute, 0)
Panels = make(map[string]*PanelPlugin) Panels = make(map[string]*PanelPlugin)
Apps = make(map[string]*AppPlugin) Apps = make(map[string]*AppPlugin)
@ -114,11 +115,24 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
return nil return nil
} }
func addPublicContent(public *PublicContent, currentDir string) { func evalRelativePluginUrlPath(pathStr string, pluginId string) string {
if public != nil { u, _ := url.Parse(pathStr)
public.Dir = path.Join(currentDir, public.Dir) if u.IsAbs() {
StaticRoutes = append(StaticRoutes, public) return pathStr
} }
return path.Join("public/plugins", pluginId, pathStr)
}
func addPublicContent(plugin *PluginCommon, currentDir string) {
if plugin.StaticRoot != "" {
StaticRoutes = append(StaticRoutes, &PluginStaticRoute{
Directory: path.Join(currentDir, plugin.StaticRoot),
PluginId: plugin.Id,
})
}
plugin.Info.Logos.Small = evalRelativePluginUrlPath(plugin.Info.Logos.Small, plugin.Id)
plugin.Info.Logos.Large = evalRelativePluginUrlPath(plugin.Info.Logos.Large, plugin.Id)
} }
func interpolatePluginJson(reader io.Reader, pluginCommon *PluginCommon) (io.Reader, error) { func interpolatePluginJson(reader io.Reader, pluginCommon *PluginCommon) (io.Reader, error) {
@ -178,7 +192,7 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
} }
DataSources[p.Id] = &p DataSources[p.Id] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(&p.PluginCommon, currentDir)
case "panel": case "panel":
p := PanelPlugin{} p := PanelPlugin{}
@ -188,7 +202,7 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
} }
Panels[p.Id] = &p Panels[p.Id] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(&p.PluginCommon, currentDir)
case "api": case "api":
p := ApiPlugin{} p := ApiPlugin{}
reader.Seek(0, 0) reader.Seek(0, 0)
@ -203,7 +217,7 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
return err return err
} }
Apps[p.Id] = &p Apps[p.Id] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(&p.PluginCommon, currentDir)
default: default:
return errors.New("Unkown plugin type " + pluginCommon.Type) return errors.New("Unkown plugin type " + pluginCommon.Type)
} }

View File

@ -29,7 +29,7 @@ func TestPluginScans(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(len(Apps), ShouldBeGreaterThan, 0) So(len(Apps), ShouldBeGreaterThan, 0)
So(Apps["app-test"].Info.Logos.Large, ShouldEqual, "public/plugins/app-test/logo_large.png") So(Apps["app-example"].Info.Logos.Large, ShouldEqual, "public/plugins/app-example/img/logo_large.png")
}) })
} }

View File

@ -1,7 +1,19 @@
{ {
"name": "App Example",
"id": "app-test",
"type": "app", "type": "app",
"name": "App Example",
"id": "app-example",
"staticRoot":" ./public",
"module": "app",
"pages": [
{"name": "Example1", "url": "/app-example", "reqRole": "Editor"}
],
"css": {
"light": "css/plugin.dark.css",
"dark": "css/plugin.light.css"
},
"info": { "info": {
"description": "Example Grafana App", "description": "Example Grafana App",
@ -11,8 +23,8 @@
}, },
"keywords": ["example"], "keywords": ["example"],
"logos": { "logos": {
"small": "{{.PluginPublicRoot}}/img/logo_small.png", "small": "img/logo_small.png",
"large": "{{.PluginPublicRoot}}/logo_large.png" "large": "img/logo_large.png"
}, },
"links": [ "links": [
{"name": "Project site", "url": "http://project.com"}, {"name": "Project site", "url": "http://project.com"},
@ -22,22 +34,6 @@
"updated": "2015-02-10" "updated": "2015-02-10"
}, },
"css": {
"light": "plugin.dark.css",
"dark": "plugin.light.css"
},
"module": "app",
"pages": [
{"name": "Example1", "url": "/app-example", "reqRole": "Editor"}
],
"public": {
"urlFragment": "app-example",
"path": "./public"
},
"dependencies": { "dependencies": {
"grafanaVersion": "2.6.x", "grafanaVersion": "2.6.x",
"plugins": [ "plugins": [