aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Kulikov <k.kulikov2@gmail.com>2020-10-28 20:04:37 +0300
committerKonstantin Kulikov <k.kulikov2@gmail.com>2020-10-28 20:04:37 +0300
commita374e7f15f51073c15728661ac8c363da5ec2a0f (patch)
treebb310f8070b1fc22e606fe00fc5634a4404c19b4
parentb85efc501595136485aea134946fa459bff115b0 (diff)
testing/grafana: upgrade to 7.3.0
-rw-r--r--testing/grafana/APKBUILD12
-rw-r--r--testing/grafana/fix-plugin-load.patch715
2 files changed, 5 insertions, 722 deletions
diff --git a/testing/grafana/APKBUILD b/testing/grafana/APKBUILD
index 73dd033a3d2..3756ba88d47 100644
--- a/testing/grafana/APKBUILD
+++ b/testing/grafana/APKBUILD
@@ -1,10 +1,10 @@
# Contributor: Konstantin Kulikov <k.kulikov2@gmail.com>
# Maintainer: Konstantin Kulikov <k.kulikov2@gmail.com>
pkgname=grafana
-pkgver=7.2.2
+pkgver=7.3.0
pkgrel=0
-_commit=ad9d408ac2 # git rev-parse --short HEAD
-_stamp=1603265219 # git --no-pager show -s --format=%ct
+_commit=bf8837f6f8 # git rev-parse --short HEAD
+_stamp=1603886623 # git --no-pager show -s --format=%ct
pkgdesc="Open source, feature rich metrics dashboard and graph editor"
url="https://grafana.com"
arch="all !mips !mips64" # go is missing
@@ -15,7 +15,6 @@ subpackages="$pkgname-openrc"
options="net chmod-clean"
source="$pkgname-$pkgver.tar.gz::https://github.com/grafana/grafana/archive/v$pkgver.tar.gz
$pkgname-$pkgver-bin.tar.gz::https://dl.grafana.com/oss/release/grafana-$pkgver.linux-amd64.tar.gz
- fix-plugin-load.patch
$pkgname.initd
$pkgname.confd"
@@ -57,8 +56,7 @@ package() {
cp -r "$builddir/conf" "$builddir/public" "$pkgdir/usr/share/$pkgname/"
}
-sha512sums="8845ab929d2c956c757f9ce4babb1d0e42667300cc42c9ad3da4e3b42ba13fd088442b5dda225a068249ccdb4c1009f6820cdb779073fb1802ba4145204b53e6 grafana-7.2.2.tar.gz
-be26cb16e2d39eb235384a30776b0961cf5acf643e8b8fa9a3fb1dba671668a687b61e463ed6c77210ac3c630755f57a5d8413e37bc931d113a856d8bb9083b5 grafana-7.2.2-bin.tar.gz
-a936680280c8d3dbbdda4339de50d5db9e73613ed9a275ebb4d10423499272d163aa96d073031fb990372ba93ed24e2d3e48f7616479102110207d19ca8c0f78 fix-plugin-load.patch
+sha512sums="6239bc24fadc5429a0df0aeda859d7454dc9732484b42732617ed12b46397afe408f8877d17b5b582fb3f671d2f6c7c95dad8d5d898e1c84253d7fe10f371b32 grafana-7.3.0.tar.gz
+1546bdc2cdffd5726d4c201629c8508283d70846c2cd8d6a5d7d90e4c0f9d950c1de24f9c8a72adb6e022317f2f7c034852edfa64fd10070c22fbf1563012277 grafana-7.3.0-bin.tar.gz
b0a781e1b1e33741a97e231c761b1200239c6f1235ffbe82311fe883387eb23bef262ad68256ebd6cf87d74298041b53b947ea7a493cfa5aa814b2a1c5181e13 grafana.initd
c2d9896ae9a9425f759a47aeab42b7c43b63328e82670d50185de8c08cda7b8df264c8b105c5c3138b90dd46e86598b16826457eb3b2979a899b3a508cbe4e8c grafana.confd"
diff --git a/testing/grafana/fix-plugin-load.patch b/testing/grafana/fix-plugin-load.patch
deleted file mode 100644
index f2393e41dd1..00000000000
--- a/testing/grafana/fix-plugin-load.patch
+++ /dev/null
@@ -1,715 +0,0 @@
-From 0a25c24b4f02a1293a5bf8c095c46e7a12e1e660 Mon Sep 17 00:00:00 2001
-From: Arve Knudsen <arve.knudsen@gmail.com>
-Date: Thu, 1 Oct 2020 16:23:33 +0200
-Subject: [PATCH 1/4] plugins: Let descendant plugins inherit their root's
- signature
-
-Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
----
- pkg/plugins/manifest.go | 2 +-
- pkg/plugins/models.go | 2 ++
- pkg/plugins/plugins.go | 64 ++++++++++++++++++++++++++++++++++-------
- 3 files changed, 57 insertions(+), 11 deletions(-)
-
-diff --git a/pkg/plugins/manifest.go b/pkg/plugins/manifest.go
-index ed137ddcce51..3e836fdfe07d 100644
---- a/pkg/plugins/manifest.go
-+++ b/pkg/plugins/manifest.go
-@@ -84,7 +84,7 @@ func readPluginManifest(body []byte) (*pluginManifest, error) {
-
- // getPluginSignatureState returns the signature state for a plugin.
- func getPluginSignatureState(log log.Logger, plugin *PluginBase) PluginSignature {
-- log.Debug("Getting signature state of plugin", "plugin", plugin.Id)
-+ log.Debug("Getting signature state of plugin", "plugin", plugin.Id, "hasRoot", plugin.Root != nil)
- manifestPath := filepath.Join(plugin.PluginDir, "MANIFEST.txt")
-
- byteValue, err := ioutil.ReadFile(manifestPath)
-diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go
-index d1d47bb8a324..f6346c97ef30 100644
---- a/pkg/plugins/models.go
-+++ b/pkg/plugins/models.go
-@@ -69,6 +69,8 @@ type PluginBase struct {
-
- GrafanaNetVersion string `json:"-"`
- GrafanaNetHasUpdate bool `json:"-"`
-+
-+ Root *PluginBase
- }
-
- func (pb *PluginBase) registerPlugin(pluginDir string) error {
-diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
-index 152ff5955bf7..20376362aa59 100644
---- a/pkg/plugins/plugins.go
-+++ b/pkg/plugins/plugins.go
-@@ -10,6 +10,7 @@ import (
- "path"
- "path/filepath"
- "reflect"
-+ "runtime"
- "strings"
- "time"
-
-@@ -45,6 +46,7 @@ type PluginScanner struct {
- cfg *setting.Cfg
- requireSigned bool
- log log.Logger
-+ plugins map[string]*PluginBase
- }
-
- type PluginManager struct {
-@@ -114,8 +116,7 @@ func (pm *PluginManager) Init() error {
- }
- }
-
-- // check plugin paths defined in config
-- if err := pm.checkPluginPaths(); err != nil {
-+ if err := pm.scanPluginPaths(); err != nil {
- return err
- }
-
-@@ -144,6 +145,19 @@ func (pm *PluginManager) Init() error {
- }
- }
-
-+ // 2nd pass to fix up any descendant plugins' signatures, to correspond to their respective root plugins
-+ for _, p := range Plugins {
-+ if p.IsCorePlugin || p.Root == nil || p.Signature == PluginSignatureInternal ||
-+ p.Signature == PluginSignatureValid {
-+ pm.log.Debug("Not setting descendant plugin's signature to that of root", "plugin", p.Id,
-+ "signature", p.Signature, "isCore", p.IsCorePlugin, "hasRoot", p.Root != nil)
-+ continue
-+ }
-+
-+ pm.log.Debug("Setting descendant plugin's signature to that of root", "plugin", p.Id, "root", p.Root.Id)
-+ p.Signature = p.Root.Signature
-+ }
-+
- return nil
- }
-
-@@ -166,7 +180,8 @@ func (pm *PluginManager) Run(ctx context.Context) error {
- return ctx.Err()
- }
-
--func (pm *PluginManager) checkPluginPaths() error {
-+// scanPluginPaths scans configured plugin paths.
-+func (pm *PluginManager) scanPluginPaths() error {
- for pluginID, settings := range pm.Cfg.PluginSettings {
- path, exists := settings["path"]
- if !exists || path == "" {
-@@ -189,8 +204,10 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
- cfg: pm.Cfg,
- requireSigned: requireSigned,
- log: pm.log,
-+ plugins: map[string]*PluginBase{},
- }
-
-+ // 1st pass: Scan plugins, also mapping plugins to their respective directories
- if err := util.Walk(pluginDir, true, true, scanner.walker); err != nil {
- if errors.Is(err, os.ErrNotExist) {
- pm.log.Debug("Couldn't scan directory since it doesn't exist", "pluginDir", pluginDir)
-@@ -211,6 +228,25 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
- pm.scanningErrors = scanner.errors
- }
-
-+ // 2nd pass: Detect any root plugins
-+ for dpath, plugin := range scanner.plugins {
-+ ancestors := strings.Split(dpath, string(filepath.Separator))
-+ ancestors = ancestors[0 : len(ancestors)-1]
-+
-+ // Try to find any root plugin
-+ aPath := ""
-+ if runtime.GOOS != "windows" && filepath.IsAbs(dpath) {
-+ aPath = "/"
-+ }
-+ for _, a := range ancestors {
-+ aPath = filepath.Join(aPath, a)
-+ if root, ok := scanner.plugins[aPath]; ok {
-+ plugin.Root = root
-+ break
-+ }
-+ }
-+ }
-+
- return nil
- }
-
-@@ -239,13 +275,15 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
- return nil
- }
-
-- if f.Name() == "plugin.json" {
-- err := scanner.loadPlugin(currentPath)
-- if err != nil {
-- scanner.log.Error("Failed to load plugin", "error", err, "pluginPath", filepath.Dir(currentPath))
-- scanner.errors = append(scanner.errors, err)
-- }
-+ if f.Name() != "plugin.json" {
-+ return nil
-+ }
-+
-+ if err := scanner.loadPlugin(currentPath); err != nil {
-+ scanner.log.Error("Failed to load plugin", "error", err, "pluginPath", filepath.Dir(currentPath))
-+ scanner.errors = append(scanner.errors, err)
- }
-+
- return nil
- }
-
-@@ -336,7 +374,13 @@ func (scanner *PluginScanner) loadPlugin(pluginJsonFilePath string) error {
- return err
- }
-
-- return loader.Load(jsonParser, currentDir, scanner.backendPluginManager)
-+ if err := loader.Load(jsonParser, currentDir, scanner.backendPluginManager); err != nil {
-+ return err
-+ }
-+
-+ // TODO: We should avoid loading the plugin a second time, and instead re-use pluginCommon
-+ scanner.plugins[currentDir] = Plugins[pluginCommon.Id]
-+ return nil
- }
-
- func (scanner *PluginScanner) IsBackendOnlyPlugin(pluginType string) bool {
-
-From f93bceb683974c5363d4ddea4d980ce27a491ace Mon Sep 17 00:00:00 2001
-From: Arve Knudsen <arve.knudsen@gmail.com>
-Date: Fri, 2 Oct 2020 14:01:14 +0200
-Subject: [PATCH 2/4] plugins: Fix handling of descendant plugins
-
-Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
----
- pkg/plugins/manifest.go | 5 +-
- pkg/plugins/plugins.go | 206 ++++++++++++++++++++++++----------------
- 2 files changed, 128 insertions(+), 83 deletions(-)
-
-diff --git a/pkg/plugins/manifest.go b/pkg/plugins/manifest.go
-index 3e836fdfe07d..9b6e2cb00c44 100644
---- a/pkg/plugins/manifest.go
-+++ b/pkg/plugins/manifest.go
-@@ -84,16 +84,18 @@ func readPluginManifest(body []byte) (*pluginManifest, error) {
-
- // getPluginSignatureState returns the signature state for a plugin.
- func getPluginSignatureState(log log.Logger, plugin *PluginBase) PluginSignature {
-- log.Debug("Getting signature state of plugin", "plugin", plugin.Id, "hasRoot", plugin.Root != nil)
-+ log.Debug("Getting signature state of plugin", "plugin", plugin.Id, "isBackend", plugin.Backend)
- manifestPath := filepath.Join(plugin.PluginDir, "MANIFEST.txt")
-
- byteValue, err := ioutil.ReadFile(manifestPath)
- if err != nil || len(byteValue) < 10 {
-+ log.Debug("Plugin is unsigned", "id", plugin.Id)
- return PluginSignatureUnsigned
- }
-
- manifest, err := readPluginManifest(byteValue)
- if err != nil {
-+ log.Debug("Plugin signature invalid", "id", plugin.Id)
- return PluginSignatureInvalid
- }
-
-@@ -126,5 +128,6 @@ func getPluginSignatureState(log log.Logger, plugin *PluginBase) PluginSignature
- }
-
- // Everything OK
-+ log.Debug("Plugin signature valid", "id", plugin.Id)
- return PluginSignatureValid
- }
-diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
-index 20376362aa59..1217a642178f 100644
---- a/pkg/plugins/plugins.go
-+++ b/pkg/plugins/plugins.go
-@@ -139,25 +139,12 @@ func (pm *PluginManager) Init() error {
- for _, p := range Plugins {
- if p.IsCorePlugin {
- p.Signature = PluginSignatureInternal
-- } else {
-+ } else if p.Signature == "" {
- p.Signature = getPluginSignatureState(pm.log, p)
- metrics.SetPluginBuildInformation(p.Id, p.Type, p.Info.Version)
- }
- }
-
-- // 2nd pass to fix up any descendant plugins' signatures, to correspond to their respective root plugins
-- for _, p := range Plugins {
-- if p.IsCorePlugin || p.Root == nil || p.Signature == PluginSignatureInternal ||
-- p.Signature == PluginSignatureValid {
-- pm.log.Debug("Not setting descendant plugin's signature to that of root", "plugin", p.Id,
-- "signature", p.Signature, "isCore", p.IsCorePlugin, "hasRoot", p.Root != nil)
-- continue
-- }
--
-- pm.log.Debug("Setting descendant plugin's signature to that of root", "plugin", p.Id, "root", p.Root.Id)
-- p.Signature = p.Root.Signature
-- }
--
- return nil
- }
-
-@@ -223,12 +210,10 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
- return err
- }
-
-- if len(scanner.errors) > 0 {
-- pm.log.Warn("Some plugins failed to load", "errors", scanner.errors)
-- pm.scanningErrors = scanner.errors
-- }
-+ pm.log.Debug("Initial plugin loading done")
-
-- // 2nd pass: Detect any root plugins
-+ // 2nd pass: Detect root plugins and verify signatures
-+ // Any plugin that descends from a root plugin may inherit the root's signature
- for dpath, plugin := range scanner.plugins {
- ancestors := strings.Split(dpath, string(filepath.Separator))
- ancestors = ancestors[0 : len(ancestors)-1]
-@@ -245,6 +230,59 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
- break
- }
- }
-+
-+ pm.log.Debug("Found plugin", "id", plugin.Id, "signature", plugin.Signature, "hasRoot", plugin.Root != nil)
-+ if !scanner.validateSignature(plugin) {
-+ pm.log.Debug("Not adding plugin since it lacks a valid signature", "id", plugin.Id,
-+ "signature", plugin.Signature)
-+ continue
-+ }
-+
-+ pm.log.Debug("Attempting to add plugin", "id", plugin.Id)
-+
-+ pluginGoType, exists := PluginTypes[plugin.Type]
-+ if !exists {
-+ return fmt.Errorf("unknown plugin type %q", plugin.Type)
-+ }
-+
-+ loader := reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
-+
-+ jsonFPath := filepath.Join(plugin.PluginDir, "plugin.json")
-+
-+ // External plugins need a module.js file for SystemJS to load
-+ if !strings.HasPrefix(jsonFPath, setting.StaticRootPath) && !scanner.IsBackendOnlyPlugin(plugin.Type) {
-+ module := filepath.Join(plugin.PluginDir, "module.js")
-+ exists, err := fs.Exists(module)
-+ if err != nil {
-+ return err
-+ }
-+ if !exists {
-+ scanner.log.Warn("Plugin missing module.js",
-+ "name", plugin.Name,
-+ "warning", "Missing module.js, If you loaded this plugin from git, make sure to compile it.",
-+ "path", module)
-+ }
-+ }
-+
-+ reader, err := os.Open(jsonFPath)
-+ if err != nil {
-+ return err
-+ }
-+ defer reader.Close()
-+
-+ jsonParser := json.NewDecoder(reader)
-+
-+ // TODO: We should avoid loading the plugin a second time, and instead re-use pluginCommon
-+ if err := loader.Load(jsonParser, plugin.PluginDir, scanner.backendPluginManager); err != nil {
-+ return err
-+ }
-+
-+ pm.log.Debug("Successfully added plugin", "id", plugin.Id)
-+ }
-+
-+ if len(scanner.errors) > 0 {
-+ pm.log.Warn("Some plugins failed to load", "errors", scanner.errors)
-+ pm.scanningErrors = scanner.errors
- }
-
- return nil
-@@ -287,13 +325,13 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
- return nil
- }
-
--func (scanner *PluginScanner) loadPlugin(pluginJsonFilePath string) error {
-- currentDir := filepath.Dir(pluginJsonFilePath)
-- reader, err := os.Open(pluginJsonFilePath)
-+func (s *PluginScanner) loadPlugin(pluginJSONFilePath string) error {
-+ s.log.Debug("Loading plugin", "path", pluginJSONFilePath)
-+ currentDir := filepath.Dir(pluginJSONFilePath)
-+ reader, err := os.Open(pluginJSONFilePath)
- if err != nil {
- return err
- }
--
- defer reader.Close()
-
- jsonParser := json.NewDecoder(reader)
-@@ -308,83 +346,87 @@ func (scanner *PluginScanner) loadPlugin(pluginJsonFilePath string) error {
-
- // The expressions feature toggle corresponds to transform plug-ins.
- if pluginCommon.Type == "transform" {
-- isEnabled := scanner.cfg.IsExpressionsEnabled()
-+ isEnabled := s.cfg.IsExpressionsEnabled()
- if !isEnabled {
-- scanner.log.Debug("Transform plugin is disabled since the expressions feature toggle is not enabled",
-+ s.log.Debug("Transform plugin is disabled since the expressions feature toggle is not enabled",
- "pluginID", pluginCommon.Id)
- return nil
- }
- }
-
-- pluginCommon.PluginDir = filepath.Dir(pluginJsonFilePath)
-+ pluginCommon.PluginDir = filepath.Dir(pluginJSONFilePath)
-+ pluginCommon.Signature = getPluginSignatureState(s.log, &pluginCommon)
-+
-+ s.plugins[currentDir] = &pluginCommon
-+
-+ return nil
-+}
-+
-+func (scanner *PluginScanner) IsBackendOnlyPlugin(pluginType string) bool {
-+ return pluginType == "renderer" || pluginType == "transform"
-+}
-
-+// validateSignature validates a plugin's signature.
-+func (s *PluginScanner) validateSignature(plugin *PluginBase) bool {
- // For the time being, we choose to only require back-end plugins to be signed
- // NOTE: the state is calculated again when setting metadata on the object
-- if pluginCommon.Backend && scanner.requireSigned {
-- sig := getPluginSignatureState(scanner.log, &pluginCommon)
-- if sig != PluginSignatureValid {
-- scanner.log.Debug("Invalid Plugin Signature", "pluginID", pluginCommon.Id, "pluginDir", pluginCommon.PluginDir, "state", sig)
-- if sig == PluginSignatureUnsigned {
-- allowUnsigned := false
-- for _, plug := range scanner.cfg.PluginsAllowUnsigned {
-- if plug == pluginCommon.Id {
-- allowUnsigned = true
-- break
-- }
-- }
-- if setting.Env != setting.DEV && !allowUnsigned {
-- return fmt.Errorf("plugin %q is unsigned", pluginCommon.Id)
-- }
-- scanner.log.Warn("Running an unsigned backend plugin", "pluginID", pluginCommon.Id, "pluginDir", pluginCommon.PluginDir)
-- } else {
-- switch sig {
-- case PluginSignatureInvalid:
-- return fmt.Errorf("plugin %q has an invalid signature", pluginCommon.Id)
-- case PluginSignatureModified:
-- return fmt.Errorf("plugin %q's signature has been modified", pluginCommon.Id)
-- default:
-- return fmt.Errorf("unrecognized plugin signature state %v", sig)
-- }
-- }
-- }
-+ if !plugin.Backend || !s.requireSigned {
-+ return true
- }
-
-- pluginGoType, exists := PluginTypes[pluginCommon.Type]
-- if !exists {
-- return fmt.Errorf("unknown plugin type %q", pluginCommon.Type)
-+ if plugin.Signature == PluginSignatureValid {
-+ s.log.Debug("Plugin has valid signature", "id", plugin.Id)
-+ return true
- }
-- loader := reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
-
-- // External plugins need a module.js file for SystemJS to load
-- if !strings.HasPrefix(pluginJsonFilePath, setting.StaticRootPath) && !scanner.IsBackendOnlyPlugin(pluginCommon.Type) {
-- module := filepath.Join(filepath.Dir(pluginJsonFilePath), "module.js")
-- exists, err := fs.Exists(module)
-- if err != nil {
-- return err
-- }
-- if !exists {
-- scanner.log.Warn("Plugin missing module.js",
-- "name", pluginCommon.Name,
-- "warning", "Missing module.js, If you loaded this plugin from git, make sure to compile it.",
-- "path", module)
-+ if plugin.Root != nil {
-+ // If a descendant plugin with invalid signature, set signature to that of root
-+ if plugin.IsCorePlugin || plugin.Signature == PluginSignatureInternal {
-+ s.log.Debug("Not setting descendant plugin's signature to that of root since it's core or internal",
-+ "plugin", plugin.Id, "signature", plugin.Signature, "isCore", plugin.IsCorePlugin)
-+ } else {
-+ s.log.Debug("Setting descendant plugin's signature to that of root", "plugin", plugin.Id,
-+ "root", plugin.Root.Id, "signature", plugin.Signature, "rootSignature", plugin.Root.Signature)
-+ plugin.Signature = plugin.Root.Signature
-+ if plugin.Signature == PluginSignatureValid {
-+ s.log.Debug("Plugin has valid signature (inherited from root)", "id", plugin.Id)
-+ return true
-+ }
- }
-+ } else {
-+ s.log.Debug("Non-valid plugin Signature", "pluginID", plugin.Id, "pluginDir", plugin.PluginDir,
-+ "state", plugin.Signature)
- }
-
-- if _, err := reader.Seek(0, 0); err != nil {
-- return err
-- }
-+ switch plugin.Signature {
-+ case PluginSignatureUnsigned:
-+ allowUnsigned := false
-+ for _, plug := range s.cfg.PluginsAllowUnsigned {
-+ if plug == plugin.Id {
-+ allowUnsigned = true
-+ break
-+ }
-+ }
-+ if setting.Env != setting.DEV && !allowUnsigned {
-+ s.log.Debug("Plugin is unsigned", "id", plugin.Id)
-+ s.errors = append(s.errors, fmt.Errorf("plugin %q is unsigned", plugin.Id))
-+ return false
-+ }
-
-- if err := loader.Load(jsonParser, currentDir, scanner.backendPluginManager); err != nil {
-- return err
-+ s.log.Warn("Running an unsigned backend plugin", "pluginID", plugin.Id, "pluginDir",
-+ plugin.PluginDir)
-+ return true
-+ case PluginSignatureInvalid:
-+ s.log.Debug("Plugin %q has an invalid signature", plugin.Id)
-+ s.errors = append(s.errors, fmt.Errorf("plugin %q has an invalid signature", plugin.Id))
-+ return false
-+ case PluginSignatureModified:
-+ s.log.Debug("Plugin %q has a modified signature", plugin.Id)
-+ s.errors = append(s.errors, fmt.Errorf("plugin %q's signature has been modified", plugin.Id))
-+ return false
-+ default:
-+ panic(fmt.Sprintf("Plugin %q has unrecognized plugin signature state %q", plugin.Id, plugin.Signature))
- }
--
-- // TODO: We should avoid loading the plugin a second time, and instead re-use pluginCommon
-- scanner.plugins[currentDir] = Plugins[pluginCommon.Id]
-- return nil
--}
--
--func (scanner *PluginScanner) IsBackendOnlyPlugin(pluginType string) bool {
-- return pluginType == "renderer" || pluginType == "transform"
- }
-
- func GetPluginMarkdown(pluginId string, name string) ([]byte, error) {
-
-From c4a35b8bbbbb415fe1a9a002da5708c2bca64088 Mon Sep 17 00:00:00 2001
-From: Arve Knudsen <arve.knudsen@gmail.com>
-Date: Fri, 2 Oct 2020 14:47:08 +0200
-Subject: [PATCH 3/4] plugins: Keep signature
-
-Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
----
- pkg/plugins/app_plugin.go | 4 ++--
- pkg/plugins/datasource_plugin.go | 4 ++--
- pkg/plugins/models.go | 11 +++++++----
- pkg/plugins/panel_plugin.go | 4 ++--
- pkg/plugins/plugins.go | 7 +++----
- pkg/plugins/renderer_plugin.go | 4 ++--
- pkg/plugins/transform_plugin.go | 4 ++--
- 7 files changed, 20 insertions(+), 18 deletions(-)
-
-diff --git a/pkg/plugins/app_plugin.go b/pkg/plugins/app_plugin.go
-index 66265fc3abc9..a6cbc3e279e0 100644
---- a/pkg/plugins/app_plugin.go
-+++ b/pkg/plugins/app_plugin.go
-@@ -58,12 +58,12 @@ type JwtTokenAuth struct {
- Params map[string]string `json:"params"`
- }
-
--func (app *AppPlugin) Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error {
-+func (app *AppPlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error {
- if err := decoder.Decode(app); err != nil {
- return err
- }
-
-- if err := app.registerPlugin(pluginDir); err != nil {
-+ if err := app.registerPlugin(base); err != nil {
- return err
- }
-
-diff --git a/pkg/plugins/datasource_plugin.go b/pkg/plugins/datasource_plugin.go
-index 39a30c9cbf68..fbacf92f9f2d 100644
---- a/pkg/plugins/datasource_plugin.go
-+++ b/pkg/plugins/datasource_plugin.go
-@@ -34,12 +34,12 @@ type DataSourcePlugin struct {
- SDK bool `json:"sdk,omitempty"`
- }
-
--func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error {
-+func (p *DataSourcePlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error {
- if err := decoder.Decode(p); err != nil {
- return errutil.Wrapf(err, "Failed to decode datasource plugin")
- }
-
-- if err := p.registerPlugin(pluginDir); err != nil {
-+ if err := p.registerPlugin(base); err != nil {
- return errutil.Wrapf(err, "Failed to register plugin")
- }
-
-diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go
-index f6346c97ef30..84b674720d39 100644
---- a/pkg/plugins/models.go
-+++ b/pkg/plugins/models.go
-@@ -43,7 +43,7 @@ func (e PluginNotFoundError) Error() string {
- }
-
- type PluginLoader interface {
-- Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error
-+ Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error
- }
-
- type PluginBase struct {
-@@ -73,12 +73,12 @@ type PluginBase struct {
- Root *PluginBase
- }
-
--func (pb *PluginBase) registerPlugin(pluginDir string) error {
-+func (pb *PluginBase) registerPlugin(base *PluginBase) error {
- if _, exists := Plugins[pb.Id]; exists {
- return fmt.Errorf("Plugin with ID %q already exists", pb.Id)
- }
-
-- if !strings.HasPrefix(pluginDir, setting.StaticRootPath) {
-+ if !strings.HasPrefix(base.PluginDir, setting.StaticRootPath) {
- plog.Info("Registering plugin", "name", pb.Name)
- }
-
-@@ -96,7 +96,10 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error {
- }
- }
-
-- pb.PluginDir = pluginDir
-+ // Copy relevant fields from the base
-+ pb.PluginDir = base.PluginDir
-+ pb.Signature = base.Signature
-+
- Plugins[pb.Id] = pb
- return nil
- }
-diff --git a/pkg/plugins/panel_plugin.go b/pkg/plugins/panel_plugin.go
-index ecece8a78fc4..4376dac18eea 100644
---- a/pkg/plugins/panel_plugin.go
-+++ b/pkg/plugins/panel_plugin.go
-@@ -11,12 +11,12 @@ type PanelPlugin struct {
- SkipDataQuery bool `json:"skipDataQuery"`
- }
-
--func (p *PanelPlugin) Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error {
-+func (p *PanelPlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error {
- if err := decoder.Decode(p); err != nil {
- return err
- }
-
-- if err := p.registerPlugin(pluginDir); err != nil {
-+ if err := p.registerPlugin(base); err != nil {
- return err
- }
-
-diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
-index 1217a642178f..4f7af38be32b 100644
---- a/pkg/plugins/plugins.go
-+++ b/pkg/plugins/plugins.go
-@@ -139,8 +139,7 @@ func (pm *PluginManager) Init() error {
- for _, p := range Plugins {
- if p.IsCorePlugin {
- p.Signature = PluginSignatureInternal
-- } else if p.Signature == "" {
-- p.Signature = getPluginSignatureState(pm.log, p)
-+ } else {
- metrics.SetPluginBuildInformation(p.Id, p.Type, p.Info.Version)
- }
- }
-@@ -272,8 +271,8 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
-
- jsonParser := json.NewDecoder(reader)
-
-- // TODO: We should avoid loading the plugin a second time, and instead re-use pluginCommon
-- if err := loader.Load(jsonParser, plugin.PluginDir, scanner.backendPluginManager); err != nil {
-+ // Load the full plugin, and add it to manager
-+ if err := loader.Load(jsonParser, plugin, scanner.backendPluginManager); err != nil {
- return err
- }
-
-diff --git a/pkg/plugins/renderer_plugin.go b/pkg/plugins/renderer_plugin.go
-index fcf7829ddde7..a5d86f5db266 100644
---- a/pkg/plugins/renderer_plugin.go
-+++ b/pkg/plugins/renderer_plugin.go
-@@ -22,12 +22,12 @@ type RendererPlugin struct {
- backendPluginManager backendplugin.Manager
- }
-
--func (r *RendererPlugin) Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error {
-+func (r *RendererPlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error {
- if err := decoder.Decode(r); err != nil {
- return err
- }
-
-- if err := r.registerPlugin(pluginDir); err != nil {
-+ if err := r.registerPlugin(base); err != nil {
- return err
- }
-
-diff --git a/pkg/plugins/transform_plugin.go b/pkg/plugins/transform_plugin.go
-index b62cc3e5258e..a3a6477287b0 100644
---- a/pkg/plugins/transform_plugin.go
-+++ b/pkg/plugins/transform_plugin.go
-@@ -28,12 +28,12 @@ type TransformPlugin struct {
- *TransformWrapper
- }
-
--func (p *TransformPlugin) Load(decoder *json.Decoder, pluginDir string, backendPluginManager backendplugin.Manager) error {
-+func (p *TransformPlugin) Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error {
- if err := decoder.Decode(p); err != nil {
- return err
- }
-
-- if err := p.registerPlugin(pluginDir); err != nil {
-+ if err := p.registerPlugin(base); err != nil {
- return err
- }
-
-
-From aaa5c115c4fbabf4cb9d8505955de43672e3835d Mon Sep 17 00:00:00 2001
-From: Arve Knudsen <arve.knudsen@gmail.com>
-Date: Fri, 2 Oct 2020 14:57:37 +0200
-Subject: [PATCH 4/4] plugins: Add documentation
-
-Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
----
- pkg/plugins/models.go | 3 +++
- pkg/plugins/plugins.go | 6 ++----
- 2 files changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go
-index 84b674720d39..ce8057bd0a84 100644
---- a/pkg/plugins/models.go
-+++ b/pkg/plugins/models.go
-@@ -42,10 +42,13 @@ func (e PluginNotFoundError) Error() string {
- return fmt.Sprintf("Plugin with id %s not found", e.PluginId)
- }
-
-+// PluginLoader can load a plugin.
- type PluginLoader interface {
-+ // Load loads a plugin and registers it with the manager.
- Load(decoder *json.Decoder, base *PluginBase, backendPluginManager backendplugin.Manager) error
- }
-
-+// PluginBase is the base plugin type.
- type PluginBase struct {
- Type string `json:"type"`
- Name string `json:"name"`
-diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
-index 4f7af38be32b..4b2b5e8232f3 100644
---- a/pkg/plugins/plugins.go
-+++ b/pkg/plugins/plugins.go
-@@ -211,13 +211,11 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error {
-
- pm.log.Debug("Initial plugin loading done")
-
-- // 2nd pass: Detect root plugins and verify signatures
-- // Any plugin that descends from a root plugin may inherit the root's signature
-+ // 2nd pass: Validate and register plugins
- for dpath, plugin := range scanner.plugins {
-+ // Try to find any root plugin
- ancestors := strings.Split(dpath, string(filepath.Separator))
- ancestors = ancestors[0 : len(ancestors)-1]
--
-- // Try to find any root plugin
- aPath := ""
- if runtime.GOOS != "windows" && filepath.IsAbs(dpath) {
- aPath = "/"