mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 01:50:55 +00:00
Do no require exec/go plugin home to use fn plugins
This commit is contained in:
@@ -45,10 +45,12 @@ s/$BAR/bar baz/g
|
|||||||
})
|
})
|
||||||
|
|
||||||
pluginConfig.RemoveBuildAnnotations()
|
pluginConfig.RemoveBuildAnnotations()
|
||||||
p := NewExecPlugin(
|
loader := pLdr.NewLoader(konfig.DisabledPluginConfig(), rf)
|
||||||
pLdr.AbsolutePluginPath(
|
pluginPath, err := loader.AbsolutePluginPath(pluginConfig.OrgId())
|
||||||
konfig.DisabledPluginConfig(),
|
if err != nil {
|
||||||
pluginConfig.OrgId()))
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
p := NewExecPlugin(pluginPath)
|
||||||
// Not checking to see if the plugin is executable,
|
// Not checking to see if the plugin is executable,
|
||||||
// because this test does not run it.
|
// because this test does not run it.
|
||||||
// This tests only covers sending configuration
|
// This tests only covers sending configuration
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
@@ -29,6 +30,10 @@ import (
|
|||||||
type Loader struct {
|
type Loader struct {
|
||||||
pc *types.PluginConfig
|
pc *types.PluginConfig
|
||||||
rf *resmap.Factory
|
rf *resmap.Factory
|
||||||
|
|
||||||
|
// absolutePluginHome caches the location of a valid plugin root directory.
|
||||||
|
// It should only be set once the directory's existence has been confirmed.
|
||||||
|
absolutePluginHome string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLoader(
|
func NewLoader(
|
||||||
@@ -95,13 +100,47 @@ func relativePluginPath(id resid.ResId) string {
|
|||||||
strings.ToLower(id.Kind))
|
strings.ToLower(id.Kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
func AbsolutePluginPath(pc *types.PluginConfig, id resid.ResId) string {
|
func (l *Loader) AbsolutePluginPath(id resid.ResId) (string, error) {
|
||||||
return filepath.Join(
|
pluginHome, err := l.absPluginHome()
|
||||||
pc.AbsPluginHome, relativePluginPath(id), id.Kind)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(pluginHome, relativePluginPath(id), id.Kind), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loader) absolutePluginPath(id resid.ResId) string {
|
// absPluginHome is the home of kustomize Exec and Go plugins.
|
||||||
return AbsolutePluginPath(l.pc, id)
|
// Kustomize plugin configuration files are k8s-style objects
|
||||||
|
// containing the fields 'apiVersion' and 'kind', e.g.
|
||||||
|
// apiVersion: apps/v1
|
||||||
|
// kind: Deployment
|
||||||
|
// kustomize reads plugin configuration data from a file path
|
||||||
|
// specified in the 'generators:' or 'transformers:' field of a
|
||||||
|
// kustomization file. For Exec and Go plugins, kustomize
|
||||||
|
// uses this data to both locate the plugin and configure it.
|
||||||
|
// Each Exec or Go plugin (its code, its tests, its supporting data
|
||||||
|
// files, etc.) must be housed in its own directory at
|
||||||
|
// ${absPluginHome}/${pluginApiVersion}/LOWERCASE(${pluginKind})
|
||||||
|
// where
|
||||||
|
// - ${absPluginHome} is an absolute path, defined below.
|
||||||
|
// - ${pluginApiVersion} is taken from the plugin config file.
|
||||||
|
// - ${pluginKind} is taken from the plugin config file.
|
||||||
|
func (l *Loader) absPluginHome() (string, error) {
|
||||||
|
// External plugins are disabled--return the dummy plugin root.
|
||||||
|
if l.pc.PluginRestrictions != types.PluginRestrictionsNone {
|
||||||
|
return konfig.NoPluginHomeSentinal, nil
|
||||||
|
}
|
||||||
|
// We've already determined plugin home--use the cached value.
|
||||||
|
if l.absolutePluginHome != "" {
|
||||||
|
return l.absolutePluginHome, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check default locations for a valid plugin root, and cache it if found.
|
||||||
|
dir, err := konfig.DefaultAbsPluginHome(filesys.MakeFsOnDisk())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
l.absolutePluginHome = dir
|
||||||
|
return l.absolutePluginHome, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBuiltinPlugin(res *resource.Resource) bool {
|
func isBuiltinPlugin(res *resource.Resource) bool {
|
||||||
@@ -176,10 +215,13 @@ func (l *Loader) loadPlugin(res *resource.Resource) (resmap.Configurable, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, error) {
|
func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, error) {
|
||||||
|
absPluginPath, err := l.AbsolutePluginPath(resId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// First try to load the plugin as an executable.
|
// First try to load the plugin as an executable.
|
||||||
p := execplugin.NewExecPlugin(l.absolutePluginPath(resId))
|
p := execplugin.NewExecPlugin(absPluginPath)
|
||||||
err := p.ErrIfNotExecutable()
|
if err = p.ErrIfNotExecutable(); err == nil {
|
||||||
if err == nil {
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
@@ -193,7 +235,7 @@ func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Failing the above, try loading it as a Go plugin.
|
// Failing the above, try loading it as a Go plugin.
|
||||||
c, err := l.loadGoPlugin(resId)
|
c, err := l.loadGoPlugin(resId, absPluginPath+".so")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -208,12 +250,11 @@ func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, err
|
|||||||
// as a Loader instance variable. So make it a package variable.
|
// as a Loader instance variable. So make it a package variable.
|
||||||
var registry = make(map[string]resmap.Configurable)
|
var registry = make(map[string]resmap.Configurable)
|
||||||
|
|
||||||
func (l *Loader) loadGoPlugin(id resid.ResId) (resmap.Configurable, error) {
|
func (l *Loader) loadGoPlugin(id resid.ResId, absPath string) (resmap.Configurable, error) {
|
||||||
regId := relativePluginPath(id)
|
regId := relativePluginPath(id)
|
||||||
if c, ok := registry[regId]; ok {
|
if c, ok := registry[regId]; ok {
|
||||||
return copyPlugin(c), nil
|
return copyPlugin(c), nil
|
||||||
}
|
}
|
||||||
absPath := l.absolutePluginPath(id) + ".so"
|
|
||||||
if !utils.FileExists(absPath) {
|
if !utils.FileExists(absPath) {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"expected file with Go object code at: %s", absPath)
|
"expected file with Go object code at: %s", absPath)
|
||||||
|
|||||||
@@ -66,10 +66,7 @@ func TestLoader(t *testing.T) {
|
|||||||
for _, behavior := range []types.BuiltinPluginLoadingOptions{
|
for _, behavior := range []types.BuiltinPluginLoadingOptions{
|
||||||
/* types.BploUseStaticallyLinked,
|
/* types.BploUseStaticallyLinked,
|
||||||
types.BploLoadFromFileSys */} {
|
types.BploLoadFromFileSys */} {
|
||||||
c, err := konfig.EnabledPluginConfig(behavior)
|
c := konfig.EnabledPluginConfig(behavior)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
pLdr := NewLoader(c, rmF)
|
pLdr := NewLoader(c, rmF)
|
||||||
if pLdr == nil {
|
if pLdr == nil {
|
||||||
t.Fatal("expect non-nil loader")
|
t.Fatal("expect non-nil loader")
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func GoBin() string {
|
|||||||
// has her ${g}/${v}/$lower(${k})/${k}.go files.
|
// has her ${g}/${v}/$lower(${k})/${k}.go files.
|
||||||
func DeterminePluginSrcRoot(fSys filesys.FileSystem) (string, error) {
|
func DeterminePluginSrcRoot(fSys filesys.FileSystem) (string, error) {
|
||||||
return konfig.FirstDirThatExistsElseError(
|
return konfig.FirstDirThatExistsElseError(
|
||||||
"source directory", fSys, []konfig.NotedFunc{
|
"plugin src root", fSys, []konfig.NotedFunc{
|
||||||
{
|
{
|
||||||
Note: "relative to unit test",
|
Note: "relative to unit test",
|
||||||
F: func() string {
|
F: func() string {
|
||||||
|
|||||||
@@ -41,28 +41,20 @@ const (
|
|||||||
NoPluginHomeSentinal = "/No/non-builtin/plugins!"
|
NoPluginHomeSentinal = "/No/non-builtin/plugins!"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EnabledPluginConfig(b types.BuiltinPluginLoadingOptions) (*types.PluginConfig, error) {
|
func EnabledPluginConfig(b types.BuiltinPluginLoadingOptions) *types.PluginConfig {
|
||||||
dir, err := DefaultAbsPluginHome(filesys.MakeFsOnDisk())
|
return MakePluginConfig(types.PluginRestrictionsNone, b)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return MakePluginConfig(types.PluginRestrictionsNone, b, dir), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DisabledPluginConfig() *types.PluginConfig {
|
func DisabledPluginConfig() *types.PluginConfig {
|
||||||
return MakePluginConfig(
|
return MakePluginConfig(
|
||||||
types.PluginRestrictionsBuiltinsOnly,
|
types.PluginRestrictionsBuiltinsOnly,
|
||||||
types.BploUseStaticallyLinked,
|
types.BploUseStaticallyLinked)
|
||||||
NoPluginHomeSentinal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakePluginConfig(
|
func MakePluginConfig(pr types.PluginRestrictions,
|
||||||
pr types.PluginRestrictions,
|
b types.BuiltinPluginLoadingOptions) *types.PluginConfig {
|
||||||
b types.BuiltinPluginLoadingOptions,
|
|
||||||
home string) *types.PluginConfig {
|
|
||||||
return &types.PluginConfig{
|
return &types.PluginConfig{
|
||||||
PluginRestrictions: pr,
|
PluginRestrictions: pr,
|
||||||
AbsPluginHome: home,
|
|
||||||
BpLoadingOptions: b,
|
BpLoadingOptions: b,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +69,7 @@ type NotedFunc struct {
|
|||||||
// the home of kustomize plugins.
|
// the home of kustomize plugins.
|
||||||
func DefaultAbsPluginHome(fSys filesys.FileSystem) (string, error) {
|
func DefaultAbsPluginHome(fSys filesys.FileSystem) (string, error) {
|
||||||
return FirstDirThatExistsElseError(
|
return FirstDirThatExistsElseError(
|
||||||
"plugin home directory", fSys, []NotedFunc{
|
"plugin root", fSys, []NotedFunc{
|
||||||
{
|
{
|
||||||
Note: "homed in $" + KustomizePluginHomeEnv,
|
Note: "homed in $" + KustomizePluginHomeEnv,
|
||||||
F: func() string {
|
F: func() string {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestFnExecGenerator(t *testing.T) {
|
func TestFnExecGenerator(t *testing.T) {
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
defer th.Reset()
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
resources:
|
resources:
|
||||||
@@ -92,8 +92,8 @@ func skipIfNoDocker(t *testing.T) {
|
|||||||
func TestFnContainerGenerator(t *testing.T) {
|
func TestFnContainerGenerator(t *testing.T) {
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
defer th.Reset()
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
resources:
|
resources:
|
||||||
@@ -308,8 +308,8 @@ spec:
|
|||||||
func TestFnContainerTransformer(t *testing.T) {
|
func TestFnContainerTransformer(t *testing.T) {
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
defer th.Reset()
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
resources:
|
resources:
|
||||||
@@ -408,8 +408,8 @@ spec:
|
|||||||
func TestFnContainerTransformerWithConfig(t *testing.T) {
|
func TestFnContainerTransformerWithConfig(t *testing.T) {
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
defer th.Reset()
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
resources:
|
resources:
|
||||||
@@ -468,8 +468,8 @@ metadata:
|
|||||||
func TestFnContainerEnvVars(t *testing.T) {
|
func TestFnContainerEnvVars(t *testing.T) {
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
defer th.Reset()
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
generators:
|
generators:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package kusttest_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
@@ -77,15 +76,7 @@ func (th Harness) MakeOptionsPluginsDisabled() krusty.Options {
|
|||||||
|
|
||||||
// Enables use of non-builtin plugins.
|
// Enables use of non-builtin plugins.
|
||||||
func (th Harness) MakeOptionsPluginsEnabled() krusty.Options {
|
func (th Harness) MakeOptionsPluginsEnabled() krusty.Options {
|
||||||
pc, err := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
|
pc := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "unable to find plugin root") {
|
|
||||||
th.t.Log(
|
|
||||||
"Tests that want to run with plugins enabled must be " +
|
|
||||||
"bookended by calls to MakeEnhancedHarness(), Reset().")
|
|
||||||
}
|
|
||||||
th.t.Fatal(err)
|
|
||||||
}
|
|
||||||
o := *krusty.MakeDefaultOptions()
|
o := *krusty.MakeDefaultOptions()
|
||||||
o.PluginConfig = pc
|
o.PluginConfig = pc
|
||||||
return o
|
return o
|
||||||
|
|||||||
@@ -40,11 +40,8 @@ type HarnessEnhanced struct {
|
|||||||
func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
|
func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
|
||||||
pte := newPluginTestEnv(t).set()
|
pte := newPluginTestEnv(t).set()
|
||||||
|
|
||||||
pc, err := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
|
pc := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
|
||||||
pc.FnpLoadingOptions.EnableStar = true
|
pc.FnpLoadingOptions.EnableStar = true
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
p := provider.NewDefaultDepProvider()
|
p := provider.NewDefaultDepProvider()
|
||||||
resourceFactory := p.GetResourceFactory()
|
resourceFactory := p.GetResourceFactory()
|
||||||
resmapFactory := resmap.NewFactory(resourceFactory)
|
resmapFactory := resmap.NewFactory(resourceFactory)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func (e *errUnableToFind) Error() string {
|
|||||||
m = append(m, "('"+p.Value+"'; "+p.Key+")")
|
m = append(m, "('"+p.Value+"'; "+p.Key+")")
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"unable to find plugin root - tried: %s", strings.Join(m, ", "))
|
"unable to find %s - tried: %s", e.what, strings.Join(m, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewErrUnableToFind(w string, a []Pair) *errUnableToFind {
|
func NewErrUnableToFind(w string, a []Pair) *errUnableToFind {
|
||||||
|
|||||||
@@ -5,25 +5,6 @@ package types
|
|||||||
|
|
||||||
// PluginConfig holds plugin configuration.
|
// PluginConfig holds plugin configuration.
|
||||||
type PluginConfig struct {
|
type PluginConfig struct {
|
||||||
// AbsPluginHome is the home of kustomize plugins.
|
|
||||||
// Kustomize plugin configuration files are k8s-style objects
|
|
||||||
// containing the fields 'apiVersion' and 'kind', e.g.
|
|
||||||
// apiVersion: apps/v1
|
|
||||||
// kind: Deployment
|
|
||||||
// kustomize reads plugin configuration data from a file path
|
|
||||||
// specified in the 'generators:' or 'transformers:' field of a
|
|
||||||
// kustomization file. kustomize must then use this data to both
|
|
||||||
// locate the plugin and configure it.
|
|
||||||
// Every kustomize plugin (its code, its tests, its supporting data
|
|
||||||
// files, etc.) must be housed in its own directory at
|
|
||||||
// ${AbsPluginHome}/${pluginApiVersion}/LOWERCASE(${pluginKind})
|
|
||||||
// where
|
|
||||||
// - ${AbsPluginHome} is an absolute path, defined below.
|
|
||||||
// - ${pluginApiVersion} is taken from the plugin config file.
|
|
||||||
// - ${pluginKind} is taken from the plugin config file.
|
|
||||||
// The value of AbsPluginHome can be any absolute path.
|
|
||||||
AbsPluginHome string
|
|
||||||
|
|
||||||
// PluginRestrictions distinguishes plugin restrictions.
|
// PluginRestrictions distinguishes plugin restrictions.
|
||||||
PluginRestrictions PluginRestrictions
|
PluginRestrictions PluginRestrictions
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package build
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
@@ -130,10 +129,7 @@ func HonorKustomizeFlags(kOpts *krusty.Options) *krusty.Options {
|
|||||||
kOpts.DoLegacyResourceSort = getFlagReorderOutput() == legacy
|
kOpts.DoLegacyResourceSort = getFlagReorderOutput() == legacy
|
||||||
kOpts.LoadRestrictions = getFlagLoadRestrictorValue()
|
kOpts.LoadRestrictions = getFlagLoadRestrictorValue()
|
||||||
if theFlags.enable.plugins {
|
if theFlags.enable.plugins {
|
||||||
c, err := konfig.EnabledPluginConfig(types.BploUseStaticallyLinked)
|
c := konfig.EnabledPluginConfig(types.BploUseStaticallyLinked)
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
c.FnpLoadingOptions = theFlags.fnOptions
|
c.FnpLoadingOptions = theFlags.fnOptions
|
||||||
kOpts.PluginConfig = c
|
kOpts.PluginConfig = c
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user