Plugins: Fix scanning plugins when permission for directories is lacking (#44587)

Fixes so that errors (directory not exists, no permission) when scanning plugins are logged as 
errors rather than with debug level. In addition, before the scanning would halt in case of 
referenced errors, but with these changes the scanning will continue. If any other error 
than the referenced error happens the scanning for specific directory would halt and return 
the error, e.g. stop Grafana from starting.

Fixes #43012
This commit is contained in:
Marcus Efraimsson 2022-01-31 14:07:10 +01:00 committed by GitHub
parent 5a5f5cacc8
commit 333de57999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 13 deletions

View File

@ -11,6 +11,8 @@ import (
"github.com/grafana/grafana/pkg/util"
)
var walk = util.Walk
type Finder struct {
log log.Logger
}
@ -51,9 +53,18 @@ func (f *Finder) getAbsPluginJSONPaths(path string) ([]string, error) {
return []string{}, err
}
if err := util.Walk(path, true, true,
if err := walk(path, true, true,
func(currentPath string, fi os.FileInfo, err error) error {
if err != nil {
if errors.Is(err, os.ErrNotExist) {
f.log.Error("Couldn't scan directory since it doesn't exist", "pluginDir", path, "err", err)
return nil
}
if errors.Is(err, os.ErrPermission) {
f.log.Error("Couldn't scan directory due to lack of permissions", "pluginDir", path, "err", err)
return nil
}
return fmt.Errorf("filepath.Walk reported an error for %q: %w", currentPath, err)
}
@ -72,15 +83,6 @@ func (f *Finder) getAbsPluginJSONPaths(path string) ([]string, error) {
pluginJSONPaths = append(pluginJSONPaths, currentPath)
return nil
}); err != nil {
if errors.Is(err, os.ErrNotExist) {
f.log.Debug("Couldn't scan directory since it doesn't exist", "pluginDir", path, "err", err)
return []string{}, nil
}
if errors.Is(err, os.ErrPermission) {
f.log.Debug("Couldn't scan directory due to lack of permissions", "pluginDir", path, "err", err)
return []string{}, nil
}
return []string{}, err
}

View File

@ -2,12 +2,16 @@ package finder
import (
"errors"
"fmt"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFinder_Find(t *testing.T) {
@ -65,3 +69,59 @@ func TestFinder_Find(t *testing.T) {
})
}
}
func TestFinder_getAbsPluginJSONPaths(t *testing.T) {
t.Run("When scanning a folder that doesn't exists shouldn't return an error", func(t *testing.T) {
origWalk := walk
walk = func(path string, followSymlinks, detectSymlinkInfiniteLoop bool, walkFn util.WalkFunc) error {
return walkFn(path, nil, os.ErrNotExist)
}
t.Cleanup(func() {
walk = origWalk
})
finder := &Finder{
log: log.New(),
}
paths, err := finder.getAbsPluginJSONPaths("test")
require.NoError(t, err)
require.Empty(t, paths)
})
t.Run("When scanning a folder that lacks permission shouldn't return an error", func(t *testing.T) {
origWalk := walk
walk = func(path string, followSymlinks, detectSymlinkInfiniteLoop bool, walkFn util.WalkFunc) error {
return walkFn(path, nil, os.ErrPermission)
}
t.Cleanup(func() {
walk = origWalk
})
finder := &Finder{
log: log.New(),
}
paths, err := finder.getAbsPluginJSONPaths("test")
require.NoError(t, err)
require.Empty(t, paths)
})
t.Run("When scanning a folder that returns a non-handled error should return that error", func(t *testing.T) {
origWalk := walk
walk = func(path string, followSymlinks, detectSymlinkInfiniteLoop bool, walkFn util.WalkFunc) error {
return walkFn(path, nil, fmt.Errorf("random error"))
}
t.Cleanup(func() {
walk = origWalk
})
finder := &Finder{
log: log.New(),
}
paths, err := finder.getAbsPluginJSONPaths("test")
require.Error(t, err)
require.Empty(t, paths)
})
}

View File

@ -62,7 +62,7 @@ func New(cfg *plugins.Cfg, license models.Licensing, authorizer plugins.PluginLo
func (l *Loader) Load(ctx context.Context, class plugins.Class, paths []string, ignore map[string]struct{}) ([]*plugins.Plugin, error) {
pluginJSONPaths, err := l.pluginFinder.Find(paths)
if err != nil {
l.log.Error("plugin finder encountered an error", "err", err)
return nil, err
}
return l.loadPlugins(ctx, class, pluginJSONPaths, ignore)