Plugins: Add inititialization stage to plugin loader pipeline (#72667)
* first pass * migrate tests * simplify * fix comments * fix linter * nil checks * remove comment
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
package initializer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/config"
|
||||
"github.com/grafana/grafana/pkg/plugins/envvars"
|
||||
)
|
||||
|
||||
type Initializer struct {
|
||||
envVarProvider envvars.Provider
|
||||
backendProvider plugins.BackendFactoryProvider
|
||||
}
|
||||
|
||||
func New(cfg *config.Cfg, backendProvider plugins.BackendFactoryProvider, license plugins.Licensing) Initializer {
|
||||
return Initializer{
|
||||
envVarProvider: envvars.NewProvider(cfg, license),
|
||||
backendProvider: backendProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Initializer) Initialize(ctx context.Context, p *plugins.Plugin) error {
|
||||
if p.Backend {
|
||||
backendFactory := i.backendProvider.BackendFactory(ctx, p)
|
||||
if backendFactory == nil {
|
||||
return errors.New("could not find backend factory for plugin")
|
||||
}
|
||||
|
||||
env, err := i.envVarProvider.Get(ctx, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if backendClient, err := backendFactory(p.ID, p.Logger(), env); err != nil {
|
||||
return err
|
||||
} else {
|
||||
p.RegisterClient(backendClient)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package initializer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
)
|
||||
|
||||
func TestInitializer_Initialize(t *testing.T) {
|
||||
t.Run("core backend datasource", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
Type: plugins.TypeDataSource,
|
||||
Includes: []*plugins.Includes{
|
||||
{
|
||||
Name: "Example dashboard",
|
||||
Type: plugins.TypeDashboard,
|
||||
},
|
||||
},
|
||||
Backend: true,
|
||||
},
|
||||
Class: plugins.ClassCore,
|
||||
}
|
||||
|
||||
i := &Initializer{
|
||||
backendProvider: &fakeBackendProvider{
|
||||
plugin: p,
|
||||
},
|
||||
envVarProvider: &fakeEnvVarsProvider{},
|
||||
}
|
||||
|
||||
err := i.Initialize(context.Background(), p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
c, exists := p.Client()
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, c)
|
||||
})
|
||||
|
||||
t.Run("renderer", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
Type: plugins.TypeRenderer,
|
||||
Dependencies: plugins.Dependencies{
|
||||
GrafanaVersion: ">=8.x",
|
||||
},
|
||||
Backend: true,
|
||||
},
|
||||
Class: plugins.ClassExternal,
|
||||
}
|
||||
|
||||
i := &Initializer{
|
||||
backendProvider: &fakeBackendProvider{
|
||||
plugin: p,
|
||||
},
|
||||
envVarProvider: &fakeEnvVarsProvider{},
|
||||
}
|
||||
|
||||
err := i.Initialize(context.Background(), p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
c, exists := p.Client()
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, c)
|
||||
})
|
||||
|
||||
t.Run("secretsmanager", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
Type: plugins.TypeSecretsManager,
|
||||
Dependencies: plugins.Dependencies{
|
||||
GrafanaVersion: ">=8.x",
|
||||
},
|
||||
Backend: true,
|
||||
},
|
||||
Class: plugins.ClassExternal,
|
||||
}
|
||||
|
||||
i := &Initializer{
|
||||
backendProvider: &fakeBackendProvider{
|
||||
plugin: p,
|
||||
},
|
||||
envVarProvider: &fakeEnvVarsProvider{},
|
||||
}
|
||||
|
||||
err := i.Initialize(context.Background(), p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
c, exists := p.Client()
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, c)
|
||||
})
|
||||
|
||||
t.Run("non backend plugin app", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
Backend: false,
|
||||
},
|
||||
}
|
||||
|
||||
i := &Initializer{
|
||||
backendProvider: &fakeBackendProvider{
|
||||
plugin: p,
|
||||
},
|
||||
envVarProvider: &fakeEnvVarsProvider{},
|
||||
}
|
||||
|
||||
err := i.Initialize(context.Background(), p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
c, exists := p.Client()
|
||||
assert.False(t, exists)
|
||||
assert.Nil(t, c)
|
||||
})
|
||||
}
|
||||
|
||||
type fakeBackendProvider struct {
|
||||
plugins.BackendFactoryProvider
|
||||
|
||||
plugin *plugins.Plugin
|
||||
}
|
||||
|
||||
func (f *fakeBackendProvider) BackendFactory(_ context.Context, _ *plugins.Plugin) backendplugin.PluginFactoryFunc {
|
||||
return func(_ string, _ log.Logger, _ []string) (backendplugin.Plugin, error) {
|
||||
return f.plugin, nil
|
||||
}
|
||||
}
|
||||
|
||||
type fakeEnvVarsProvider struct {
|
||||
GetFunc func(ctx context.Context, p *plugins.Plugin) []string
|
||||
}
|
||||
|
||||
func (f *fakeEnvVarsProvider) Get(ctx context.Context, p *plugins.Plugin) ([]string, error) {
|
||||
if f.GetFunc != nil {
|
||||
return f.GetFunc(ctx, p), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angularinspector"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader/assetpath"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader/initializer"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/bootstrap"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/discovery"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/process"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/signature"
|
||||
@@ -24,13 +24,13 @@ import (
|
||||
var _ plugins.ErrorResolver = (*Loader)(nil)
|
||||
|
||||
type Loader struct {
|
||||
discovery discovery.Discoverer
|
||||
bootstrap bootstrap.Bootstrapper
|
||||
discovery discovery.Discoverer
|
||||
bootstrap bootstrap.Bootstrapper
|
||||
initializer initialization.Initializer
|
||||
|
||||
processManager process.Service
|
||||
pluginRegistry registry.Service
|
||||
roleRegistry plugins.RoleRegistry
|
||||
pluginInitializer initializer.Initializer
|
||||
signatureValidator signature.Validator
|
||||
externalServiceRegistry oauth.ExternalServiceRegistry
|
||||
assetPath *assetpath.Service
|
||||
@@ -42,23 +42,20 @@ type Loader struct {
|
||||
errs map[string]*plugins.SignatureError
|
||||
}
|
||||
|
||||
func ProvideService(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLoaderAuthorizer,
|
||||
pluginRegistry registry.Service, backendProvider plugins.BackendFactoryProvider,
|
||||
roleRegistry plugins.RoleRegistry, assetPath *assetpath.Service,
|
||||
func ProvideService(cfg *config.Cfg, authorizer plugins.PluginLoaderAuthorizer,
|
||||
pluginRegistry registry.Service, roleRegistry plugins.RoleRegistry, assetPath *assetpath.Service,
|
||||
angularInspector angularinspector.Inspector, externalServiceRegistry oauth.ExternalServiceRegistry,
|
||||
discovery discovery.Discoverer, bootstrap bootstrap.Bootstrapper) *Loader {
|
||||
return New(cfg, license, authorizer, pluginRegistry, backendProvider, process.NewManager(pluginRegistry),
|
||||
roleRegistry, assetPath, angularInspector, externalServiceRegistry, discovery, bootstrap)
|
||||
discovery discovery.Discoverer, bootstrap bootstrap.Bootstrapper, initializer initialization.Initializer) *Loader {
|
||||
return New(cfg, authorizer, pluginRegistry, process.NewManager(pluginRegistry), roleRegistry, assetPath,
|
||||
angularInspector, externalServiceRegistry, discovery, bootstrap, initializer)
|
||||
}
|
||||
|
||||
func New(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLoaderAuthorizer,
|
||||
pluginRegistry registry.Service, backendProvider plugins.BackendFactoryProvider,
|
||||
func New(cfg *config.Cfg, authorizer plugins.PluginLoaderAuthorizer, pluginRegistry registry.Service,
|
||||
processManager process.Service, roleRegistry plugins.RoleRegistry, assetPath *assetpath.Service,
|
||||
angularInspector angularinspector.Inspector, externalServiceRegistry oauth.ExternalServiceRegistry,
|
||||
discovery discovery.Discoverer, bootstrap bootstrap.Bootstrapper) *Loader {
|
||||
discovery discovery.Discoverer, bootstrap bootstrap.Bootstrapper, initializer initialization.Initializer) *Loader {
|
||||
return &Loader{
|
||||
pluginRegistry: pluginRegistry,
|
||||
pluginInitializer: initializer.New(cfg, backendProvider, license),
|
||||
signatureValidator: signature.NewValidator(authorizer),
|
||||
processManager: processManager,
|
||||
errs: make(map[string]*plugins.SignatureError),
|
||||
@@ -70,6 +67,7 @@ func New(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLo
|
||||
externalServiceRegistry: externalServiceRegistry,
|
||||
discovery: discovery,
|
||||
bootstrap: bootstrap,
|
||||
initializer: initializer,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,24 +142,9 @@ func (l *Loader) Load(ctx context.Context, src plugins.PluginSource) ([]*plugins
|
||||
// </VERIFICATION STAGE>
|
||||
|
||||
// <INITIALIZATION STAGE>
|
||||
initializedPlugins := make([]*plugins.Plugin, 0, len(verifiedPlugins))
|
||||
for _, p := range verifiedPlugins {
|
||||
err = l.pluginInitializer.Initialize(ctx, p)
|
||||
if err != nil {
|
||||
l.log.Error("Could not initialize plugin", "pluginId", p.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = l.pluginRegistry.Add(ctx, p); err != nil {
|
||||
l.log.Error("Could not start plugin", "pluginId", p.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !p.IsCorePlugin() {
|
||||
l.log.Info("Plugin registered", "pluginID", p.ID)
|
||||
}
|
||||
|
||||
initializedPlugins = append(initializedPlugins, p)
|
||||
initializedPlugins, err := l.initializer.Initialize(ctx, verifiedPlugins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// </INITIALIZATION STAGE>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user