Merge pull request #1724 from monopole/removeErrorFromConstructor

Improve error messaging around plugin loading problems.
This commit is contained in:
Jeff Regan
2019-11-03 06:46:31 -08:00
committed by GitHub
12 changed files with 67 additions and 47 deletions

View File

@@ -28,11 +28,6 @@ type Kustomizer struct {
options *Options options *Options
} }
// MakeDefaultKustomizer returns a Kustomizer with default configuration.
func MakeDefaultKustomizer() *Kustomizer {
return MakeKustomizer(filesys.MakeFsOnDisk(), MakeDefaultOptions())
}
// MakeKustomizer returns an instance of Kustomizer. // MakeKustomizer returns an instance of Kustomizer.
func MakeKustomizer(fSys filesys.FileSystem, o *Options) *Kustomizer { func MakeKustomizer(fSys filesys.FileSystem, o *Options) *Kustomizer {
return &Kustomizer{fSys: fSys, options: o} return &Kustomizer{fSys: fSys, options: o}

View File

@@ -35,6 +35,6 @@ func MakeDefaultOptions() *Options {
DoLegacyResourceSort: true, DoLegacyResourceSort: true,
LoadRestrictions: types.LoadRestrictionsRootOnly, LoadRestrictions: types.LoadRestrictionsRootOnly,
DoPrune: false, DoPrune: false,
PluginConfig: pgmconfig.DefaultPluginConfig(), PluginConfig: pgmconfig.DisabledPluginConfig(),
} }
} }

View File

@@ -36,19 +36,27 @@ const (
DomainName = "sigs.k8s.io" DomainName = "sigs.k8s.io"
) )
func ActivePluginConfig() *types.PluginConfig { func EnabledPluginConfig() *types.PluginConfig {
pc := DefaultPluginConfig() return MakePluginConfig(
pc.PluginRestrictions = types.PluginRestrictionsNone types.PluginRestrictionsNone, DefaultAbsPluginHome())
return pc
} }
func DefaultPluginConfig() *types.PluginConfig { func DisabledPluginConfig() *types.PluginConfig {
return MakePluginConfig(
types.PluginRestrictionsBuiltinsOnly, NoPluginHomeSentinal)
}
func MakePluginConfig(
pr types.PluginRestrictions, home string) *types.PluginConfig {
return &types.PluginConfig{ return &types.PluginConfig{
PluginRestrictions: types.PluginRestrictionsBuiltinsOnly, PluginRestrictions: pr,
AbsPluginHome: DefaultAbsPluginHome(), AbsPluginHome: home,
} }
} }
// Use an obviously erroneous path, in case it's accidentally used.
const NoPluginHomeSentinal = "/no/non-builtin/plugins!"
func DefaultAbsPluginHome() string { func DefaultAbsPluginHome() string {
return filepath.Join(configRoot(), RelPluginHome) return filepath.Join(configRoot(), RelPluginHome)
} }

View File

@@ -41,7 +41,7 @@ func DefaultSrcRoot() (string, error) {
} }
nope = append(nope, root) nope = append(nope, root)
root = pgmconfig.DefaultPluginConfig().AbsPluginHome root = pgmconfig.DefaultAbsPluginHome()
if FileExists(root) { if FileExists(root) {
return root, nil return root, nil
} }

View File

@@ -44,15 +44,19 @@ type ExecPlugin struct {
h *resmap.PluginHelpers h *resmap.PluginHelpers
} }
func NewExecPlugin(p string) (*ExecPlugin, error) { func NewExecPlugin(p string) *ExecPlugin {
f, err := os.Stat(p) return &ExecPlugin{path: p}
}
func (p *ExecPlugin) ErrIfNotExecutable() error {
f, err := os.Stat(p.path)
if err != nil { if err != nil {
return nil, err return err
} }
if f.Mode()&0111 == 0000 { if f.Mode()&0111 == 0000 {
return nil, fmt.Errorf("unable to execute plugin on path: %s", p) return fmt.Errorf("unexecutable plugin at: %s", p.path)
} }
return &ExecPlugin{path: p}, nil return nil
} }
func (p *ExecPlugin) Path() string { func (p *ExecPlugin) Path() string {

View File

@@ -5,7 +5,6 @@ package execplugin_test
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
"testing" "testing"
@@ -44,13 +43,15 @@ s/$BAR/bar/g
\ \ \ \ \ \
`)) `))
p, err := NewExecPlugin( p := NewExecPlugin(
loader.AbsolutePluginPath( loader.AbsolutePluginPath(
pgmconfig.DefaultPluginConfig(), pgmconfig.DisabledPluginConfig(),
pluginConfig.OrgId())) pluginConfig.OrgId()))
if err != nil { // Not checking to see if the plugin is executable,
t.Fatalf("unexpected error: %v", err.Error()) // because this test does not run it.
} // This tests only covers sending configuration
// to the plugin wrapper object and confirming
// that it's properly prepared for execution.
yaml, err := pluginConfig.AsYAML() yaml, err := pluginConfig.AsYAML()
if err != nil { if err != nil {
@@ -58,7 +59,7 @@ s/$BAR/bar/g
} }
p.Config(resmap.NewPluginHelpers(ldr, v, rf), yaml) p.Config(resmap.NewPluginHelpers(ldr, v, rf), yaml)
expected := "/kustomize/plugin/someteam.example.com/v1/sedtransformer/SedTransformer" expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
if !strings.HasSuffix(p.Path(), expected) { if !strings.HasSuffix(p.Path(), expected) {
t.Fatalf("expected suffix '%s', got '%s'", expected, p.Path()) t.Fatalf("expected suffix '%s', got '%s'", expected, p.Path())
} }
@@ -118,9 +119,9 @@ func strptr(s string) *string {
} }
func TestUpdateResourceOptions(t *testing.T) { func TestUpdateResourceOptions(t *testing.T) {
p, err := NewExecPlugin("") p := NewExecPlugin("")
if !os.IsNotExist(err) { if err := p.ErrIfNotExecutable(); err == nil {
t.Fatalf("unexpected error: %v", err.Error()) t.Fatalf("expected unexecutable error")
} }
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()) rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
in := resmap.New() in := resmap.New()
@@ -166,9 +167,9 @@ func TestUpdateResourceOptions(t *testing.T) {
} }
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) { func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
p, err := NewExecPlugin("") p := NewExecPlugin("")
if !os.IsNotExist(err) { if err := p.ErrIfNotExecutable(); err == nil {
t.Fatalf("unexpected error: %v", err.Error()) t.Fatalf("expected unexecutable error")
} }
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()) rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
cases := []string{ cases := []string{

View File

@@ -146,13 +146,23 @@ func (l *Loader) makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
} }
func (l *Loader) loadPlugin(resId resid.ResId) (resmap.Configurable, error) { func (l *Loader) loadPlugin(resId resid.ResId) (resmap.Configurable, error) {
p, err := execplugin.NewExecPlugin(l.absolutePluginPath(resId)) // First try to load the plugin as an executable.
p := execplugin.NewExecPlugin(l.absolutePluginPath(resId))
err := p.ErrIfNotExecutable()
if err == nil { if err == nil {
return p, nil return p, nil
} }
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
// The file exists, but something else is wrong,
// likely it's not executable.
// Assume the user forgot to set the exec bit,
// and return an error, rather than adding ".so"
// to the name and attempting to load it as a Go
// plugin, which will likely fail and result
// in an obscure message.
return nil, err return nil, err
} }
// Failing the above, try loading it as a Go plugin.
c, err := l.loadGoPlugin(resId) c, err := l.loadGoPlugin(resId)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -186,7 +196,7 @@ func (l *Loader) loadGoPlugin(id resid.ResId) (resmap.Configurable, error) {
} }
c, ok := symbol.(resmap.Configurable) c, ok := symbol.(resmap.Configurable)
if !ok { if !ok {
return nil, fmt.Errorf("plugin %s not configurable", regId) return nil, fmt.Errorf("plugin '%s' not configurable", regId)
} }
registry[regId] = c registry[regId] = c
return copyPlugin(c), nil return copyPlugin(c), nil

View File

@@ -57,7 +57,7 @@ func TestLoader(t *testing.T) {
ldr := loadertest.NewFakeLoader("/foo") ldr := loadertest.NewFakeLoader("/foo")
pLdr := NewLoader(pgmconfig.ActivePluginConfig(), rmF) pLdr := NewLoader(pgmconfig.EnabledPluginConfig(), rmF)
if pLdr == nil { if pLdr == nil {
t.Fatal("expect non-nil loader") t.Fatal("expect non-nil loader")
} }

View File

@@ -300,7 +300,7 @@ spec:
func TestSharedPatchDisAllowed(t *testing.T) { func TestSharedPatchDisAllowed(t *testing.T) {
th := kusttest_test.NewKustTestHarnessFull( th := kusttest_test.NewKustTestHarnessFull(
t, "/app/overlay", t, "/app/overlay",
loader.RestrictionRootOnly, pgmconfig.DefaultPluginConfig()) loader.RestrictionRootOnly, pgmconfig.DisabledPluginConfig())
writeSmallBase(th) writeSmallBase(th)
th.WriteK("/app/overlay", ` th.WriteK("/app/overlay", `
commonLabels: commonLabels:
@@ -332,7 +332,7 @@ spec:
func TestSharedPatchAllowed(t *testing.T) { func TestSharedPatchAllowed(t *testing.T) {
th := kusttest_test.NewKustTestHarnessFull( th := kusttest_test.NewKustTestHarnessFull(
t, "/app/overlay", t, "/app/overlay",
loader.RestrictionNone, pgmconfig.DefaultPluginConfig()) loader.RestrictionNone, pgmconfig.DisabledPluginConfig())
writeSmallBase(th) writeSmallBase(th)
th.WriteK("/app/overlay", ` th.WriteK("/app/overlay", `
commonLabels: commonLabels:

View File

@@ -65,7 +65,7 @@ metadata:
rf := resmap.NewFactory(resource.NewFactory( rf := resmap.NewFactory(resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil) kunstruct.NewKunstructuredFactoryImpl()), nil)
pl := pLdr.NewLoader(pgmconfig.ActivePluginConfig(), rf) pl := pLdr.NewLoader(pgmconfig.EnabledPluginConfig(), rf)
tg, err := target.NewKustTarget( tg, err := target.NewKustTarget(
ldr, valtest_test.MakeFakeValidator(), rf, transformer.NewFactoryImpl(), pl) ldr, valtest_test.MakeFakeValidator(), rf, transformer.NewFactoryImpl(), pl)
if err != nil { if err != nil {

View File

@@ -36,17 +36,17 @@ type KustTestHarness struct {
func NewKustTestHarness(t *testing.T, path string) *KustTestHarness { func NewKustTestHarness(t *testing.T, path string) *KustTestHarness {
return NewKustTestHarnessFull( return NewKustTestHarnessFull(
t, path, fLdr.RestrictionRootOnly, pgmconfig.DefaultPluginConfig()) t, path, fLdr.RestrictionRootOnly, pgmconfig.DisabledPluginConfig())
} }
func NewKustTestHarnessAllowPlugins(t *testing.T, path string) *KustTestHarness { func NewKustTestHarnessAllowPlugins(t *testing.T, path string) *KustTestHarness {
return NewKustTestHarnessFull( return NewKustTestHarnessFull(
t, path, fLdr.RestrictionRootOnly, pgmconfig.ActivePluginConfig()) t, path, fLdr.RestrictionRootOnly, pgmconfig.EnabledPluginConfig())
} }
func NewKustTestHarnessNoLoadRestrictor(t *testing.T, path string) *KustTestHarness { func NewKustTestHarnessNoLoadRestrictor(t *testing.T, path string) *KustTestHarness {
return NewKustTestHarnessFull( return NewKustTestHarnessFull(
t, path, fLdr.RestrictionNone, pgmconfig.DefaultPluginConfig()) t, path, fLdr.RestrictionNone, pgmconfig.DisabledPluginConfig())
} }
func NewKustTestHarnessFull( func NewKustTestHarnessFull(

View File

@@ -15,7 +15,6 @@ import (
"sigs.k8s.io/kustomize/api/pgmconfig" "sigs.k8s.io/kustomize/api/pgmconfig"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@@ -103,12 +102,15 @@ func (o *Options) Validate(args []string) (err error) {
} }
func (o *Options) makeOptions() *krusty.Options { func (o *Options) makeOptions() *krusty.Options {
opts := krusty.MakeDefaultOptions() opts := &krusty.Options{
opts.LoadRestrictions = getFlagLoadRestrictorValue() DoLegacyResourceSort: o.outOrder == legacy,
opts.DoLegacyResourceSort = o.outOrder == legacy LoadRestrictions: getFlagLoadRestrictorValue(),
opts.PluginConfig.PluginRestrictions = types.PluginRestrictionsBuiltinsOnly DoPrune: false,
}
if isFlagEnablePluginsSet() { if isFlagEnablePluginsSet() {
opts.PluginConfig.PluginRestrictions = types.PluginRestrictionsNone opts.PluginConfig = pgmconfig.EnabledPluginConfig()
} else {
opts.PluginConfig = pgmconfig.DisabledPluginConfig()
} }
return opts return opts
} }