feat: nice errors when failing to load plugins

partially fixes #7305
This commit is contained in:
Steven Allen 2020-06-04 20:22:28 -07:00 committed by Adin Schmahmann
parent 7648a46780
commit c07b6fb1d1
5 changed files with 82 additions and 43 deletions

View File

@ -0,0 +1,18 @@
// +build !cgo,!noplugin
// +build linux darwin
package loader
import (
"errors"
iplugin "github.com/ipfs/go-ipfs/plugin"
)
func init() {
loadPluginFunc = nocgoLoadPlugin
}
func nocgoLoadPlugin(fi string) ([]iplugin.Plugin, error) {
return nil, errors.New("not built with cgo support")
}

View File

@ -0,0 +1,17 @@
// +build noplugin
package loader
import (
"errors"
iplugin "github.com/ipfs/go-ipfs/plugin"
)
func init() {
loadPluginFunc = nopluginLoadPlugin
}
func nopluginLoadPlugin(string) ([]iplugin.Plugin, error) {
return nil, errors.New("not built with plugin support")
}

View File

@ -1,56 +1,20 @@
// +build !noplugin
// +build linux,cgo darwin,cgo
// +build cgo,!noplugin
// +build linux darwin
package loader
import (
"errors"
"fmt"
"os"
"path/filepath"
"plugin"
iplugin "github.com/ipfs/go-ipfs/plugin"
)
func init() {
loadPluginsFunc = linuxLoadFunc
loadPluginFunc = unixLoadPlugin
}
func linuxLoadFunc(pluginDir string) ([]iplugin.Plugin, error) {
var plugins []iplugin.Plugin
err := filepath.Walk(pluginDir, func(fi string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
if fi != pluginDir {
log.Warnf("found directory inside plugins directory: %s", fi)
}
return nil
}
if info.Mode().Perm()&0111 == 0 {
// file is not executable let's not load it
// this is to prevent loading plugins from for example non-executable
// mounts, some /tmp mounts are marked as such for security
log.Errorf("non-executable file in plugins directory: %s", fi)
return nil
}
if newPlugins, err := loadPlugin(fi); err == nil {
plugins = append(plugins, newPlugins...)
} else {
return fmt.Errorf("loading plugin %s: %s", fi, err)
}
return nil
})
return plugins, err
}
func loadPlugin(fi string) ([]iplugin.Plugin, error) {
func unixLoadPlugin(fi string) ([]iplugin.Plugin, error) {
pl, err := plugin.Open(fi)
if err != nil {
return nil, err

View File

@ -5,6 +5,7 @@ import (
"io"
"os"
"path/filepath"
"runtime"
"strings"
config "github.com/ipfs/go-ipfs-config"
@ -30,8 +31,8 @@ func Preload(plugins ...plugin.Plugin) {
var log = logging.Logger("plugin/loader")
var loadPluginsFunc = func(string) ([]plugin.Plugin, error) {
return nil, nil
var loadPluginFunc = func(string) ([]plugin.Plugin, error) {
return nil, fmt.Errorf("unsupported platform %s", runtime.GOOS)
}
type loaderState int
@ -182,7 +183,36 @@ func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) {
return nil, err
}
return loadPluginsFunc(pluginDir)
var plugins []plugin.Plugin
err = filepath.Walk(pluginDir, func(fi string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
if fi != pluginDir {
log.Warnf("found directory inside plugins directory: %s", fi)
}
return nil
}
if info.Mode().Perm()&0111 == 0 {
// file is not executable let's not load it
// this is to prevent loading plugins from for example non-executable
// mounts, some /tmp mounts are marked as such for security
log.Errorf("non-executable file in plugins directory: %s", fi)
return nil
}
if newPlugins, err := loadPluginFunc(fi); err == nil {
plugins = append(plugins, newPlugins...)
} else {
return fmt.Errorf("loading plugin %s: %s", fi, err)
}
return nil
})
return plugins, err
}
// Initialize initializes all loaded plugins

View File

@ -89,4 +89,14 @@ test_expect_success "configure the plugin" '
test_plugin true "$IPFS_PATH" "foobar"
test_expect_success "noplugin flag works" '
test_must_fail go run -tags=noplugin github.com/ipfs/go-ipfs/cmd/ipfs id > output 2>&1
test_should_contain "not built with plugin support" output
'
test_expect_success "noplugin flag works" '
CGO_ENABLED=0 test_must_fail go run github.com/ipfs/go-ipfs/cmd/ipfs id > output 2>&1
test_should_contain "not built with cgo support" output
'
test_done