Commit 3bb20dbf by Torkel Ödegaard

feat(plugins): changed plugin schema, pluginType -> type, type -> id

parent 7a8b3c41
...@@ -22,7 +22,7 @@ func GetAppPlugins(c *middleware.Context) Response { ...@@ -22,7 +22,7 @@ func GetAppPlugins(c *middleware.Context) Response {
Enabled: app.Enabled, Enabled: app.Enabled,
Pinned: app.Pinned, Pinned: app.Pinned,
Module: app.Module, Module: app.Module,
Info: app.Info, Info: &app.Info,
} }
} }
......
...@@ -119,7 +119,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro ...@@ -119,7 +119,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
panels := map[string]interface{}{} panels := map[string]interface{}{}
for _, panel := range enabledPlugins.Panels { for _, panel := range enabledPlugins.Panels {
panels[panel.Type] = map[string]interface{}{ panels[panel.Id] = map[string]interface{}{
"module": panel.Module, "module": panel.Module,
"name": panel.Name, "name": panel.Name,
} }
......
...@@ -4,6 +4,13 @@ import ( ...@@ -4,6 +4,13 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
) )
type PluginCommon struct {
Type string `json:"type"`
Name string `json:"name"`
Id string `json:"id"`
Info PluginInfo `json:"info"`
}
type PluginInfo struct { type PluginInfo struct {
Author PluginInfoLink `json:"author"` Author PluginInfoLink `json:"author"`
Description string `json:"description"` Description string `json:"description"`
...@@ -22,10 +29,9 @@ type PluginLogos struct { ...@@ -22,10 +29,9 @@ type PluginLogos struct {
} }
type DataSourcePlugin struct { type DataSourcePlugin struct {
Type string `json:"type"` PluginCommon
Name string `json:"name"`
ServiceName string `json:"serviceName"`
Module string `json:"module"` Module string `json:"module"`
ServiceName string `json:"serviceName"`
Partials map[string]interface{} `json:"partials"` Partials map[string]interface{} `json:"partials"`
DefaultMatchFormat string `json:"defaultMatchFormat"` DefaultMatchFormat string `json:"defaultMatchFormat"`
Annotations bool `json:"annotations"` Annotations bool `json:"annotations"`
...@@ -36,8 +42,7 @@ type DataSourcePlugin struct { ...@@ -36,8 +42,7 @@ type DataSourcePlugin struct {
} }
type PanelPlugin struct { type PanelPlugin struct {
Type string `json:"type"` PluginCommon
Name string `json:"name"`
Module string `json:"module"` Module string `json:"module"`
PublicContent *PublicContent `json:"public"` PublicContent *PublicContent `json:"public"`
App string `json:"app"` App string `json:"app"`
...@@ -71,21 +76,19 @@ type AppPluginCss struct { ...@@ -71,21 +76,19 @@ type AppPluginCss struct {
} }
type ApiPlugin struct { type ApiPlugin struct {
Type string `json:"type"` PluginCommon
Routes []*ApiPluginRoute `json:"routes"` Routes []*ApiPluginRoute `json:"routes"`
App string `json:"app"` App string `json:"app"`
} }
type AppPlugin struct { type AppPlugin struct {
Type string `json:"type"` PluginCommon
Name string `json:"name"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Pinned bool `json:"pinned"` Pinned bool `json:"pinned"`
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"` PublicContent *PublicContent `json:"public"`
Info *PluginInfo `json:"info"`
} }
type EnabledPlugins struct { type EnabledPlugins struct {
......
...@@ -121,7 +121,7 @@ func addPublicContent(public *PublicContent, currentDir string) { ...@@ -121,7 +121,7 @@ func addPublicContent(public *PublicContent, currentDir string) {
} }
} }
func interpolatePluginJson(reader io.Reader) (io.Reader, error) { func interpolatePluginJson(reader io.Reader, pluginCommon *PluginCommon) (io.Reader, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.ReadFrom(reader) buf.ReadFrom(reader)
jsonStr := buf.String() // jsonStr := buf.String() //
...@@ -132,7 +132,7 @@ func interpolatePluginJson(reader io.Reader) (io.Reader, error) { ...@@ -132,7 +132,7 @@ func interpolatePluginJson(reader io.Reader) (io.Reader, error) {
} }
data := map[string]interface{}{ data := map[string]interface{}{
"PluginPublicRoot": "HAHAHA", "PluginPublicRoot": "public/plugins/" + pluginCommon.Id,
} }
var resultBuffer bytes.Buffer var resultBuffer bytes.Buffer
...@@ -153,76 +153,59 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error { ...@@ -153,76 +153,59 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
defer reader.Close() defer reader.Close()
jsonParser := json.NewDecoder(reader) jsonParser := json.NewDecoder(reader)
pluginJson := make(map[string]interface{}) pluginCommon := PluginCommon{}
if err := jsonParser.Decode(&pluginJson); err != nil { if err := jsonParser.Decode(&pluginCommon); err != nil {
return err return err
} }
pluginType, exists := pluginJson["pluginType"] if pluginCommon.Id == "" || pluginCommon.Type == "" {
if !exists { return errors.New("Did not find type and id property in plugin.json")
return errors.New("Did not find pluginType property in plugin.json")
} }
reader.Seek(0, 0) reader.Seek(0, 0)
if newReader, err := interpolatePluginJson(reader); err != nil { if newReader, err := interpolatePluginJson(reader, &pluginCommon); err != nil {
return err return err
} else { } else {
jsonParser = json.NewDecoder(newReader) jsonParser = json.NewDecoder(newReader)
} }
if pluginType == "datasource" { switch pluginCommon.Type {
case "datasource":
p := DataSourcePlugin{} p := DataSourcePlugin{}
if err := jsonParser.Decode(&p); err != nil { if err := jsonParser.Decode(&p); err != nil {
return err return err
} }
if p.Type == "" { DataSources[p.Id] = &p
return errors.New("Did not find type property in plugin.json")
}
DataSources[p.Type] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(p.PublicContent, currentDir)
}
if pluginType == "panel" { case "panel":
p := PanelPlugin{} p := PanelPlugin{}
reader.Seek(0, 0) reader.Seek(0, 0)
if err := jsonParser.Decode(&p); err != nil { if err := jsonParser.Decode(&p); err != nil {
return err return err
} }
if p.Type == "" { Panels[p.Id] = &p
return errors.New("Did not find type property in plugin.json")
}
Panels[p.Type] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(p.PublicContent, currentDir)
} case "api":
if pluginType == "api" {
p := ApiPlugin{} p := ApiPlugin{}
reader.Seek(0, 0) reader.Seek(0, 0)
if err := jsonParser.Decode(&p); err != nil { if err := jsonParser.Decode(&p); err != nil {
return err return err
} }
if p.Type == "" { ApiPlugins[p.Id] = &p
return errors.New("Did not find type property in plugin.json") case "app":
}
ApiPlugins[p.Type] = &p
}
if pluginType == "app" {
p := AppPlugin{} p := AppPlugin{}
reader.Seek(0, 0) reader.Seek(0, 0)
if err := jsonParser.Decode(&p); err != nil { if err := jsonParser.Decode(&p); err != nil {
return err return err
} }
if p.Type == "" { Apps[p.Id] = &p
return errors.New("Did not find type property in plugin.json")
}
Apps[p.Type] = &p
addPublicContent(p.PublicContent, currentDir) addPublicContent(p.PublicContent, currentDir)
default:
return errors.New("Unkown plugin type " + pluginCommon.Type)
} }
return nil return nil
......
...@@ -29,7 +29,7 @@ func TestPluginScans(t *testing.T) { ...@@ -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, "plugins/app-exampl/img/logo_large.png") So(Apps["app-test"].Info.Logos.Large, ShouldEqual, "public/plugins/app-test/logo_large.png")
}) })
} }
{ {
"pluginType": "datasource", "type": "datasource",
"name": "CloudWatch", "name": "CloudWatch",
"id": "cloudwatch",
"type": "cloudwatch",
"serviceName": "CloudWatchDatasource", "serviceName": "CloudWatchDatasource",
"module": "app/plugins/datasource/cloudwatch/datasource", "module": "app/plugins/datasource/cloudwatch/datasource",
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "Elasticsearch", "name": "Elasticsearch",
"id": "elasticsearch",
"type": "elasticsearch",
"serviceName": "ElasticDatasource", "serviceName": "ElasticDatasource",
"module": "app/plugins/datasource/elasticsearch/datasource", "module": "app/plugins/datasource/elasticsearch/datasource",
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "Grafana", "name": "Grafana",
"id": "grafana",
"builtIn": true, "builtIn": true,
"type": "grafana",
"serviceName": "GrafanaDatasource", "serviceName": "GrafanaDatasource",
"module": "app/plugins/datasource/grafana/datasource", "module": "app/plugins/datasource/grafana/datasource",
......
{ {
"pluginType": "datasource",
"name": "Graphite", "name": "Graphite",
"type": "graphite", "type": "datasource",
"id": "graphite",
"serviceName": "GraphiteDatasource", "serviceName": "GraphiteDatasource",
"module": "app/plugins/datasource/graphite/datasource", "module": "app/plugins/datasource/graphite/datasource",
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "InfluxDB 0.9.x", "name": "InfluxDB 0.9.x",
"id": "influxdb",
"type": "influxdb",
"serviceName": "InfluxDatasource", "serviceName": "InfluxDatasource",
"module": "app/plugins/datasource/influxdb/datasource", "module": "app/plugins/datasource/influxdb/datasource",
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "Mixed datasource", "name": "Mixed datasource",
"id": "mixed",
"builtIn": true, "builtIn": true,
"mixed": true, "mixed": true,
"type": "mixed",
"serviceName": "MixedDatasource", "serviceName": "MixedDatasource",
"module": "app/plugins/datasource/mixed/datasource", "module": "app/plugins/datasource/mixed/datasource",
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "OpenTSDB", "name": "OpenTSDB",
"id": "opentsdb",
"type": "opentsdb",
"serviceName": "OpenTSDBDatasource", "serviceName": "OpenTSDBDatasource",
"module": "app/plugins/datasource/opentsdb/datasource", "module": "app/plugins/datasource/opentsdb/datasource",
"partials": { "partials": {
......
{ {
"pluginType": "datasource", "type": "datasource",
"name": "Prometheus", "name": "Prometheus",
"id": "prometheus",
"type": "prometheus",
"serviceName": "PrometheusDatasource", "serviceName": "PrometheusDatasource",
"module": "app/plugins/datasource/prometheus/datasource", "module": "app/plugins/datasource/prometheus/datasource",
......
define([
'angular',
],
function (angular) {
'use strict';
var module = angular.module('grafana.services');
module.factory('SqlDatasource', function() {
function SqlDatasource() {
}
return SqlDatasource;
});
});
<h2>SQL Options</h2>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 80px">
DB Type
</li>
<li>
<select class="input-medium tight-form-input" ng-model="current.jsonData.dbType" ng-options="f for f in ['sqlite3','mysql','postgres']"></select>
</li>
<li class="tight-form-item" style="width: 80px">
Host
</li>
<li>
<input type="text" class="tight-form-input input-medium" ng-model='current.jsonData.host' placeholder="localhost:3306">
</li>
<li class="tight-form-item" ng-if="current.jsonData.dbType === 'postgres'">
SSL&nbsp;
<input class="cr1" id="jsonData.ssl" type="checkbox" ng-model="current.jsonData.ssl" ng-checked="current.jsonData.ssl">
<label for="jsonData.ssl" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 80px">
Database
</li>
<li>
<input type="text" class="tight-form-input input-medium" ng-model='current.database' placeholder="">
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 80px">
User
</li>
<li>
<input type="text" class="tight-form-input input-medium" ng-model='current.user' placeholder="">
</li>
<li class="tight-form-item" style="width: 80px">
Password
</li>
<li>
<input type="password" class="tight-form-input input-medium" ng-model='current.password' placeholder="">
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="fluid-row" style="margin-top: 20px">
<div class="span2"></div>
<div class="grafana-info-box span8">
<h5>Test graph</h5>
<p>
This is just a test data source that generates random walk series. If this is your only data source
open the left side menu and navigate to the data sources admin screen and add your data sources. You can change
data source using the button to the left of the <strong>Add query</strong> button.
</p>
</div>
<div class="span2"></div>
<div class="clearfix"></div>
</div>
{
"pluginType": "datasource",
"name": "Generic SQL (prototype)",
"type": "generic_sql",
"serviceName": "SqlDatasource",
"module": "app/plugins/datasource/sql/datasource",
"partials": {
"config": "app/plugins/datasource/sql/partials/config.html",
"query": "app/plugins/datasource/sql/partials/query.editor.html"
},
"metrics": true
}
{ {
"pluginType": "panel", "type": "panel",
"name": "Dashboard list", "name": "Dashboard list",
"type": "dashlist", "id": "dashlist",
"module": "app/plugins/panels/dashlist/module" "module": "app/plugins/panels/dashlist/module"
} }
{ {
"pluginType": "panel", "type": "panel",
"name": "Graph", "name": "Graph",
"type": "graph", "id": "graph",
"module": "app/plugins/panels/graph/module" "module": "app/plugins/panels/graph/module"
} }
{ {
"pluginType": "panel", "type": "panel",
"name": "Singlestat", "name": "Singlestat",
"type": "singlestat", "id": "singlestat",
"module": "app/plugins/panels/singlestat/module" "module": "app/plugins/panels/singlestat/module"
} }
{ {
"pluginType": "panel", "type": "panel",
"name": "Table", "name": "Table",
"type": "table", "id": "table",
"module": "app/plugins/panels/table/module" "module": "app/plugins/panels/table/module"
} }
{ {
"pluginType": "panel", "type": "panel",
"name": "Text", "name": "Text",
"type": "text", "id": "text",
"module": "app/plugins/panels/text/module" "module": "app/plugins/panels/text/module"
} }
{ {
"pluginType": "app",
"name": "App Example", "name": "App Example",
"type": "app-test", "id": "app-test",
"type": "app",
"plugins": [],
"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"
},
"info": { "info": {
"description": "Example Grafana App", "description": "Example Grafana App",
...@@ -40,6 +22,22 @@ ...@@ -40,6 +22,22 @@
"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": [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment