Plugins: Add remaining steps to inititialization stage (#72894)

add remainder of init steps
This commit is contained in:
Will Browne 2023-08-04 12:35:57 +02:00 committed by GitHub
parent 60b4a0b2a4
commit 98f827537b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 124 additions and 35 deletions

View File

@ -71,11 +71,12 @@ func TestCallResource(t *testing.T) {
reg := registry.ProvideService() reg := registry.ProvideService()
angularInspector, err := angularinspector.NewStaticInspector() angularInspector, err := angularinspector.NewStaticInspector()
require.NoError(t, err) require.NoError(t, err)
proc := process.NewManager(reg)
discovery := pipeline.ProvideDiscoveryStage(pCfg, finder.NewLocalFinder(pCfg.DevMode), reg) discovery := pipeline.ProvideDiscoveryStage(pCfg, finder.NewLocalFinder(pCfg.DevMode), reg)
bootstrap := pipeline.ProvideBootstrapStage(pCfg, signature.ProvideService(pCfg, statickey.New()), assetpath.ProvideService(pluginscdn.ProvideService(pCfg))) bootstrap := pipeline.ProvideBootstrapStage(pCfg, signature.ProvideService(pCfg, statickey.New()), assetpath.ProvideService(pluginscdn.ProvideService(pCfg)))
initialize := pipeline.ProvideInitializationStage(pCfg, reg, fakes.NewFakeLicensingService(), provider.ProvideService(coreRegistry)) initialize := pipeline.ProvideInitializationStage(pCfg, reg, fakes.NewFakeLicensingService(), provider.ProvideService(coreRegistry), proc, &fakes.FakeOauthService{}, fakes.NewFakeRoleRegistry())
terminate, err := pipeline.ProvideTerminationStage(pCfg, reg, process.NewManager(reg)) terminate, err := pipeline.ProvideTerminationStage(pCfg, reg, proc)
require.NoError(t, err) require.NoError(t, err)
l := loader.ProvideService(pCfg, signature.NewUnsignedAuthorizer(pCfg), l := loader.ProvideService(pCfg, signature.NewUnsignedAuthorizer(pCfg),

View File

@ -5,7 +5,6 @@ import (
"errors" "errors"
"time" "time"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log" "github.com/grafana/grafana/pkg/plugins/log"
@ -19,7 +18,6 @@ import (
"github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/signature"
"github.com/grafana/grafana/pkg/plugins/oauth" "github.com/grafana/grafana/pkg/plugins/oauth"
"github.com/grafana/grafana/pkg/services/featuremgmt"
) )
var _ plugins.ErrorResolver = (*Loader)(nil) var _ plugins.ErrorResolver = (*Loader)(nil)
@ -153,32 +151,6 @@ func (l *Loader) Load(ctx context.Context, src plugins.PluginSource) ([]*plugins
} }
// </INITIALIZATION STAGE> // </INITIALIZATION STAGE>
// <POST-INITIALIZATION STAGE>
for _, p := range initializedPlugins {
if err = l.processManager.Start(ctx, p.ID); err != nil {
l.log.Error("Could not start plugin", "pluginId", p.ID, "err", err)
continue
}
if p.ExternalServiceRegistration != nil && l.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAuth) {
s, err := l.externalServiceRegistry.RegisterExternalService(ctx, p.ID, p.ExternalServiceRegistration)
if err != nil {
l.log.Error("Could not register an external service. Initialization skipped", "pluginID", p.ID, "err", err)
continue
}
p.ExternalService = s
}
if err = l.roleRegistry.DeclarePluginRoles(ctx, p.ID, p.Name, p.Roles); err != nil {
l.log.Warn("Declare plugin roles failed.", "pluginID", p.ID, "err", err)
}
if !p.IsCorePlugin() && !p.IsBundledPlugin() {
metrics.SetPluginBuildInformation(p.ID, string(p.Type), p.Info.Version, string(p.Signature))
}
}
// </POST-INITIALIZATION STAGE>
return initializedPlugins, nil return initializedPlugins, nil
} }

View File

@ -122,11 +122,12 @@ func TestIntegrationPluginManager(t *testing.T) {
lic := plicensing.ProvideLicensing(cfg, &licensing.OSSLicensingService{Cfg: cfg}) lic := plicensing.ProvideLicensing(cfg, &licensing.OSSLicensingService{Cfg: cfg})
angularInspector, err := angularinspector.NewStaticInspector() angularInspector, err := angularinspector.NewStaticInspector()
require.NoError(t, err) require.NoError(t, err)
proc := process.NewManager(reg)
discovery := pipeline.ProvideDiscoveryStage(pCfg, finder.NewLocalFinder(pCfg.DevMode), reg) discovery := pipeline.ProvideDiscoveryStage(pCfg, finder.NewLocalFinder(pCfg.DevMode), reg)
bootstrap := pipeline.ProvideBootstrapStage(pCfg, signature.ProvideService(pCfg, statickey.New()), assetpath.ProvideService(pluginscdn.ProvideService(pCfg))) bootstrap := pipeline.ProvideBootstrapStage(pCfg, signature.ProvideService(pCfg, statickey.New()), assetpath.ProvideService(pluginscdn.ProvideService(pCfg)))
initialize := pipeline.ProvideInitializationStage(pCfg, reg, lic, provider.ProvideService(coreRegistry)) initialize := pipeline.ProvideInitializationStage(pCfg, reg, lic, provider.ProvideService(coreRegistry), proc, &fakes.FakeOauthService{}, fakes.NewFakeRoleRegistry())
terminate, err := pipeline.ProvideTerminationStage(pCfg, reg, process.NewManager(reg)) terminate, err := pipeline.ProvideTerminationStage(pCfg, reg, proc)
require.NoError(t, err) require.NoError(t, err)
l := loader.ProvideService(pCfg, signature.NewUnsignedAuthorizer(pCfg), l := loader.ProvideService(pCfg, signature.NewUnsignedAuthorizer(pCfg),

View File

@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/envvars" "github.com/grafana/grafana/pkg/plugins/envvars"
"github.com/grafana/grafana/pkg/plugins/log" "github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/plugins/manager/process"
"github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/registry"
) )
@ -15,7 +16,7 @@ import (
// It uses the envvars.Provider to retrieve the environment variables required for the plugin and the plugins.BackendFactoryProvider // It uses the envvars.Provider to retrieve the environment variables required for the plugin and the plugins.BackendFactoryProvider
// to get fetch backend factory, which is used to form a connection to the backend plugin process. // to get fetch backend factory, which is used to form a connection to the backend plugin process.
// //
// Note: This step does not start the backend plugin process. // Note: This step does not start the backend plugin process. Please see BackendClientStarter for starting the backend plugin process.
type BackendClientInit struct { type BackendClientInit struct {
envVarProvider envvars.Provider envVarProvider envvars.Provider
backendProvider plugins.BackendFactoryProvider backendProvider plugins.BackendFactoryProvider
@ -58,6 +59,33 @@ func (b *BackendClientInit) Initialize(ctx context.Context, p *plugins.Plugin) (
return p, nil return p, nil
} }
// BackendClientStarter implements an InitializeFunc for starting a backend plugin process.
type BackendClientStarter struct {
processManager process.Service
log log.Logger
}
// BackendProcessStartStep returns a new InitializeFunc for starting a backend plugin process.
func BackendProcessStartStep(processManager process.Service) InitializeFunc {
return newBackendProcessStarter(processManager).Start
}
func newBackendProcessStarter(processManager process.Service) *BackendClientStarter {
return &BackendClientStarter{
processManager: processManager,
log: log.New("plugins.backend.start"),
}
}
// Start will start the backend plugin process.
func (b *BackendClientStarter) Start(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
if err := b.processManager.Start(ctx, p.ID); err != nil {
b.log.Error("Could not start plugin", "pluginId", p.ID, "err", err)
return nil, err
}
return p, nil
}
// PluginRegistration implements an InitializeFunc for registering a plugin with the plugin registry. // PluginRegistration implements an InitializeFunc for registering a plugin with the plugin registry.
type PluginRegistration struct { type PluginRegistration struct {
pluginRegistry registry.Service pluginRegistry registry.Service

View File

@ -1327,7 +1327,7 @@ func newLoader(t *testing.T, cfg *config.Cfg, reg registry.Service, proc process
angularInspector, &fakes.FakeOauthService{}, angularInspector, &fakes.FakeOauthService{},
pipeline.ProvideDiscoveryStage(cfg, finder.NewLocalFinder(false), reg), pipeline.ProvideDiscoveryStage(cfg, finder.NewLocalFinder(false), reg),
pipeline.ProvideBootstrapStage(cfg, signature.DefaultCalculator(cfg), assets), pipeline.ProvideBootstrapStage(cfg, signature.DefaultCalculator(cfg), assets),
pipeline.ProvideInitializationStage(cfg, reg, lic, backendFactory), pipeline.ProvideInitializationStage(cfg, reg, lic, backendFactory, proc, &fakes.FakeOauthService{}, fakes.NewFakeRoleRegistry()),
terminate) terminate)
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination"
"github.com/grafana/grafana/pkg/plugins/manager/process" "github.com/grafana/grafana/pkg/plugins/manager/process"
"github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/oauth"
) )
func ProvideDiscoveryStage(cfg *config.Cfg, pf finder.Finder, pr registry.Service) *discovery.Discovery { func ProvideDiscoveryStage(cfg *config.Cfg, pf finder.Finder, pr registry.Service) *discovery.Discovery {
@ -36,11 +37,17 @@ func ProvideBootstrapStage(cfg *config.Cfg, sc plugins.SignatureCalculator, a *a
}) })
} }
func ProvideInitializationStage(cfg *config.Cfg, pr registry.Service, l plugins.Licensing, bp plugins.BackendFactoryProvider) *initialization.Initialize { func ProvideInitializationStage(cfg *config.Cfg, pr registry.Service, l plugins.Licensing,
bp plugins.BackendFactoryProvider, pm process.Service, externalServiceRegistry oauth.ExternalServiceRegistry,
roleRegistry plugins.RoleRegistry) *initialization.Initialize {
return initialization.New(cfg, initialization.Opts{ return initialization.New(cfg, initialization.Opts{
InitializeFuncs: []initialization.InitializeFunc{ InitializeFuncs: []initialization.InitializeFunc{
initialization.BackendClientInitStep(envvars.NewProvider(cfg, l), bp), initialization.BackendClientInitStep(envvars.NewProvider(cfg, l), bp),
initialization.PluginRegistrationStep(pr), initialization.PluginRegistrationStep(pr),
initialization.BackendProcessStartStep(pm),
ExternalServiceRegistrationStep(cfg, externalServiceRegistry),
RegisterPluginRolesStep(roleRegistry),
ReportBuildMetrics,
}, },
}) })
} }

View File

@ -0,0 +1,80 @@
package pipeline
import (
"context"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"
"github.com/grafana/grafana/pkg/plugins/oauth"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
// ExternalServiceRegistration implements an InitializeFunc for registering external services.
type ExternalServiceRegistration struct {
cfg *config.Cfg
externalServiceRegistry oauth.ExternalServiceRegistry
log log.Logger
}
// ExternalServiceRegistrationStep returns an InitializeFunc for registering external services.
func ExternalServiceRegistrationStep(cfg *config.Cfg, externalServiceRegistry oauth.ExternalServiceRegistry) initialization.InitializeFunc {
return newExternalServiceRegistration(cfg, externalServiceRegistry).Register
}
func newExternalServiceRegistration(cfg *config.Cfg, serviceRegistry oauth.ExternalServiceRegistry) *ExternalServiceRegistration {
return &ExternalServiceRegistration{
cfg: cfg,
externalServiceRegistry: serviceRegistry,
log: log.New("plugins.external.registration"),
}
}
// Register registers the external service with the external service registry, if the feature is enabled.
func (r *ExternalServiceRegistration) Register(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
if p.ExternalServiceRegistration != nil && r.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAuth) {
s, err := r.externalServiceRegistry.RegisterExternalService(ctx, p.ID, p.ExternalServiceRegistration)
if err != nil {
r.log.Error("Could not register an external service. Initialization skipped", "pluginID", p.ID, "err", err)
return nil, err
}
p.ExternalService = s
}
return p, nil
}
// RegisterPluginRoles implements an InitializeFunc for registering plugin roles.
type RegisterPluginRoles struct {
log log.Logger
roleRegistry plugins.RoleRegistry
}
// RegisterPluginRolesStep returns a new InitializeFunc for registering plugin roles.
func RegisterPluginRolesStep(roleRegistry plugins.RoleRegistry) initialization.InitializeFunc {
return newRegisterPluginRoles(roleRegistry).Register
}
func newRegisterPluginRoles(registry plugins.RoleRegistry) *RegisterPluginRoles {
return &RegisterPluginRoles{
log: log.New("plugins.roles.registration"),
roleRegistry: registry,
}
}
// Register registers the plugin roles with the role registry.
func (r *RegisterPluginRoles) Register(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
if err := r.roleRegistry.DeclarePluginRoles(ctx, p.ID, p.Name, p.Roles); err != nil {
r.log.Warn("Declare plugin roles failed.", "pluginID", p.ID, "err", err)
}
return p, nil
}
// ReportBuildMetrics reports build information for all plugins, except core and bundled plugins.
func ReportBuildMetrics(_ context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
if !p.IsCorePlugin() && !p.IsBundledPlugin() {
metrics.SetPluginBuildInformation(p.ID, string(p.Type), p.Info.Version, string(p.Signature))
}
return p, nil
}