mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 03:12:13 +08:00
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
This commit is contained in:

committed by
Carl Bergquist

parent
8f29d28572
commit
a8eed9d344
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
|
pm := &PluginManager{}
|
||||||
|
err := pm.Init()
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
Convey(desc, fn)
|
Convey(desc, fn)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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() {
|
func (pm *PluginManager) updateAppDashboards() {
|
||||||
time.Sleep(time.Second * 5)
|
pm.log.Debug("Looking for App Dashboard Updates")
|
||||||
|
|
||||||
plog.Debug("Looking for App Dashboard Updates")
|
|
||||||
|
|
||||||
query := m.GetPluginSettingsQuery{OrgId: 0}
|
query := m.GetPluginSettingsQuery{OrgId: 0}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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) {
|
func init() {
|
||||||
err := initPlugins(ctx)
|
registry.RegisterService(&PluginManager{})
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PluginManager{
|
|
||||||
log: log.New("plugins"),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PluginManager) Run(ctx context.Context) error {
|
func (pm *PluginManager) Init() error {
|
||||||
<-ctx.Done()
|
pm.log = log.New("plugins")
|
||||||
|
|
||||||
for _, p := range DataSources {
|
|
||||||
p.Kill()
|
|
||||||
}
|
|
||||||
|
|
||||||
p.log.Info("Stopped Plugins", "reason", ctx.Err())
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initPlugins(ctx context.Context) error {
|
|
||||||
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()
|
return nil
|
||||||
go updateAppDashboards()
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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() {
|
func (pm *PluginManager) checkForUpdates() {
|
||||||
log.Trace("Checking for updates")
|
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)
|
||||||
|
Reference in New Issue
Block a user