Start pluglib, a set of public, plugin specific functions.

This commit is contained in:
Jeffrey Regan
2019-10-14 17:52:40 -07:00
committed by jregan
parent 2fadb4dd59
commit 41a008e9a3
78 changed files with 280 additions and 329 deletions

View File

@@ -1,18 +1,5 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package plugins
@@ -50,7 +37,6 @@ func DefaultSrcRoot() (string, error) {
os.Getenv("GOPATH"), "src",
pgmconfig.DomainName,
pgmconfig.ProgramName, pgmconfig.PluginRoot)
if FileExists(root) {
return root, nil
}

View File

@@ -13,7 +13,6 @@ import (
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/resid"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/types"
@@ -41,11 +40,8 @@ type ExecPlugin struct {
// Plugin configuration data.
cfg []byte
// resmap Factory to make resources
rf *resmap.Factory
// loader to load files
ldr ifc.Loader
// PluginHelpers
h *resmap.PluginHelpers
}
func NewExecPlugin(p string) *ExecPlugin {
@@ -61,10 +57,8 @@ func (p *ExecPlugin) isAvailable() bool {
return f.Mode()&0111 != 0000
}
func (p *ExecPlugin) Config(
ldr ifc.Loader, rf *resmap.Factory, config []byte) error {
p.rf = rf
p.ldr = ldr
func (p *ExecPlugin) Config(h *resmap.PluginHelpers, config []byte) error {
p.h = h
p.cfg = config
return p.processOptionalArgsFields()
}
@@ -81,7 +75,7 @@ func (p *ExecPlugin) processOptionalArgsFields() error {
p.args = strings.Split(c.ArgsOneLiner, " ")
}
if c.ArgsFromFile != "" {
content, err := p.ldr.Load(c.ArgsFromFile)
content, err := p.h.Loader().Load(c.ArgsFromFile)
if err != nil {
return err
}
@@ -100,7 +94,7 @@ func (p *ExecPlugin) Generate() (resmap.ResMap, error) {
if err != nil {
return nil, err
}
rm, err := p.rf.NewResMapFromBytes(output)
rm, err := p.h.ResmapFactory().NewResMapFromBytes(output)
if err != nil {
return nil, err
}
@@ -154,8 +148,8 @@ func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
cmd.Env = p.getEnv()
cmd.Stdin = bytes.NewReader(input)
cmd.Stderr = os.Stderr
if _, err := os.Stat(p.ldr.Root()); err == nil {
cmd.Dir = p.ldr.Root()
if _, err := os.Stat(p.h.Loader().Root()); err == nil {
cmd.Dir = p.h.Loader().Root()
}
result, err := cmd.Output()
if err != nil {
@@ -170,7 +164,7 @@ func (p *ExecPlugin) getEnv() []string {
env := os.Environ()
env = append(env,
"KUSTOMIZE_PLUGIN_CONFIG_STRING="+string(p.cfg),
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.ldr.Root())
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.h.Loader().Root())
return env
}
@@ -195,7 +189,7 @@ func (p *ExecPlugin) getResMapWithIdAnnotation(rm resmap.ResMap) (resmap.ResMap,
// updateResMapValues updates the Resource value in the given ResMap
// with the emitted Resource values in output.
func (p *ExecPlugin) updateResMapValues(output []byte, rm resmap.ResMap) error {
outputRM, err := p.rf.NewResMapFromBytes(output)
outputRM, err := p.h.ResmapFactory().NewResMapFromBytes(output)
if err != nil {
return err
}

View File

@@ -1,18 +1,5 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package plugins
@@ -60,7 +47,7 @@ s/$BAR/bar/g
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
p.Config(ldr, rf, yaml)
p.Config(resmap.NewPluginHelpers(ldr, rf), yaml)
expected := "/kustomize/plugin/someteam.example.com/v1/sedtransformer/SedTransformer"
if !strings.HasSuffix(p.path, expected) {

View File

@@ -123,7 +123,7 @@ func (l *Loader) loadAndConfigurePlugin(
if err != nil {
return nil, errors.Wrapf(err, "marshalling yaml from res %s", res.OrgId())
}
err = c.Config(ldr, l.rf, yaml)
err = c.Config(resmap.NewPluginHelpers(ldr, l.rf), yaml)
if err != nil {
return nil, errors.Wrapf(
err, "plugin %s fails configuration", res.OrgId())

View File

@@ -6,10 +6,11 @@ package plugins_test
import (
"testing"
"sigs.k8s.io/kustomize/v3/pluglib"
"sigs.k8s.io/kustomize/v3/internal/loadertest"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
. "sigs.k8s.io/kustomize/v3/pkg/plugins"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resource"
)
@@ -42,7 +43,7 @@ port: "12345"
)
func TestLoader(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(

View File

@@ -1,111 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package testenv
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/plugins"
)
// EnvForTest manages the plugin test environment.
// It sets/resets XDG_CONFIG_HOME, makes/removes a temp objRoot.
type EnvForTest struct {
t *testing.T
compiler *plugins.Compiler
workDir string
oldXdg string
wasSet bool
}
func NewEnvForTest(t *testing.T) *EnvForTest {
return &EnvForTest{t: t}
}
func (x *EnvForTest) Set() *EnvForTest {
x.createWorkDir()
x.compiler = x.makeCompiler()
x.setEnv()
return x
}
func (x *EnvForTest) Reset() {
x.resetEnv()
x.removeWorkDir()
}
func (x *EnvForTest) BuildGoPlugin(g, v, k string) {
err := x.compiler.Compile(g, v, k)
if err != nil {
x.t.Errorf("compile failed: %v", err)
}
}
func (x *EnvForTest) BuildExecPlugin(g, v, k string) {
lowK := strings.ToLower(k)
obj := filepath.Join(x.compiler.ObjRoot(), g, v, lowK, k)
src := filepath.Join(x.compiler.SrcRoot(), g, v, lowK, k)
if err := os.MkdirAll(filepath.Dir(obj), 0755); err != nil {
x.t.Errorf("error making directory: %s", filepath.Dir(obj))
}
cmd := exec.Command("cp", src, obj)
cmd.Env = os.Environ()
if err := cmd.Run(); err != nil {
x.t.Errorf("error copying %s to %s: %v", src, obj, err)
}
}
func (x *EnvForTest) makeCompiler() *plugins.Compiler {
// The plugin loader wants to find object code under
// $XDG_CONFIG_HOME/kustomize/plugins
// and the compiler writes object code to
// $objRoot
// so set things up accordingly.
objRoot := filepath.Join(
x.workDir, pgmconfig.ProgramName, pgmconfig.PluginRoot)
err := os.MkdirAll(objRoot, os.ModePerm)
if err != nil {
x.t.Error(err)
}
srcRoot, err := plugins.DefaultSrcRoot()
if err != nil {
x.t.Error(err)
}
return plugins.NewCompiler(srcRoot, objRoot)
}
func (x *EnvForTest) createWorkDir() {
var err error
x.workDir, err = ioutil.TempDir("", "kustomize-plugin-tests")
if err != nil {
x.t.Errorf("failed to make work dir: %v", err)
}
}
func (x *EnvForTest) removeWorkDir() {
err := os.RemoveAll(x.workDir)
if err != nil {
x.t.Errorf(
"removing work dir: %s %v", x.workDir, err)
}
}
func (x *EnvForTest) setEnv() {
x.oldXdg, x.wasSet = os.LookupEnv(pgmconfig.XdgConfigHome)
os.Setenv(pgmconfig.XdgConfigHome, x.workDir)
}
func (x *EnvForTest) resetEnv() {
if x.wasSet {
os.Setenv(pgmconfig.XdgConfigHome, x.oldXdg)
} else {
os.Unsetenv(pgmconfig.XdgConfigHome)
}
}

View File

@@ -30,14 +30,32 @@ type Generator interface {
Generate() (ResMap, error)
}
// Something that's configurable accepts a config
// object (typically YAML in []byte form), and an
// ifc.Loader to possible read more configuration
// from the file system (e.g. patch files) and
// a resource factory to build any type-sensitive
// parts. The factory could probably be factored out.
// Something that's configurable accepts an
// instance of PluginHelpers and a raw config
// object (YAML in []byte form).
type Configurable interface {
Config(ldr ifc.Loader, rf *Factory, config []byte) error
Config(h *PluginHelpers, config []byte) error
}
// NewPluginHelpers makes an instance of PluginHelpers.
func NewPluginHelpers(ldr ifc.Loader, rf *Factory) *PluginHelpers {
return &PluginHelpers{ldr: ldr, rf: rf}
}
// PluginHelpers holds things that any or all plugins might need.
// This should be available to each plugin, in addition to
// any plugin-specific configuration.
type PluginHelpers struct {
ldr ifc.Loader
rf *Factory
}
func (c *PluginHelpers) Loader() ifc.Loader {
return c.ldr
}
func (c *PluginHelpers) ResmapFactory() *Factory {
return c.rf
}
type GeneratorPlugin interface {

View File

@@ -11,8 +11,9 @@ import (
"regexp"
"testing"
"sigs.k8s.io/kustomize/v3/pluglib"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
)
// This is an example of using a helm chart as a base,
@@ -29,7 +30,7 @@ import (
// TODO: Download and inflate the chart, and check that
// in for the test.
func TestChartInflatorPlugin(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildExecPlugin(

View File

@@ -7,14 +7,14 @@ import (
"testing"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
"sigs.k8s.io/kustomize/v3/pluglib"
)
// Demo custom configuration of a builtin transformation.
// This is a NamePrefixer that only touches Deployments
// and Services.
func TestCustomNamePrefixer(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
@@ -103,7 +103,7 @@ metadata:
// Demo custom configuration as a base.
func TestReusableCustomNamePrefixer(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(

View File

@@ -10,7 +10,7 @@ import (
"testing"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
"sigs.k8s.io/kustomize/v3/pluglib"
)
const patchAddProbe = `
@@ -340,7 +340,7 @@ patchesStrategicMerge:
}
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
@@ -380,7 +380,7 @@ transformers:
}
func TestIssue1251_Plugins_Local(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
@@ -430,7 +430,7 @@ jsonOp: '%s'
// Remote in the sense that they are bundled in a different kustomization.
func TestIssue1251_Plugins_Bundled(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(

View File

@@ -4,8 +4,9 @@
package target_test
import (
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
)
func makeResourcesForPatchTest(th *kusttest_test.KustTestHarness) {

View File

@@ -377,7 +377,7 @@ func (kt *KustTarget) configureBuiltinPlugin(
err, "builtin %s marshal", bpt)
}
}
err = p.Config(kt.ldr, kt.rFactory, y)
err = p.Config(resmap.NewPluginHelpers(kt.ldr, kt.rFactory), y)
if err != nil {
return errors.Wrapf(err, "builtin %s config: %v", bpt, y)
}

View File

@@ -4,9 +4,10 @@
package target_test
import (
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"strings"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
)
func TestNamespacedSecrets(t *testing.T) {

View File

@@ -9,13 +9,14 @@ import (
"path/filepath"
"testing"
"sigs.k8s.io/kustomize/v3/pluglib"
"sigs.k8s.io/kustomize/v3/filesys"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/plugins"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/target"
@@ -23,7 +24,7 @@ import (
)
func TestPluginDir(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildExecPlugin(

View File

@@ -8,7 +8,7 @@ import (
"testing"
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
"sigs.k8s.io/kustomize/v3/pkg/plugins/testenv"
"sigs.k8s.io/kustomize/v3/pluglib"
)
func writeDeployment(th *kusttest_test.KustTestHarness, path string) {
@@ -50,7 +50,7 @@ metadata:
}
func TestOrderedTransformers(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
@@ -96,7 +96,7 @@ spec:
}
func TestPluginsNotEnabled(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
@@ -119,7 +119,7 @@ transformers:
}
func TestSedTransformer(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildExecPlugin(
@@ -187,7 +187,7 @@ metadata:
}
func TestTransformedTransformers(t *testing.T) {
tc := testenv.NewEnvForTest(t).Set()
tc := pluglib.NewEnvForTest(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(

View File

@@ -18,8 +18,9 @@ package config
import (
"reflect"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
)
func TestMergeAll(t *testing.T) {

View File

@@ -18,9 +18,10 @@ package transformers
import (
"fmt"
"testing"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"testing"
)
type noopMutator struct {

View File

@@ -18,6 +18,7 @@ package transformers
import (
"fmt"
"sigs.k8s.io/kustomize/v3/pkg/expansion"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"