Dogfood the plugin framework.

This PR:

* provides a code generator that converts
  kustomize Go plugins to normal code, i.e.
  the plugin appears as
    t := builtin.NewImageTagTransformer()
  instead of
    p := plugin.Open("imagetagtransformer.so")
    s := p.Lookup(someSymbol)
    t, ok = s.(Transformer)

* converts the main processing thread in
  kusttarget.go to use those factory calls to run
  builtin generators and transformer before
  calling user-supplied plugins,

* as an example, provides an imagetag transformer
  plugin, converting a legacy transformer to
  builtin plugin form with its own isolated test.
  This test can be expanded by moving more code
  into it, but that can be done in a later PR.

Writing core functionality as plugins assures a
maintained plugin authoring and testing framework,
assures modularity, provides meaningful plugin
examples, and gives us a means to make informed
choices on which kustomize packages to publish
(and which to move to internal/).  The code
generator allows all this without losing "go get
sigs.k8s.io/kustomize" functionality.

TODO:

  1) Convert remaining legacy transformers to
     plugins (patch SMP/JSON, name prefix/suffix,
     labels/annos) with their own tests.  The
     generators are already done; this PR wires
     them up, and all tests & examples pass.

  2) Push code down into the plugins, as the first
     pass at conversion writes plugins as thin
     layers over calls into code under the mess
     that is pkg/.  Once this is done, we can
     reasonably move all the packages that aren't
     imported by plugins to internal/.

This PR could be split in two, one to merge the
the generator, and the second to merge the
ImageTagTransformer plugin and its wiring into the
main flow.

The latter PR could then serve as an example for
converting the remaining transformers.
This commit is contained in:
Jeffrey Regan
2019-05-07 17:54:02 -07:00
parent c8be17c91f
commit 939de0cdbe
12 changed files with 836 additions and 34 deletions

View File

@@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
//go:generate go run sigs.k8s.io/kustomize/cmd/pluginator
package main
import (

View File

@@ -0,0 +1,56 @@
// +build plugin
/*
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.
*/
//go:generate go run sigs.k8s.io/kustomize/cmd/pluginator
package main
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/image"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/yaml"
)
// Find matching image declarations and replace
// the name, tag and/or digest.
type plugin struct {
ImageTag image.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
FieldSpecs []config.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
var KustomizePlugin plugin
func (p *plugin) Config(
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
p.ImageTag = image.Image{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *plugin) Transform(m resmap.ResMap) error {
argsList := make([]image.Image, 1)
argsList[0] = p.ImageTag
t, err := transformers.NewImageTransformer(argsList, p.FieldSpecs)
if err != nil {
return err
}
return t.Transform(m)
}

View File

@@ -0,0 +1,91 @@
/*
Copyright 2018 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 main_test
import (
"testing"
"sigs.k8s.io/kustomize/internal/plugintest"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/kusttest"
"sigs.k8s.io/kustomize/pkg/loader"
)
func TestImageTagTransformer(t *testing.T) {
tc := plugintest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"builtin", "", "ImageTagTransformer")
th := kusttest_test.NewKustTestHarnessFull(
t, "/app", loader.RestrictionRootOnly, plugin.ActivePluginConfig())
rm := th.LoadAndRunTransformer(`
apiVersion: builtin
kind: ImageTagTransformer
metadata:
name: notImportantHere
imageTag:
name: nginx
newTag: v2
`,`
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
initContainers:
- name: nginx2
image: my-nginx:1.8.0
- name: init-alpine
image: alpine:1.8.0
containers:
- name: ngnix
image: nginx:1.7.9
- name: repliaced-with-digest
image: foobar:1
- name: postgresdb
image: postgres:1.8.0
`)
th.AssertActualEqualsExpected(rm, `
apiVersion: v1
group: apps
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:v2
name: ngnix
- image: foobar:1
name: repliaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: my-nginx:1.8.0
name: nginx2
- image: alpine:1.8.0
name: init-alpine
`)
}

View File

@@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
//go:generate go run sigs.k8s.io/kustomize/cmd/pluginator
package main
import (

View File

@@ -0,0 +1,37 @@
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
package builtingen
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/yaml"
)
type ConfigMapGeneratorPlugin struct {
ldr ifc.Loader
rf *resmap.Factory
types.GeneratorOptions
types.ConfigMapArgs
}
func NewConfigMapGeneratorPlugin() *ConfigMapGeneratorPlugin {
return &ConfigMapGeneratorPlugin{}
}
func (p *ConfigMapGeneratorPlugin) Config(
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
p.ConfigMapArgs = types.ConfigMapArgs{}
err = yaml.Unmarshal(config, p)
p.ldr = ldr
p.rf = rf
return
}
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
argsList := make([]types.ConfigMapArgs, 1)
argsList[0] = p.ConfigMapArgs
return p.rf.NewResMapFromConfigMapArgs(
p.ldr, &p.GeneratorOptions, argsList)
}

View File

@@ -0,0 +1,40 @@
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
package builtingen
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/image"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/yaml"
)
// Find matching image declarations and replace
// the name, tag and/or digest.
type ImageTagTransformerPlugin struct {
ImageTag image.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
FieldSpecs []config.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func NewImageTagTransformerPlugin() *ImageTagTransformerPlugin {
return &ImageTagTransformerPlugin{}
}
func (p *ImageTagTransformerPlugin) Config(
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
p.ImageTag = image.Image{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
argsList := make([]image.Image, 1)
argsList[0] = p.ImageTag
t, err := transformers.NewImageTransformer(argsList, p.FieldSpecs)
if err != nil {
return err
}
return t.Transform(m)
}

View File

@@ -0,0 +1,37 @@
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
package builtingen
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/yaml"
)
type SecretGeneratorPlugin struct {
ldr ifc.Loader
rf *resmap.Factory
types.GeneratorOptions
types.SecretArgs
}
func NewSecretGeneratorPlugin() *SecretGeneratorPlugin {
return &SecretGeneratorPlugin{}
}
func (p *SecretGeneratorPlugin) Config(
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
p.SecretArgs = types.SecretArgs{}
err = yaml.Unmarshal(config, p)
p.ldr = ldr
p.rf = rf
return
}
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
argsList := make([]types.SecretArgs, 1)
argsList[0] = p.SecretArgs
return p.rf.NewResMapFromSecretArgs(
p.ldr, &p.GeneratorOptions, argsList)
}