Commit a8eed9d3 by Torkel Ödegaard Committed by Carl Bergquist

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
parent 8f29d285
...@@ -17,6 +17,7 @@ import ( ...@@ -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 ( ...@@ -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 ( ...@@ -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 { ...@@ -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)
} }
......
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()) { ...@@ -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)
}) })
} }
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) { ...@@ -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)
......
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() { ...@@ -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 { ...@@ -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 ( ...@@ -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 { ...@@ -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 {
<-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 { ...@@ -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 { ...@@ -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 { ...@@ -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
} }
......
package plugins package plugins
import ( import (
"context"
"path/filepath" "path/filepath"
"testing" "testing"
...@@ -15,7 +14,9 @@ func TestPluginScans(t *testing.T) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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)
......
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