From 440d03617676cd3364a93c52b76d69ff4de57971 Mon Sep 17 00:00:00 2001 From: jregan Date: Thu, 4 Apr 2019 13:21:42 -0700 Subject: [PATCH] some transformer plugins --- pkg/target/kusttarget.go | 56 +++++++++++++ pkg/target/transformerplugin_test.go | 119 +++++++++++++++++++++++++++ pkg/transformers/transformer.go | 9 +- plugins/DatePrefixer.go | 30 +++++++ plugins/StringPrefixer.go | 44 ++++++++++ plugins/kvMaker.go | 24 ++++++ 6 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 pkg/target/transformerplugin_test.go create mode 100644 plugins/DatePrefixer.go create mode 100644 plugins/StringPrefixer.go create mode 100644 plugins/kvMaker.go diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index 25e5aff9e..e476cecdd 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -21,6 +21,9 @@ import ( "bytes" "encoding/json" "fmt" + "os" + "path/filepath" + "plugin" "strings" "github.com/ghodss/yaml" @@ -318,5 +321,58 @@ func (kt *KustTarget) newTransformer( return nil, err } r = append(r, t) + + tp, err := kt.loadTransformerPlugins() + if err != nil { + return nil, err + } + r = append(r, tp...) return transformers.NewMultiTransformer(r), nil } + +func (kt *KustTarget) loadTransformerPlugins() ([]transformers.Transformer, error) { + var result []transformers.Transformer + + pc := types.PluginConfig{ + DirectoryPath: os.Getenv("GOPATH"), + GoEnabled: true} + + root := filepath.Join( + pc.DirectoryPath, "src", "sigs.k8s.io", "kustomize", "plugins") + + if !pc.GoEnabled { + return nil, fmt.Errorf("plugins not enabled") + } + + transformerPluginConfigs, err := kt.rFactory.FromFiles( + kt.ldr, kt.kustomization.Transformers) + + for id, res := range transformerPluginConfigs { + fileName := filepath.Join(root, id.Gvk().Kind+".so") + goPlugin, err := plugin.Open(fileName) + if err != nil { + return nil, fmt.Errorf("plugin %s file not opened", fileName) + } + symbol, err := goPlugin.Lookup("Transformer") + if err != nil { + return nil, fmt.Errorf("plugin %s fails lookup", fileName) + } + c, ok := symbol.(transformers.Configurable) + if !ok { + return nil, fmt.Errorf("plugin %s not configurable", fileName) + } + err = c.Config(res) + if err != nil { + return nil, errors.Wrapf(err, "plugin %s fails configuration", fileName) + } + t, ok := c.(transformers.Transformer) + if !ok { + return nil, fmt.Errorf("plugin %s not a transformer", fileName) + } + + result = append(result, t) + fmt.Printf("Added plugin %s\n", fileName) + + } + return result, err +} diff --git a/pkg/target/transformerplugin_test.go b/pkg/target/transformerplugin_test.go new file mode 100644 index 000000000..9c050b0cf --- /dev/null +++ b/pkg/target/transformerplugin_test.go @@ -0,0 +1,119 @@ +/* +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. +*/ + +package target_test + +import ( + "sigs.k8s.io/kustomize/pkg/types" + "testing" +) + +func writeDeployment(th *KustTestHarness, path string) { + th.writeF(path, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myDeployment +spec: + template: + metadata: + labels: + backend: awesome + spec: + containers: + - name: whatever + image: whatever +`) +} + +func writeStringPrefixer(th *KustTestHarness, path string) { + th.writeF(path, ` +apiVersion: strings.microwoosh.com/v1 +kind: StringPrefixer +metadata: + name: myStringPrefixer +prefix: apple- +`) +} + +func writeDatePrefixer(th *KustTestHarness, path string) { + th.writeF(path, ` +apiVersion: team.dater.com/v1 +kind: DatePrefixer +metadata: + name: myDatePrefixer +`) +} + +func TestOrderedTransformers(t *testing.T) { + th := NewKustTestHarnessWithPluginConfig( + t, "/app", types.PluginConfig{GoEnabled: true}) + th.writeK("/app", ` +resources: +- deployment.yaml +transformers: +- stringPrefixer.yaml +`) + writeDeployment(th, "/app/deployment.yaml") + writeStringPrefixer(th, "/app/stringPrefixer.yaml") + writeDatePrefixer(th, "/app/datePrefixer.yaml") + m, err := th.makeKustTarget().MakeCustomizedResMap() + if err != nil { + t.Fatalf("Err: %v", err) + } + th.assertActualEqualsExpected(m, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: apple-myDeployment +spec: + template: + metadata: + labels: + backend: awesome + spec: + containers: + - image: whatever + name: whatever +`) +} + +func xTestTransformedTransformers(t *testing.T) { + th := NewKustTestHarnessWithPluginConfig( + t, "/app/overlay", types.PluginConfig{GoEnabled: true}) + + th.writeK("/app/base", ` +resources: +- stringPrefixer.yaml +transformers: +- datePrefixer.yaml +`) + writeStringPrefixer(th, "/app/base/stringPrefixer.yaml") + writeDatePrefixer(th, "/app/base/datePrefixer.yaml") + + th.writeK("/app/overlay", ` +resources: +- deployment.yaml +transformers: +- ../base +`) + writeDeployment(th, "/app/overlay/deployment.yaml") + + m, err := th.makeKustTarget().MakeCustomizedResMap() + if err != nil { + t.Fatalf("Err: %v", err) + } + th.assertActualEqualsExpected(m, ` +HEY +`) +} diff --git a/pkg/transformers/transformer.go b/pkg/transformers/transformer.go index dc6f8807c..93288646c 100644 --- a/pkg/transformers/transformer.go +++ b/pkg/transformers/transformer.go @@ -17,10 +17,17 @@ limitations under the License. // Package transformers has implementations of resmap.ResMap transformers. package transformers -import "sigs.k8s.io/kustomize/pkg/resmap" +import ( + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resmap" +) // A Transformer modifies an instance of resmap.ResMap. type Transformer interface { // Transform modifies data in the argument, e.g. adding labels to resources that can be labelled. Transform(m resmap.ResMap) error } + +type Configurable interface { + Config(k ifc.Kunstructured) error +} diff --git a/plugins/DatePrefixer.go b/plugins/DatePrefixer.go new file mode 100644 index 000000000..8f7daf93f --- /dev/null +++ b/plugins/DatePrefixer.go @@ -0,0 +1,30 @@ +// +build plugin + +package main + +import ( + "time" + + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type plugin struct{} + +var Transformer plugin + +func (p *plugin) Config(k ifc.Kunstructured) error { + return nil +} + +func (p *plugin) Transform(m resmap.ResMap) error { + tr, err := transformers.NewNamePrefixSuffixTransformer( + time.Now().Format("2006-01-02")+"-", "", + config.MakeDefaultConfig().NamePrefix) + if err != nil { + return err + } + return tr.Transform(m) +} diff --git a/plugins/StringPrefixer.go b/plugins/StringPrefixer.go new file mode 100644 index 000000000..0c8de29f9 --- /dev/null +++ b/plugins/StringPrefixer.go @@ -0,0 +1,44 @@ +// +build plugin + +// Assuming GOPATH is something like +// ~/gopath +// and this source file is located at +// $GOPATH/src/sigs.k8s.io/kustomize/plugins/StringPrefixer.go, +// build it like this: +// dir=$GOPATH/src/sigs.k8s.io/kustomize/plugins +// go build -buildmode plugin -tags=plugin \ +// -o $dir/StringPrefixer.so $dir/StringPrefixer.go + +package main + +import ( + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type plugin struct{ + prefix string +} + +var Transformer plugin + +func (p *plugin) Config(k ifc.Kunstructured) error { + var err error + p.prefix, err = k.GetFieldValue("prefix") + if err != nil { + return err + } + return nil +} + +func (p *plugin) Transform(m resmap.ResMap) error { + tr, err := transformers.NewNamePrefixSuffixTransformer( + p.prefix, "", + config.MakeDefaultConfig().NamePrefix) + if err != nil { + return err + } + return tr.Transform(m) +} diff --git a/plugins/kvMaker.go b/plugins/kvMaker.go new file mode 100644 index 000000000..2250f3e46 --- /dev/null +++ b/plugins/kvMaker.go @@ -0,0 +1,24 @@ +// +build plugin + +package main +var database = map[string]string{ + "TREE": "oak", + "ROCKET": "Saturn V", + "FRUIT": "apple", + "VEGETABLE": "carrot", + "SIMPSON": "homer", +} + +type plugin struct{} +var KVSource plugin +func (p plugin) Get( + root string, args []string) (map[string]string, error) { + r := make(map[string]string) + for _, k := range args { + v, ok := database[k] + if ok { + r[k] = v + } + } + return r, nil +}