add replacement transformer

This commit is contained in:
Natasha Sarkar
2021-04-14 16:08:50 -07:00
parent 0df531e7c6
commit 038bc7713b
14 changed files with 916 additions and 3 deletions

View File

@@ -0,0 +1,65 @@
// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/replacement"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/yaml"
)
// Replace values in targets with values from a source
type ReplacementTransformerPlugin struct {
ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"`
}
func (p *ReplacementTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.ReplacementList = []types.ReplacementField{}
if err := yaml.Unmarshal(c, p); err != nil {
return err
}
for _, r := range p.ReplacementList {
if r.Path != "" && (r.Source != nil || len(r.Targets) != 0) {
return fmt.Errorf("cannot specify both path and inline replacement")
}
if r.Path != "" {
// load the replacement from the path
content, err := h.Loader().Load(r.Path)
if err != nil {
return err
}
repl := types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl)
} else {
// replacement information is already loaded
p.Replacements = append(p.Replacements, r.Replacement)
}
}
return nil
}
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
var nodes []*kyaml.RNode
for _, r := range m.Resources() {
nodes = append(nodes, r.Node())
}
_, err = replacement.Filter{
Replacements: p.Replacements,
}.Filter(nodes)
return err
}
func NewReplacementTransformerPlugin() resmap.TransformerPlugin {
return &ReplacementTransformerPlugin{}
}

View File

@@ -13,7 +13,7 @@ import (
)
type Filter struct {
Replacements []types.Replacement
Replacements []types.Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"`
}
// Filter replaces values of targets with values from sources

View File

@@ -24,11 +24,12 @@ func _() {
_ = x[SecretGenerator-13]
_ = x[ValueAddTransformer-14]
_ = x[HelmChartInflationGenerator-15]
_ = x[ReplacementTransformer-16]
}
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGenerator"
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer"
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316}
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316, 338}
func (i BuiltinPluginType) String() string {
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {

View File

@@ -28,6 +28,7 @@ const (
SecretGenerator
ValueAddTransformer
HelmChartInflationGenerator
ReplacementTransformer
)
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
@@ -72,6 +73,7 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
PatchStrategicMergeTransformer: builtins.NewPatchStrategicMergeTransformerPlugin,
PatchTransformer: builtins.NewPatchTransformerPlugin,
PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin,
ReplacementTransformer: builtins.NewReplacementTransformerPlugin,
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
ValueAddTransformer: builtins.NewValueAddTransformerPlugin,
}

View File

@@ -57,6 +57,7 @@ func (kt *KustTarget) configureBuiltinTransformers(
builtinhelpers.PatchJson6902Transformer,
builtinhelpers.ReplicaCountTransformer,
builtinhelpers.ImageTagTransformer,
builtinhelpers.ReplacementTransformer,
} {
r, err := transformerConfigurators[bpt](
kt, bpt, builtinhelpers.TransformerFactories[bpt], tc)
@@ -323,6 +324,21 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
}
return
},
builtinhelpers.ReplacementTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
var c struct {
Replacements []types.ReplacementField
}
c.Replacements = kt.kustomization.Replacements
p := f()
err = kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
return nil, err
}
result = append(result, p)
return result, nil
},
builtinhelpers.ReplicaCountTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {

View File

@@ -0,0 +1,271 @@
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// end to end tests to demonstrate functionality of ReplacementTransformer
func TestReplacementsField(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK(".", `
resources:
- resource.yaml
replacements:
- source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image
`)
th.WriteF("resource.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
expected := `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}
func TestReplacementsFieldWithPath(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK(".", `
resources:
- resource.yaml
replacements:
- path: replacement.yaml
`)
th.WriteF("replacement.yaml",
`
source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image
`)
th.WriteF("resource.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
expected := `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}
func TestReplacementTransformerWithDiamondShape(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/deployment.yaml",
`
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
`)
th.WriteF("base/kustomization.yaml",
`
resources:
- deployment.yaml
`)
th.WriteF("a/kustomization.yaml",
`
namePrefix: a-
resources:
- ../base
replacements:
- path: replacement.yaml
`)
th.WriteF("a/replacement.yaml",
`
source:
name: a-sourceA
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
name: a-deploy
fieldPaths:
- spec.template.spec.containers.[name=nginx].image
`)
th.WriteF("b/kustomization.yaml",
`
namePrefix: b-
resources:
- ../base
replacements:
- path: replacement.yaml
`)
th.WriteF("b/replacement.yaml",
`
source:
name: b-sourceB
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
name: b-deploy
fieldPaths:
- spec.template.spec.containers.[name=nginx].image
`)
th.WriteF("combined/kustomization.yaml",
`
resources:
- ../a
- ../b
`)
m := th.Run("combined", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-deploy
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-deploy
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
`)
}

View File

@@ -57,6 +57,10 @@ func (r *Resource) AsRNode() *kyaml.RNode {
return r.node.Copy()
}
func (r *Resource) Node() *kyaml.RNode {
return r.node
}
func (r *Resource) ResetPrimaryData(incoming *Resource) {
r.node = incoming.node.Copy()
}

View File

@@ -74,6 +74,10 @@ type Kustomization struct {
// patch, but this operator is simpler to specify.
Images []Image `json:"images,omitempty" yaml:"images,omitempty"`
// Replacements is a list of replacements, which will copy nodes from a
// specified source to N specified targets.
Replacements []ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
// Replicas is a list of {resourcename, count} that allows for simpler replica
// specification. This can also be done with a patch.
Replicas []Replica `json:"replicas,omitempty" yaml:"replicas,omitempty"`

View File

@@ -0,0 +1,6 @@
package types
type ReplacementField struct {
Replacement `json:",inline,omitempty" yaml:",inline,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
}