Plugins: Do not fail bootstrap stage if single decorate step fails (#73147)

* don't fail all if decorate step fails

* fix casing

* include err too

* cover pluginsintegration too
This commit is contained in:
Will Browne
2023-08-10 14:46:38 +02:00
committed by GitHub
parent 67de18ff06
commit c5e9a82ccb
19 changed files with 75 additions and 69 deletions
@@ -69,14 +69,22 @@ func (b *Bootstrap) Bootstrap(ctx context.Context, src plugins.PluginSource, fou
return ps, nil
}
bootstrappedPlugins := make([]*plugins.Plugin, 0, len(ps))
for _, p := range ps {
for _, decorator := range b.decorateSteps {
p, err = decorator(ctx, p)
var ip *plugins.Plugin
stepFailed := false
for _, decorate := range b.decorateSteps {
ip, err = decorate(ctx, p)
if err != nil {
return nil, err
stepFailed = true
b.log.Error("Could not decorate plugin", "pluginId", p.ID, "error", err)
break
}
}
if !stepFailed {
bootstrappedPlugins = append(bootstrappedPlugins, ip)
}
}
return ps, nil
return bootstrappedPlugins, nil
}
@@ -49,12 +49,12 @@ func (c *DefaultConstructor) Construct(ctx context.Context, src plugins.PluginSo
for _, bundle := range bundles {
sig, err := c.signatureCalculator.Calculate(ctx, src, bundle.Primary)
if err != nil {
c.log.Warn("Could not calculate plugin signature state", "pluginID", bundle.Primary.JSONData.ID, "err", err)
c.log.Warn("Could not calculate plugin signature state", "pluginId", bundle.Primary.JSONData.ID, "error", err)
continue
}
plugin, err := c.pluginFactoryFunc(bundle.Primary, src.PluginClass(ctx), sig)
if err != nil {
c.log.Error("Could not create primary plugin base", "pluginID", bundle.Primary.JSONData.ID, "err", err)
c.log.Error("Could not create primary plugin base", "pluginId", bundle.Primary.JSONData.ID, "error", err)
continue
}
res = append(res, plugin)
@@ -63,7 +63,7 @@ func (c *DefaultConstructor) Construct(ctx context.Context, src plugins.PluginSo
for _, child := range bundle.Children {
cp, err := c.pluginFactoryFunc(*child, plugin.Class, sig)
if err != nil {
c.log.Error("Could not create child plugin base", "pluginID", child.JSONData.ID, "err", err)
c.log.Error("Could not create child plugin base", "pluginId", child.JSONData.ID, "error", err)
continue
}
cp.Parent = plugin
@@ -58,17 +58,17 @@ func New(cfg *config.Cfg, opts Opts) *Discovery {
// Discover will execute the Find and Filter steps of the Discovery stage.
func (d *Discovery) Discover(ctx context.Context, src plugins.PluginSource) ([]*plugins.FoundBundle, error) {
found, err := d.findStep(ctx, src)
discoveredPlugins, err := d.findStep(ctx, src)
if err != nil {
return nil, err
}
for _, filterStep := range d.findFilterSteps {
found, err = filterStep(ctx, src.PluginClass(ctx), found)
for _, filter := range d.findFilterSteps {
discoveredPlugins, err = filter(ctx, src.PluginClass(ctx), discoveredPlugins)
if err != nil {
return nil, err
}
}
return found, nil
return discoveredPlugins, nil
}
@@ -37,14 +37,14 @@ func (d *DuplicatePluginValidation) Filter(ctx context.Context, bundles []*plugi
for _, b := range bundles {
_, exists := d.registry.Plugin(ctx, b.Primary.JSONData.ID)
if exists {
d.log.Warn("Skipping loading of plugin as it's a duplicate", "pluginID", b.Primary.JSONData.ID)
d.log.Warn("Skipping loading of plugin as it's a duplicate", "pluginId", b.Primary.JSONData.ID)
continue
}
for _, child := range b.Children {
_, exists = d.registry.Plugin(ctx, child.JSONData.ID)
if exists {
d.log.Warn("Skipping loading of child plugin as it's a duplicate", "pluginID", child.JSONData.ID)
d.log.Warn("Skipping loading of child plugin as it's a duplicate", "pluginId", child.JSONData.ID)
continue
}
}
@@ -54,7 +54,7 @@ func (i *Initialize) Initialize(ctx context.Context, ps []*plugins.Plugin) ([]*p
ip, err = init(ctx, p)
if err != nil {
stepFailed = true
i.log.Error("Could not initialize plugin", "pluginId", p.ID, "err", err)
i.log.Error("Could not initialize plugin", "pluginId", p.ID, "error", err)
break
}
}
@@ -80,7 +80,7 @@ func newBackendProcessStarter(processManager process.Service) *BackendClientStar
// 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)
b.log.Error("Could not start plugin", "pluginId", p.ID, "error", err)
return nil, err
}
return p, nil
@@ -107,11 +107,11 @@ func newPluginRegistration(pluginRegistry registry.Service) *PluginRegistration
// Initialize registers the plugin with the plugin registry.
func (r *PluginRegistration) Initialize(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
if err := r.pluginRegistry.Add(ctx, p); err != nil {
r.log.Error("Could not register plugin", "pluginID", p.ID, "err", err)
return nil, errors.New("could not register plugin")
r.log.Error("Could not register plugin", "pluginId", p.ID, "error", err)
return nil, err
}
if !p.IsCorePlugin() {
r.log.Info("Plugin registered", "pluginID", p.ID)
r.log.Info("Plugin registered", "pluginId", p.ID)
}
return p, nil
@@ -60,12 +60,12 @@ func (v *ModuleJSValidator) Validate(_ context.Context, p *plugins.Plugin) error
f, err := p.FS.Open("module.js")
if err != nil {
if errors.Is(err, plugins.ErrFileNotExist) {
v.log.Warn("Plugin missing module.js", "pluginID", p.ID,
v.log.Warn("Plugin missing module.js", "pluginId", p.ID,
"warning", "Missing module.js, If you loaded this plugin from git, make sure to compile it.")
}
} else if f != nil {
if err = f.Close(); err != nil {
v.log.Warn("Could not close module.js", "pluginID", p.ID, "err", err)
v.log.Warn("Could not close module.js", "pluginId", p.ID, "error", err)
}
}
}
@@ -99,12 +99,12 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
canc()
if err != nil {
a.log.Warn("Could not inspect plugin for angular", "pluginID", p.ID, "err", err)
a.log.Warn("Could not inspect plugin for angular", "pluginId", p.ID, "error", err)
}
// Do not initialize plugins if they're using Angular and Angular support is disabled
if p.AngularDetected && !a.cfg.AngularSupportEnabled {
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginID", p.ID)
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginId", p.ID)
return errors.New("angular plugins are not supported")
}
}
@@ -2,7 +2,6 @@ package validation
import (
"context"
"errors"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
@@ -41,27 +40,26 @@ func New(cfg *config.Cfg, opts Opts) *Validate {
}
// Validate will execute the Validate steps of the Validation stage.
func (t *Validate) Validate(ctx context.Context, ps []*plugins.Plugin) ([]*plugins.Plugin, error) {
if len(t.validateSteps) == 0 {
func (v *Validate) Validate(ctx context.Context, ps []*plugins.Plugin) ([]*plugins.Plugin, error) {
if len(v.validateSteps) == 0 {
return ps, nil
}
var err error
verifiedPlugins := make([]*plugins.Plugin, 0, len(ps))
validatedPlugins := make([]*plugins.Plugin, 0, len(ps))
for _, p := range ps {
stepFailed := false
for _, validate := range t.validateSteps {
err = validate(ctx, p)
if err != nil && !errors.Is(err, nil) {
for _, validate := range v.validateSteps {
err := validate(ctx, p)
if err != nil {
stepFailed = true
t.log.Error("Plugin verification failed", "pluginID", p.ID, "err", err)
v.log.Error("Plugin validation failed", "pluginId", p.ID, "error", err)
break
}
}
if !stepFailed {
verifiedPlugins = append(verifiedPlugins, p)
validatedPlugins = append(validatedPlugins, p)
}
}
return verifiedPlugins, nil
return validatedPlugins, nil
}