浏览代码

Refactoring PluginManager to be a self registering service (#11755)

* refator: refactored PluginManager to be a self registering service, a lot more work needed to fully make plugin manager use instance variables and not so many globals
Torkel Ödegaard 7 年之前
父节点
当前提交
a8eed9d344

+ 2 - 8
pkg/cmd/grafana-server/server.go

@@ -17,6 +17,7 @@ import (
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/registry"
 	"github.com/grafana/grafana/pkg/registry"
 	"github.com/grafana/grafana/pkg/services/dashboards"
 	"github.com/grafana/grafana/pkg/services/dashboards"
+	"github.com/grafana/grafana/pkg/services/notifications"
 	"github.com/grafana/grafana/pkg/services/provisioning"
 	"github.com/grafana/grafana/pkg/services/provisioning"
 
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/sync/errgroup"
@@ -25,8 +26,6 @@ import (
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/login"
 	"github.com/grafana/grafana/pkg/login"
 	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/metrics"
-	"github.com/grafana/grafana/pkg/plugins"
-	"github.com/grafana/grafana/pkg/services/notifications"
 	"github.com/grafana/grafana/pkg/services/sqlstore"
 	"github.com/grafana/grafana/pkg/services/sqlstore"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/setting"
 
 
@@ -34,6 +33,7 @@ import (
 	"github.com/grafana/grafana/pkg/tracing"
 	"github.com/grafana/grafana/pkg/tracing"
 
 
 	_ "github.com/grafana/grafana/pkg/extensions"
 	_ "github.com/grafana/grafana/pkg/extensions"
+	_ "github.com/grafana/grafana/pkg/plugins"
 	_ "github.com/grafana/grafana/pkg/services/alerting"
 	_ "github.com/grafana/grafana/pkg/services/alerting"
 	_ "github.com/grafana/grafana/pkg/services/cleanup"
 	_ "github.com/grafana/grafana/pkg/services/cleanup"
 	_ "github.com/grafana/grafana/pkg/services/search"
 	_ "github.com/grafana/grafana/pkg/services/search"
@@ -73,12 +73,6 @@ func (g *GrafanaServerImpl) Start() error {
 	login.Init()
 	login.Init()
 	social.NewOAuthService()
 	social.NewOAuthService()
 
 
-	pluginManager, err := plugins.NewPluginManager(g.context)
-	if err != nil {
-		return fmt.Errorf("Failed to start plugins. error: %v", err)
-	}
-	g.childRoutines.Go(func() error { return pluginManager.Run(g.context) })
-
 	if err := provisioning.Init(g.context, setting.HomePath, setting.Cfg); err != nil {
 	if err := provisioning.Init(g.context, setting.HomePath, setting.Cfg); err != nil {
 		return fmt.Errorf("Failed to provision Grafana from config. error: %v", err)
 		return fmt.Errorf("Failed to provision Grafana from config. error: %v", err)
 	}
 	}

+ 3 - 3
pkg/plugins/dashboard_importer_test.go

@@ -1,7 +1,6 @@
 package plugins
 package plugins
 
 
 import (
 import (
-	"context"
 	"io/ioutil"
 	"io/ioutil"
 	"testing"
 	"testing"
 
 
@@ -91,10 +90,11 @@ func pluginScenario(desc string, t *testing.T, fn func()) {
 		setting.Cfg = ini.Empty()
 		setting.Cfg = ini.Empty()
 		sec, _ := setting.Cfg.NewSection("plugin.test-app")
 		sec, _ := setting.Cfg.NewSection("plugin.test-app")
 		sec.NewKey("path", "../../tests/test-app")
 		sec.NewKey("path", "../../tests/test-app")
-		err := initPlugins(context.Background())
 
 
-		So(err, ShouldBeNil)
+		pm := &PluginManager{}
+		err := pm.Init()
 
 
+		So(err, ShouldBeNil)
 		Convey(desc, fn)
 		Convey(desc, fn)
 	})
 	})
 }
 }

+ 3 - 2
pkg/plugins/dashboards_test.go

@@ -1,7 +1,6 @@
 package plugins
 package plugins
 
 
 import (
 import (
-	"context"
 	"testing"
 	"testing"
 
 
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/bus"
@@ -18,7 +17,9 @@ func TestPluginDashboards(t *testing.T) {
 		setting.Cfg = ini.Empty()
 		setting.Cfg = ini.Empty()
 		sec, _ := setting.Cfg.NewSection("plugin.test-app")
 		sec, _ := setting.Cfg.NewSection("plugin.test-app")
 		sec.NewKey("path", "../../tests/test-app")
 		sec.NewKey("path", "../../tests/test-app")
-		err := initPlugins(context.Background())
+
+		pm := &PluginManager{}
+		err := pm.Init()
 
 
 		So(err, ShouldBeNil)
 		So(err, ShouldBeNil)
 
 

+ 2 - 6
pkg/plugins/dashboards_updater.go

@@ -1,8 +1,6 @@
 package plugins
 package plugins
 
 
 import (
 import (
-	"time"
-
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/bus"
 	m "github.com/grafana/grafana/pkg/models"
 	m "github.com/grafana/grafana/pkg/models"
 )
 )
@@ -11,10 +9,8 @@ func init() {
 	bus.AddEventListener(handlePluginStateChanged)
 	bus.AddEventListener(handlePluginStateChanged)
 }
 }
 
 
-func updateAppDashboards() {
-	time.Sleep(time.Second * 5)
-
-	plog.Debug("Looking for App Dashboard Updates")
+func (pm *PluginManager) updateAppDashboards() {
+	pm.log.Debug("Looking for App Dashboard Updates")
 
 
 	query := m.GetPluginSettingsQuery{OrgId: 0}
 	query := m.GetPluginSettingsQuery{OrgId: 0}
 
 

+ 1 - 1
pkg/plugins/datasource_plugin.go

@@ -76,7 +76,7 @@ func composeBinaryName(executable, os, arch string) string {
 	return fmt.Sprintf("%s_%s_%s%s", executable, os, strings.ToLower(arch), extension)
 	return fmt.Sprintf("%s_%s_%s%s", executable, os, strings.ToLower(arch), extension)
 }
 }
 
 
-func (p *DataSourcePlugin) initBackendPlugin(ctx context.Context, log log.Logger) error {
+func (p *DataSourcePlugin) startBackendPlugin(ctx context.Context, log log.Logger) error {
 	p.log = log.New("plugin-id", p.Id)
 	p.log = log.New("plugin-id", p.Id)
 
 
 	err := p.spawnSubProcess()
 	err := p.spawnSubProcess()

+ 41 - 32
pkg/plugins/plugins.go

@@ -11,8 +11,10 @@ import (
 	"path/filepath"
 	"path/filepath"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
+	"time"
 
 
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/log"
+	"github.com/grafana/grafana/pkg/registry"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"
 	"github.com/grafana/grafana/pkg/util"
 )
 )
@@ -39,30 +41,12 @@ type PluginManager struct {
 	log log.Logger
 	log log.Logger
 }
 }
 
 
-func NewPluginManager(ctx context.Context) (*PluginManager, error) {
-	err := initPlugins(ctx)
-
-	if err != nil {
-		return nil, err
-	}
-
-	return &PluginManager{
-		log: log.New("plugins"),
-	}, nil
+func init() {
+	registry.RegisterService(&PluginManager{})
 }
 }
 
 
-func (p *PluginManager) Run(ctx context.Context) error {
-	<-ctx.Done()
-
-	for _, p := range DataSources {
-		p.Kill()
-	}
-
-	p.log.Info("Stopped Plugins", "reason", ctx.Err())
-	return ctx.Err()
-}
-
-func initPlugins(ctx context.Context) error {
+func (pm *PluginManager) Init() error {
+	pm.log = log.New("plugins")
 	plog = log.New("plugins")
 	plog = log.New("plugins")
 
 
 	DataSources = map[string]*DataSourcePlugin{}
 	DataSources = map[string]*DataSourcePlugin{}
@@ -76,7 +60,7 @@ func initPlugins(ctx context.Context) error {
 		"app":        AppPlugin{},
 		"app":        AppPlugin{},
 	}
 	}
 
 
-	plog.Info("Starting plugin search")
+	pm.log.Info("Starting plugin search")
 	scan(path.Join(setting.StaticRootPath, "app/plugins"))
 	scan(path.Join(setting.StaticRootPath, "app/plugins"))
 
 
 	// check if plugins dir exists
 	// check if plugins dir exists
@@ -99,13 +83,6 @@ func initPlugins(ctx context.Context) error {
 	}
 	}
 
 
 	for _, ds := range DataSources {
 	for _, ds := range DataSources {
-		if ds.Backend {
-			err := ds.initBackendPlugin(ctx, plog)
-			if err != nil {
-				plog.Error("Failed to init plugin.", "error", err, "plugin", ds.Id)
-			}
-		}
-
 		ds.initFrontendPlugin()
 		ds.initFrontendPlugin()
 	}
 	}
 
 
@@ -113,8 +90,40 @@ func initPlugins(ctx context.Context) error {
 		app.initApp()
 		app.initApp()
 	}
 	}
 
 
-	go StartPluginUpdateChecker()
-	go updateAppDashboards()
+	return nil
+}
+
+func (pm *PluginManager) startBackendPlugins(ctx context.Context) error {
+	for _, ds := range DataSources {
+		if ds.Backend {
+			if err := ds.startBackendPlugin(ctx, plog); err != nil {
+				pm.log.Error("Failed to init plugin.", "error", err, "plugin", ds.Id)
+			}
+		}
+	}
+
+	return nil
+}
+
+func (pm *PluginManager) Run(ctx context.Context) error {
+	pm.startBackendPlugins(ctx)
+	pm.updateAppDashboards()
+	pm.checkForUpdates()
+
+	ticker := time.NewTicker(time.Minute * 10)
+	for {
+		select {
+		case <-ticker.C:
+			pm.checkForUpdates()
+		case <-ctx.Done():
+			break
+		}
+	}
+
+	// kil backend plugins
+	for _, p := range DataSources {
+		p.Kill()
+	}
 
 
 	return nil
 	return nil
 }
 }

+ 6 - 3
pkg/plugins/plugins_test.go

@@ -1,7 +1,6 @@
 package plugins
 package plugins
 
 
 import (
 import (
-	"context"
 	"path/filepath"
 	"path/filepath"
 	"testing"
 	"testing"
 
 
@@ -15,7 +14,9 @@ func TestPluginScans(t *testing.T) {
 	Convey("When scanning for plugins", t, func() {
 	Convey("When scanning for plugins", t, func() {
 		setting.StaticRootPath, _ = filepath.Abs("../../public/")
 		setting.StaticRootPath, _ = filepath.Abs("../../public/")
 		setting.Cfg = ini.Empty()
 		setting.Cfg = ini.Empty()
-		err := initPlugins(context.Background())
+
+		pm := &PluginManager{}
+		err := pm.Init()
 
 
 		So(err, ShouldBeNil)
 		So(err, ShouldBeNil)
 		So(len(DataSources), ShouldBeGreaterThan, 1)
 		So(len(DataSources), ShouldBeGreaterThan, 1)
@@ -30,7 +31,9 @@ func TestPluginScans(t *testing.T) {
 		setting.Cfg = ini.Empty()
 		setting.Cfg = ini.Empty()
 		sec, _ := setting.Cfg.NewSection("plugin.nginx-app")
 		sec, _ := setting.Cfg.NewSection("plugin.nginx-app")
 		sec.NewKey("path", "../../tests/test-app")
 		sec.NewKey("path", "../../tests/test-app")
-		err := initPlugins(context.Background())
+
+		pm := &PluginManager{}
+		err := pm.Init()
 
 
 		So(err, ShouldBeNil)
 		So(err, ShouldBeNil)
 		So(len(Apps), ShouldBeGreaterThan, 0)
 		So(len(Apps), ShouldBeGreaterThan, 0)

+ 6 - 19
pkg/plugins/update_checker.go

@@ -26,23 +26,6 @@ type GithubLatest struct {
 	Testing string `json:"testing"`
 	Testing string `json:"testing"`
 }
 }
 
 
-func StartPluginUpdateChecker() {
-	if !setting.CheckForUpdates {
-		return
-	}
-
-	// do one check directly
-	go checkForUpdates()
-
-	ticker := time.NewTicker(time.Minute * 10)
-	for {
-		select {
-		case <-ticker.C:
-			checkForUpdates()
-		}
-	}
-}
-
 func getAllExternalPluginSlugs() string {
 func getAllExternalPluginSlugs() string {
 	var result []string
 	var result []string
 	for _, plug := range Plugins {
 	for _, plug := range Plugins {
@@ -56,8 +39,12 @@ func getAllExternalPluginSlugs() string {
 	return strings.Join(result, ",")
 	return strings.Join(result, ",")
 }
 }
 
 
-func checkForUpdates() {
-	log.Trace("Checking for updates")
+func (pm *PluginManager) checkForUpdates() {
+	if !setting.CheckForUpdates {
+		return
+	}
+
+	pm.log.Debug("Checking for updates")
 
 
 	pluginSlugs := getAllExternalPluginSlugs()
 	pluginSlugs := getAllExternalPluginSlugs()
 	resp, err := httpClient.Get("https://grafana.com/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)
 	resp, err := httpClient.Get("https://grafana.com/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)