Plugins: Add pluginStoreServiceLoading feature toggle (#112588)
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
@@ -33,11 +34,36 @@ type Service struct {
|
||||
pluginRegistry registry.Service
|
||||
pluginLoader loader.Service
|
||||
pluginSources sources.Registry
|
||||
loadOnStartup bool
|
||||
}
|
||||
|
||||
func ProvideService(pluginRegistry registry.Service, pluginSources sources.Registry,
|
||||
pluginLoader loader.Service) *Service {
|
||||
return New(pluginRegistry, pluginLoader, pluginSources)
|
||||
pluginLoader loader.Service, features featuremgmt.FeatureToggles) (*Service, error) {
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagPluginStoreServiceLoading) {
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources)
|
||||
s.loadOnStartup = true
|
||||
return s, nil
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
start := time.Now()
|
||||
totalPlugins := 0
|
||||
logger := log.New("plugin.store")
|
||||
logger.Info("Loading plugins...")
|
||||
|
||||
for _, ps := range pluginSources.List(ctx) {
|
||||
loadedPlugins, err := pluginLoader.Load(ctx, ps)
|
||||
if err != nil {
|
||||
logger.Error("Loading plugin source failed", "source", ps.PluginClass(ctx), "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalPlugins += len(loadedPlugins)
|
||||
}
|
||||
|
||||
logger.Info("Plugins loaded", "count", totalPlugins, "duration", time.Since(start))
|
||||
|
||||
return New(pluginRegistry, pluginLoader, pluginSources), nil
|
||||
}
|
||||
|
||||
func (s *Service) Run(ctx context.Context) error {
|
||||
@@ -50,6 +76,7 @@ func (s *Service) Run(ctx context.Context) error {
|
||||
|
||||
func NewPluginStoreForTest(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSources sources.Registry) (*Service, error) {
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources)
|
||||
s.loadOnStartup = true
|
||||
if err := s.StartAsync(context.Background()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,6 +97,9 @@ func New(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSou
|
||||
}
|
||||
|
||||
func (s *Service) starting(ctx context.Context) error {
|
||||
if !s.loadOnStartup {
|
||||
return nil
|
||||
}
|
||||
start := time.Now()
|
||||
totalPlugins := 0
|
||||
logger := log.New(ServiceName)
|
||||
@@ -85,7 +115,6 @@ func (s *Service) starting(ctx context.Context) error {
|
||||
}
|
||||
|
||||
logger.Info("Plugins loaded", "count", totalPlugins, "duration", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,45 +11,83 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
)
|
||||
|
||||
func TestStore_ProvideService(t *testing.T) {
|
||||
t.Run("Plugin sources are added in order", func(t *testing.T) {
|
||||
var loadedSrcs []plugins.Class
|
||||
l := &pluginfakes.FakeLoader{
|
||||
LoadFunc: func(ctx context.Context, src plugins.PluginSource) ([]*plugins.Plugin, error) {
|
||||
loadedSrcs = append(loadedSrcs, src.PluginClass(ctx))
|
||||
return nil, nil
|
||||
tests := []struct {
|
||||
name string
|
||||
featureEnabled bool
|
||||
expectedLoadOnStartup bool
|
||||
expectedBeforeStart []plugins.Class
|
||||
expectedAfterStart []plugins.Class
|
||||
}{
|
||||
{
|
||||
name: "with FlagPluginStoreServiceLoading disabled",
|
||||
featureEnabled: false,
|
||||
expectedLoadOnStartup: false,
|
||||
expectedBeforeStart: []plugins.Class{"1", "2", "3"},
|
||||
expectedAfterStart: []plugins.Class{"1", "2", "3"},
|
||||
},
|
||||
{
|
||||
name: "with FlagPluginStoreServiceLoading enabled",
|
||||
featureEnabled: true,
|
||||
expectedLoadOnStartup: true,
|
||||
expectedBeforeStart: nil,
|
||||
expectedAfterStart: []plugins.Class{"1", "2", "3"},
|
||||
},
|
||||
}
|
||||
|
||||
srcs := &pluginfakes.FakeSourceRegistry{ListFunc: func(_ context.Context) []plugins.PluginSource {
|
||||
return []plugins.PluginSource{
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "1"
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var loadedSrcs []plugins.Class
|
||||
l := &pluginfakes.FakeLoader{
|
||||
LoadFunc: func(ctx context.Context, src plugins.PluginSource) ([]*plugins.Plugin, error) {
|
||||
loadedSrcs = append(loadedSrcs, src.PluginClass(ctx))
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "2"
|
||||
},
|
||||
},
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "3"
|
||||
},
|
||||
},
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
service := ProvideService(pluginfakes.NewFakePluginRegistry(), srcs, l)
|
||||
ctx := context.Background()
|
||||
err := service.StartAsync(ctx)
|
||||
require.NoError(t, err)
|
||||
err = service.AwaitRunning(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []plugins.Class{"1", "2", "3"}, loadedSrcs)
|
||||
srcs := &pluginfakes.FakeSourceRegistry{ListFunc: func(_ context.Context) []plugins.PluginSource {
|
||||
return []plugins.PluginSource{
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "1"
|
||||
},
|
||||
},
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "2"
|
||||
},
|
||||
},
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return "3"
|
||||
},
|
||||
},
|
||||
}
|
||||
}}
|
||||
|
||||
var features featuremgmt.FeatureToggles
|
||||
if tt.featureEnabled {
|
||||
features = featuremgmt.WithFeatures(featuremgmt.FlagPluginStoreServiceLoading)
|
||||
} else {
|
||||
features = featuremgmt.WithFeatures()
|
||||
}
|
||||
|
||||
service, err := ProvideService(pluginfakes.NewFakePluginRegistry(), srcs, l, features)
|
||||
require.Equal(t, tt.expectedLoadOnStartup, service.loadOnStartup)
|
||||
require.Equal(t, tt.expectedBeforeStart, loadedSrcs)
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
err = service.StartAsync(ctx)
|
||||
require.NoError(t, err)
|
||||
err = service.AwaitRunning(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.expectedAfterStart, loadedSrcs)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user