mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-30 01:46:23 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa2313c282 | ||
|
|
eeed1954fb | ||
|
|
cd00ce7ab1 | ||
|
|
145d07363f | ||
|
|
33fff655db | ||
|
|
31ab347da2 | ||
|
|
7a48b2ba8e | ||
|
|
876f2a8236 |
@@ -20,6 +20,10 @@ package kunstruct
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
jsonpatch "github.com/evanphx/json-patch"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||||
@@ -285,3 +289,59 @@ func (fs *UnstructAdapter) MatchesAnnotationSelector(selector string) (bool, err
|
|||||||
}
|
}
|
||||||
return s.Matches(labels.Set(fs.GetAnnotations())), nil
|
return s.Matches(labels.Set(fs.GetAnnotations())), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs *UnstructAdapter) Patch(patch ifc.Kunstructured) error {
|
||||||
|
versionedObj, err := scheme.Scheme.New(
|
||||||
|
toSchemaGvk(patch.GetGvk()))
|
||||||
|
merged := map[string]interface{}{}
|
||||||
|
saveName := fs.GetName()
|
||||||
|
switch {
|
||||||
|
case runtime.IsNotRegisteredError(err):
|
||||||
|
baseBytes, err := json.Marshal(fs.Map())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
patchBytes, err := json.Marshal(patch.Map())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(mergedBytes, &merged)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case err != nil:
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
// Use Strategic-Merge-Patch to handle types w/ schema
|
||||||
|
// TODO: Change this to use the new Merge package.
|
||||||
|
// Store the name of the target object, because this name may have been munged.
|
||||||
|
// Apply this name to the patched object.
|
||||||
|
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
|
||||||
|
fs.Map(),
|
||||||
|
patch.Map(),
|
||||||
|
lookupPatchMeta)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.SetMap(merged)
|
||||||
|
fs.SetName(saveName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toSchemaGvk converts to a schema.GroupVersionKind.
|
||||||
|
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
|
||||||
|
return schema.GroupVersionKind{
|
||||||
|
Group: x.Group,
|
||||||
|
Version: x.Version,
|
||||||
|
Kind: x.Kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ package transformer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer/patch"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer/patch"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FactoryImpl makes patch transformer and name hash transformer
|
// FactoryImpl makes patch transformer and name hash transformer
|
||||||
@@ -18,9 +18,8 @@ func NewFactoryImpl() *FactoryImpl {
|
|||||||
return &FactoryImpl{}
|
return &FactoryImpl{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakePatchTransformer makes a new patch transformer
|
func (p *FactoryImpl) MergePatches(patches []*resource.Resource,
|
||||||
func (p *FactoryImpl) MakePatchTransformer(
|
rf *resource.Factory) (
|
||||||
slice []*resource.Resource,
|
resmap.ResMap, error) {
|
||||||
rf *resource.Factory) (transformers.Transformer, error) {
|
return patch.MergePatches(patches, rf)
|
||||||
return patch.NewTransformer(slice, rf)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ package patch
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
|
|
||||||
"github.com/evanphx/json-patch"
|
"github.com/evanphx/json-patch"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -122,3 +127,64 @@ func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource)
|
|||||||
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
|
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
|
||||||
return smp.rf.FromMap(mergeJSONMap), err
|
return smp.rf.FromMap(mergeJSONMap), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergePatches merge and index patches by OrgId.
|
||||||
|
// It errors out if there is conflict between patches.
|
||||||
|
func MergePatches(patches []*resource.Resource,
|
||||||
|
rf *resource.Factory) (resmap.ResMap, error) {
|
||||||
|
rc := resmap.New()
|
||||||
|
for ix, patch := range patches {
|
||||||
|
id := patch.OrgId()
|
||||||
|
existing := rc.GetMatchingResourcesByOriginalId(id.GvknEquals)
|
||||||
|
if len(existing) == 0 {
|
||||||
|
rc.Append(patch)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(existing) > 1 {
|
||||||
|
return nil, fmt.Errorf("self conflict in patches")
|
||||||
|
}
|
||||||
|
|
||||||
|
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk))
|
||||||
|
if err != nil && !runtime.IsNotRegisteredError(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var cd conflictDetector
|
||||||
|
if err != nil {
|
||||||
|
cd = newJMPConflictDetector(rf)
|
||||||
|
} else {
|
||||||
|
cd, err = newSMPConflictDetector(versionedObj, rf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conflict, err := cd.hasConflict(existing[0], patch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if conflict {
|
||||||
|
conflictingPatch, err := cd.findConflict(ix, patches)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"conflict between %#v and %#v",
|
||||||
|
conflictingPatch.Map(), patch.Map())
|
||||||
|
}
|
||||||
|
merged, err := cd.mergePatches(existing[0], patch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rc.Replace(merged)
|
||||||
|
}
|
||||||
|
return rc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toSchemaGvk converts to a schema.GroupVersionKind.
|
||||||
|
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
|
||||||
|
return schema.GroupVersionKind{
|
||||||
|
Group: x.Group,
|
||||||
|
Version: x.Version,
|
||||||
|
Kind: x.Kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package patch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/evanphx/json-patch"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// transformer applies strategic merge patches.
|
|
||||||
type transformer struct {
|
|
||||||
patches []*resource.Resource
|
|
||||||
rf *resource.Factory
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ transformers.Transformer = &transformer{}
|
|
||||||
|
|
||||||
// NewTransformer constructs a strategic merge patch transformer.
|
|
||||||
func NewTransformer(
|
|
||||||
slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) {
|
|
||||||
if len(slice) == 0 {
|
|
||||||
return transformers.NewNoOpTransformer(), nil
|
|
||||||
}
|
|
||||||
return &transformer{patches: slice, rf: rf}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform apply the patches on top of the base resources.
|
|
||||||
// nolint:ineffassign
|
|
||||||
func (tf *transformer) Transform(m resmap.ResMap) error {
|
|
||||||
patches, err := tf.mergePatches()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, patch := range patches.Resources() {
|
|
||||||
target, err := m.GetById(patch.OrgId())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
merged := map[string]interface{}{}
|
|
||||||
versionedObj, err := scheme.Scheme.New(
|
|
||||||
toSchemaGvk(patch.OrgId().Gvk))
|
|
||||||
saveName := target.GetName()
|
|
||||||
switch {
|
|
||||||
case runtime.IsNotRegisteredError(err):
|
|
||||||
// Use JSON merge patch to handle types w/o schema
|
|
||||||
baseBytes, err := json.Marshal(target.Map())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
patchBytes, err := json.Marshal(patch.Map())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(mergedBytes, &merged)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case err != nil:
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
// Use Strategic-Merge-Patch to handle types w/ schema
|
|
||||||
// TODO: Change this to use the new Merge package.
|
|
||||||
// Store the name of the target object, because this name may have been munged.
|
|
||||||
// Apply this name to the patched object.
|
|
||||||
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
|
|
||||||
target.Map(),
|
|
||||||
patch.Map(),
|
|
||||||
lookupPatchMeta)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.SetMap(merged)
|
|
||||||
target.SetName(saveName)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mergePatches merge and index patches by OrgId.
|
|
||||||
// It errors out if there is conflict between patches.
|
|
||||||
func (tf *transformer) mergePatches() (resmap.ResMap, error) {
|
|
||||||
rc := resmap.New()
|
|
||||||
for ix, patch := range tf.patches {
|
|
||||||
id := patch.OrgId()
|
|
||||||
existing := rc.GetMatchingResourcesByOriginalId(id.GvknEquals)
|
|
||||||
if len(existing) == 0 {
|
|
||||||
rc.Append(patch)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(existing) > 1 {
|
|
||||||
return nil, fmt.Errorf("self conflict in patches")
|
|
||||||
}
|
|
||||||
|
|
||||||
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk))
|
|
||||||
if err != nil && !runtime.IsNotRegisteredError(err) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var cd conflictDetector
|
|
||||||
if err != nil {
|
|
||||||
cd = newJMPConflictDetector(tf.rf)
|
|
||||||
} else {
|
|
||||||
cd, err = newSMPConflictDetector(versionedObj, tf.rf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conflict, err := cd.hasConflict(existing[0], patch)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if conflict {
|
|
||||||
conflictingPatch, err := cd.findConflict(ix, tf.patches)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"conflict between %#v and %#v",
|
|
||||||
conflictingPatch.Map(), patch.Map())
|
|
||||||
}
|
|
||||||
merged, err := cd.mergePatches(existing[0], patch)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rc.Replace(merged)
|
|
||||||
}
|
|
||||||
return rc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// toSchemaGvk converts to a schema.GroupVersionKind.
|
|
||||||
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
|
|
||||||
return schema.GroupVersionKind{
|
|
||||||
Group: x.Group,
|
|
||||||
Version: x.Version,
|
|
||||||
Kind: x.Kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,579 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package patch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
|
||||||
)
|
|
||||||
|
|
||||||
var rf = resource.NewFactory(
|
|
||||||
kunstruct.NewKunstructuredFactoryImpl())
|
|
||||||
|
|
||||||
func TestOverlayRun(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"labels": map[string]interface{}{
|
|
||||||
"old-label": "old-value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"labels": map[string]interface{}{
|
|
||||||
"another-label": "foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:latest",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "SOMEENV",
|
|
||||||
"value": "BAR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"labels": map[string]interface{}{
|
|
||||||
"old-label": "old-value",
|
|
||||||
"another-label": "foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:latest",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "SOMEENV",
|
|
||||||
"value": "BAR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(base, expected) {
|
|
||||||
err = expected.ErrorIfNotEqualLists(base)
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultiplePatches(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:latest",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "SOMEENV",
|
|
||||||
"value": "BAR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "ANOTHERENV",
|
|
||||||
"value": "HELLO",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "busybox",
|
|
||||||
"image": "busybox",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:latest",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "ANOTHERENV",
|
|
||||||
"value": "HELLO",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "SOMEENV",
|
|
||||||
"value": "BAR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "busybox",
|
|
||||||
"image": "busybox",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(base, expected) {
|
|
||||||
err = expected.ErrorIfNotEqualLists(base)
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultiplePatchesWithConflict(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:latest",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "SOMEENV",
|
|
||||||
"value": "BAR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:1.7.9",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("did not get expected error")
|
|
||||||
}
|
|
||||||
if !strings.Contains(err.Error(), "conflict") {
|
|
||||||
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPatchesWithWrongNamespace(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
"namespace": "namespace1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
"namespace": "namespace2",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:1.7.9",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("did not get expected error")
|
|
||||||
}
|
|
||||||
if !strings.Contains(err.Error(), "failed to find unique target for patch") {
|
|
||||||
t.Fatalf("expected error to contain %q but get %v", "failed to find target for patch", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoSchemaOverlayRun(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"A": "X",
|
|
||||||
"B": "Y",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"B": nil,
|
|
||||||
"C": "Z",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"A": "X",
|
|
||||||
"C": "Z",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if err = expected.ErrorIfNotEqualLists(base); err != nil {
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoSchemaMultiplePatches(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"A": "X",
|
|
||||||
"B": "Y",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"B": nil,
|
|
||||||
"C": "Z",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"C": "Z",
|
|
||||||
"D": "W",
|
|
||||||
},
|
|
||||||
"baz": map[string]interface{}{
|
|
||||||
"hello": "world",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"A": "X",
|
|
||||||
"C": "Z",
|
|
||||||
"D": "W",
|
|
||||||
},
|
|
||||||
"baz": map[string]interface{}{
|
|
||||||
"hello": "world",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if err = expected.ErrorIfNotEqualLists(base); err != nil {
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
|
|
||||||
base := resmaptest_test.NewRmBuilder(t, rf).
|
|
||||||
Add(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"A": "X",
|
|
||||||
"B": "Y",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).ResMap()
|
|
||||||
patch := []*resource.Resource{
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"B": nil,
|
|
||||||
"C": "Z",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "example.com/v1",
|
|
||||||
"kind": "Foo",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "my-foo",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"bar": map[string]interface{}{
|
|
||||||
"C": "NOT_Z",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
lt, err := NewTransformer(patch, rf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
err = lt.Transform(base)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("did not get expected error")
|
|
||||||
}
|
|
||||||
if !strings.Contains(err.Error(), "conflict") {
|
|
||||||
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc/transformer"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
@@ -61,7 +60,7 @@ https://github.com/hashicorp/go-getter#url-format
|
|||||||
func NewCmdBuild(
|
func NewCmdBuild(
|
||||||
out io.Writer, fSys fs.FileSystem,
|
out io.Writer, fSys fs.FileSystem,
|
||||||
v ifc.Validator, rf *resmap.Factory,
|
v ifc.Validator, rf *resmap.Factory,
|
||||||
ptf transformer.Factory) *cobra.Command {
|
ptf resmap.PatchFactory) *cobra.Command {
|
||||||
var o Options
|
var o Options
|
||||||
|
|
||||||
pluginConfig := plugins.DefaultPluginConfig()
|
pluginConfig := plugins.DefaultPluginConfig()
|
||||||
@@ -115,7 +114,7 @@ func (o *Options) Validate(args []string) (err error) {
|
|||||||
// RunBuild runs build command.
|
// RunBuild runs build command.
|
||||||
func (o *Options) RunBuild(
|
func (o *Options) RunBuild(
|
||||||
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
||||||
rf *resmap.Factory, ptf transformer.Factory,
|
rf *resmap.Factory, ptf resmap.PatchFactory,
|
||||||
pl *plugins.Loader) error {
|
pl *plugins.Loader) error {
|
||||||
ldr, err := loader.NewLoader(
|
ldr, err := loader.NewLoader(
|
||||||
o.loadRestrictor, v, o.kustomizationPath, fSys)
|
o.loadRestrictor, v, o.kustomizationPath, fSys)
|
||||||
@@ -136,7 +135,7 @@ func (o *Options) RunBuild(
|
|||||||
|
|
||||||
func (o *Options) RunBuildPrune(
|
func (o *Options) RunBuildPrune(
|
||||||
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
||||||
rf *resmap.Factory, ptf transformer.Factory,
|
rf *resmap.Factory, ptf resmap.PatchFactory,
|
||||||
pl *plugins.Loader) error {
|
pl *plugins.Loader) error {
|
||||||
ldr, err := loader.NewLoader(
|
ldr, err := loader.NewLoader(
|
||||||
o.loadRestrictor, v, o.kustomizationPath, fSys)
|
o.loadRestrictor, v, o.kustomizationPath, fSys)
|
||||||
@@ -180,7 +179,7 @@ func (o *Options) emitResources(
|
|||||||
|
|
||||||
func NewCmdBuildPrune(
|
func NewCmdBuildPrune(
|
||||||
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
out io.Writer, v ifc.Validator, fSys fs.FileSystem,
|
||||||
rf *resmap.Factory, ptf transformer.Factory,
|
rf *resmap.Factory, ptf resmap.PatchFactory,
|
||||||
pl *plugins.Loader) *cobra.Command {
|
pl *plugins.Loader) *cobra.Command {
|
||||||
var o Options
|
var o Options
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,13 @@ See https://sigs.k8s.io/kustomize
|
|||||||
}
|
}
|
||||||
|
|
||||||
uf := kunstruct.NewKunstructuredFactoryImpl()
|
uf := kunstruct.NewKunstructuredFactoryImpl()
|
||||||
rf := resmap.NewFactory(resource.NewFactory(uf))
|
pf := transformer.NewFactoryImpl()
|
||||||
|
rf := resmap.NewFactory(resource.NewFactory(uf), pf)
|
||||||
v := validator.NewKustValidator()
|
v := validator.NewKustValidator()
|
||||||
c.AddCommand(
|
c.AddCommand(
|
||||||
build.NewCmdBuild(
|
build.NewCmdBuild(
|
||||||
stdOut, fSys, v,
|
stdOut, fSys, v,
|
||||||
rf, transformer.NewFactoryImpl()),
|
rf, pf),
|
||||||
edit.NewCmdEdit(fSys, v, uf),
|
edit.NewCmdEdit(fSys, v, uf),
|
||||||
misc.NewCmdConfig(fSys),
|
misc.NewCmdConfig(fSys),
|
||||||
misc.NewCmdVersion(stdOut),
|
misc.NewCmdVersion(stdOut),
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ type Kunstructured interface {
|
|||||||
SetAnnotations(map[string]string)
|
SetAnnotations(map[string]string)
|
||||||
MatchesLabelSelector(selector string) (bool, error)
|
MatchesLabelSelector(selector string) (bool, error)
|
||||||
MatchesAnnotationSelector(selector string) (bool, error)
|
MatchesAnnotationSelector(selector string) (bool, error)
|
||||||
|
Patch(Kunstructured) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// KunstructuredFactory makes instances of Kunstructured.
|
// KunstructuredFactory makes instances of Kunstructured.
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
/// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Package patch holds miscellaneous interfaces used by kustomize.
|
|
||||||
package transformer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Factory makes transformers that require k8sdeps.
|
|
||||||
type Factory interface {
|
|
||||||
MakePatchTransformer(
|
|
||||||
slice []*resource.Resource,
|
|
||||||
rf *resource.Factory) (transformers.Transformer, error)
|
|
||||||
}
|
|
||||||
@@ -49,7 +49,7 @@ func NewKustTestHarnessFull(
|
|||||||
t *testing.T, path string,
|
t *testing.T, path string,
|
||||||
lr loader.LoadRestrictorFunc, pc *types.PluginConfig) *KustTestHarness {
|
lr loader.LoadRestrictorFunc, pc *types.PluginConfig) *KustTestHarness {
|
||||||
rf := resmap.NewFactory(resource.NewFactory(
|
rf := resmap.NewFactory(resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()))
|
kunstruct.NewKunstructuredFactoryImpl()), transformer.NewFactoryImpl())
|
||||||
return &KustTestHarness{
|
return &KustTestHarness{
|
||||||
t: t,
|
t: t,
|
||||||
rf: rf,
|
rf: rf,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func TestExecPluginConfig(t *testing.T) {
|
|||||||
path := "/app"
|
path := "/app"
|
||||||
rf := resmap.NewFactory(
|
rf := resmap.NewFactory(
|
||||||
resource.NewFactory(
|
resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()))
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
ldr := loadertest.NewFakeLoader(path)
|
ldr := loadertest.NewFakeLoader(path)
|
||||||
pluginConfig := rf.RF().FromMap(
|
pluginConfig := rf.RF().FromMap(
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func TestLoader(t *testing.T) {
|
|||||||
"someteam.example.com", "v1", "SomeServiceGenerator")
|
"someteam.example.com", "v1", "SomeServiceGenerator")
|
||||||
|
|
||||||
rmF := resmap.NewFactory(resource.NewFactory(
|
rmF := resmap.NewFactory(resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()))
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
|
||||||
l := NewLoader(ActivePluginConfig(), rmF)
|
l := NewLoader(ActivePluginConfig(), rmF)
|
||||||
if l == nil {
|
if l == nil {
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import (
|
|||||||
// Factory makes instances of ResMap.
|
// Factory makes instances of ResMap.
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
resF *resource.Factory
|
resF *resource.Factory
|
||||||
|
tf PatchFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactory returns a new resmap.Factory.
|
// NewFactory returns a new resmap.Factory.
|
||||||
func NewFactory(rf *resource.Factory) *Factory {
|
func NewFactory(rf *resource.Factory, tf PatchFactory) *Factory {
|
||||||
return &Factory{resF: rf}
|
return &Factory{resF: rf, tf: tf}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RF returns a resource.Factory.
|
// RF returns a resource.Factory.
|
||||||
@@ -118,6 +119,11 @@ func (rmF *Factory) FromSecretArgs(
|
|||||||
return rmF.FromResource(res), nil
|
return rmF.FromResource(res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rmF *Factory) MergePatches(patches []*resource.Resource) (
|
||||||
|
ResMap, error) {
|
||||||
|
return rmF.tf.MergePatches(patches, rmF.resF)
|
||||||
|
}
|
||||||
|
|
||||||
func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) {
|
func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) {
|
||||||
result := New()
|
result := New()
|
||||||
for _, res := range resources {
|
for _, res := range resources {
|
||||||
|
|||||||
15
pkg/resmap/patchfactory.go
Normal file
15
pkg/resmap/patchfactory.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package patch holds miscellaneous interfaces used by kustomize.
|
||||||
|
package resmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PatchFactory makes transformers that require k8sdeps.
|
||||||
|
type PatchFactory interface {
|
||||||
|
MergePatches(patches []*resource.Resource,
|
||||||
|
rf *resource.Factory) (ResMap, error)
|
||||||
|
}
|
||||||
@@ -530,7 +530,20 @@ func (m *resWrangler) SubsetThatCouldBeReferencedByResource(
|
|||||||
inputRes *resource.Resource) ResMap {
|
inputRes *resource.Resource) ResMap {
|
||||||
inputId := inputRes.OrgId()
|
inputId := inputRes.OrgId()
|
||||||
if !inputId.IsNamespaceableKind() {
|
if !inputId.IsNamespaceableKind() {
|
||||||
return m
|
if inputRes.GetOutermostNamePrefix() == "" {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
result := New()
|
||||||
|
for _, r := range m.Resources() {
|
||||||
|
if r.GetOutermostNamePrefix() == inputRes.GetOutermostNamePrefix() &&
|
||||||
|
r.GetOutermostNameSuffix() == inputRes.GetOutermostNameSuffix() {
|
||||||
|
err := result.Append(r)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
result := New()
|
result := New()
|
||||||
for _, r := range m.Resources() {
|
for _, r := range m.Resources() {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
var rf = resource.NewFactory(
|
var rf = resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl())
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
var rmF = NewFactory(rf)
|
var rmF = NewFactory(rf, nil)
|
||||||
|
|
||||||
func doAppend(t *testing.T, w ResMap, r *resource.Resource) {
|
func doAppend(t *testing.T, w ResMap, r *resource.Resource) {
|
||||||
err := w.Append(r)
|
err := w.Append(r)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/accumulator"
|
"sigs.k8s.io/kustomize/v3/pkg/accumulator"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc/transformer"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
@@ -30,7 +29,7 @@ type KustTarget struct {
|
|||||||
kustomization *types.Kustomization
|
kustomization *types.Kustomization
|
||||||
ldr ifc.Loader
|
ldr ifc.Loader
|
||||||
rFactory *resmap.Factory
|
rFactory *resmap.Factory
|
||||||
tFactory transformer.Factory
|
tFactory resmap.PatchFactory
|
||||||
pLdr *plugins.Loader
|
pLdr *plugins.Loader
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ type KustTarget struct {
|
|||||||
func NewKustTarget(
|
func NewKustTarget(
|
||||||
ldr ifc.Loader,
|
ldr ifc.Loader,
|
||||||
rFactory *resmap.Factory,
|
rFactory *resmap.Factory,
|
||||||
tFactory transformer.Factory,
|
tFactory resmap.PatchFactory,
|
||||||
pLdr *plugins.Loader) (*KustTarget, error) {
|
pLdr *plugins.Loader) (*KustTarget, error) {
|
||||||
content, err := loadKustFile(ldr)
|
content, err := loadKustFile(ldr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -293,19 +292,7 @@ func (kt *KustTarget) configureExternalGenerators() ([]transformers.Generator, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
||||||
patches, err := kt.rFactory.RF().SliceFromPatches(
|
|
||||||
kt.ldr, kt.kustomization.PatchesStrategicMerge)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(
|
|
||||||
err, "reading strategic merge patches %v",
|
|
||||||
kt.kustomization.PatchesStrategicMerge)
|
|
||||||
}
|
|
||||||
var r []transformers.Transformer
|
var r []transformers.Transformer
|
||||||
t, err := kt.tFactory.MakePatchTransformer(patches, kt.rFactory.RF())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r = append(r, t)
|
|
||||||
tConfig := ra.GetTransformerConfig()
|
tConfig := ra.GetTransformerConfig()
|
||||||
lts, err := kt.configureBuiltinTransformers(tConfig)
|
lts, err := kt.configureBuiltinTransformers(tConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -317,7 +304,7 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r = append(r, lts...)
|
r = append(r, lts...)
|
||||||
t = transformers.NewMultiTransformer(r)
|
t := transformers.NewMultiTransformer(r)
|
||||||
return ra.Transform(t)
|
return ra.Transform(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func (kt *KustTarget) configureBuiltinTransformers(
|
|||||||
// with tests:
|
// with tests:
|
||||||
// - patch SMP
|
// - patch SMP
|
||||||
configurators := []transformerConfigurator{
|
configurators := []transformerConfigurator{
|
||||||
|
kt.configureBuiltinPatchStrategicMergeTransformer,
|
||||||
kt.configureBuiltinNamespaceTransformer,
|
kt.configureBuiltinNamespaceTransformer,
|
||||||
kt.configureBuiltinNameTransformer,
|
kt.configureBuiltinNameTransformer,
|
||||||
kt.configureBuiltinLabelTransformer,
|
kt.configureBuiltinLabelTransformer,
|
||||||
@@ -165,6 +166,28 @@ func (kt *KustTarget) configureBuiltinPatchJson6902Transformer(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) configureBuiltinPatchStrategicMergeTransformer(
|
||||||
|
tConfig *config.TransformerConfig) (
|
||||||
|
result []transformers.Transformer, err error) {
|
||||||
|
if len(kt.kustomization.PatchesStrategicMerge) == 0 {
|
||||||
|
result = append(result, transformers.NewNoOpTransformer())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c struct {
|
||||||
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
|
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
}
|
||||||
|
c.Paths = kt.kustomization.PatchesStrategicMerge
|
||||||
|
c.Patches = "" // Not implemented for kustomization file yet
|
||||||
|
p := builtin.NewPatchStrategicMergeTransformerPlugin()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, "patchStrategicMerge")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) configureBuiltinLabelTransformer(
|
func (kt *KustTarget) configureBuiltinLabelTransformer(
|
||||||
tConfig *config.TransformerConfig) (
|
tConfig *config.TransformerConfig) (
|
||||||
result []transformers.Transformer, err error) {
|
result []transformers.Transformer, err error) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ metadata:
|
|||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
rf := resmap.NewFactory(resource.NewFactory(
|
rf := resmap.NewFactory(resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()))
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
|
||||||
pl := plugins.NewLoader(plugins.ActivePluginConfig(), rf)
|
pl := plugins.NewLoader(plugins.ActivePluginConfig(), rf)
|
||||||
tg, err := target.NewKustTarget(ldr, rf, transformer.NewFactoryImpl(), pl)
|
tg, err := target.NewKustTarget(ldr, rf, transformer.NewFactoryImpl(), pl)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ func writeBase(th *kusttest_test.KustTestHarness) {
|
|||||||
resources:
|
resources:
|
||||||
- serviceaccount.yaml
|
- serviceaccount.yaml
|
||||||
- rolebinding.yaml
|
- rolebinding.yaml
|
||||||
|
- clusterrolebinding.yaml
|
||||||
namePrefix: pfx-
|
namePrefix: pfx-
|
||||||
nameSuffix: -sfx
|
nameSuffix: -sfx
|
||||||
`)
|
`)
|
||||||
@@ -34,6 +35,19 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: role
|
name: role
|
||||||
subjects:
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: serviceaccount
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/base/clusterrolebinding.yaml", `
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: serviceaccount
|
name: serviceaccount
|
||||||
`)
|
`)
|
||||||
@@ -86,6 +100,18 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: role
|
name: role
|
||||||
subjects:
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: pfx-serviceaccount-sfx
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: pfx-rolebinding-sfx
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: pfx-serviceaccount-sfx
|
name: pfx-serviceaccount-sfx
|
||||||
`)
|
`)
|
||||||
@@ -114,6 +140,18 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: role
|
name: role
|
||||||
subjects:
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: a-pfx-serviceaccount-sfx-suffixA
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: a-pfx-rolebinding-sfx-suffixA
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: a-pfx-serviceaccount-sfx-suffixA
|
name: a-pfx-serviceaccount-sfx-suffixA
|
||||||
`)
|
`)
|
||||||
@@ -142,6 +180,18 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: role
|
name: role
|
||||||
subjects:
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: b-pfx-serviceaccount-sfx-suffixB
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: b-pfx-rolebinding-sfx-suffixB
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: b-pfx-serviceaccount-sfx-suffixB
|
name: b-pfx-serviceaccount-sfx-suffixB
|
||||||
`)
|
`)
|
||||||
@@ -174,6 +224,18 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: a-pfx-serviceaccount-sfx-suffixA
|
name: a-pfx-serviceaccount-sfx-suffixA
|
||||||
---
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: a-pfx-rolebinding-sfx-suffixA
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: a-pfx-serviceaccount-sfx-suffixA
|
||||||
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
@@ -188,6 +250,18 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: role
|
name: role
|
||||||
subjects:
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: b-pfx-serviceaccount-sfx-suffixB
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: b-pfx-rolebinding-sfx-suffixB
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: role
|
||||||
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: b-pfx-serviceaccount-sfx-suffixB
|
name: b-pfx-serviceaccount-sfx-suffixB
|
||||||
`)
|
`)
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ nameReference:
|
|||||||
- path: spec/initContainers/envFrom/configMapRef/name
|
- path: spec/initContainers/envFrom/configMapRef/name
|
||||||
version: v1
|
version: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
|
- path: spec/volumes/projected/sources/configMap/name
|
||||||
|
version: v1
|
||||||
|
kind: Pod
|
||||||
- path: spec/template/spec/volumes/configMap/name
|
- path: spec/template/spec/volumes/configMap/name
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
||||||
@@ -74,6 +77,8 @@ nameReference:
|
|||||||
kind: ReplicaSet
|
kind: ReplicaSet
|
||||||
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
||||||
kind: ReplicaSet
|
kind: ReplicaSet
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/configMap/name
|
||||||
|
kind: ReplicaSet
|
||||||
- path: spec/template/spec/volumes/configMap/name
|
- path: spec/template/spec/volumes/configMap/name
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
||||||
@@ -84,6 +89,8 @@ nameReference:
|
|||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/configMap/name
|
||||||
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/volumes/configMap/name
|
- path: spec/template/spec/volumes/configMap/name
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
||||||
@@ -106,6 +113,8 @@ nameReference:
|
|||||||
kind: Job
|
kind: Job
|
||||||
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
|
||||||
kind: Job
|
kind: Job
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/configMap/name
|
||||||
|
kind: Job
|
||||||
- path: spec/jobTemplate/spec/template/spec/volumes/configMap/name
|
- path: spec/jobTemplate/spec/template/spec/volumes/configMap/name
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/configMap/name
|
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/configMap/name
|
||||||
@@ -140,6 +149,9 @@ nameReference:
|
|||||||
- path: spec/imagePullSecrets/name
|
- path: spec/imagePullSecrets/name
|
||||||
version: v1
|
version: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
|
- path: spec/volumes/projected/sources/secret/name
|
||||||
|
version: v1
|
||||||
|
kind: Pod
|
||||||
- path: spec/template/spec/volumes/secret/secretName
|
- path: spec/template/spec/volumes/secret/secretName
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||||
@@ -166,6 +178,8 @@ nameReference:
|
|||||||
kind: ReplicaSet
|
kind: ReplicaSet
|
||||||
- path: spec/template/spec/imagePullSecrets/name
|
- path: spec/template/spec/imagePullSecrets/name
|
||||||
kind: ReplicaSet
|
kind: ReplicaSet
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/secret/name
|
||||||
|
kind: ReplicaSet
|
||||||
- path: spec/template/spec/volumes/secret/secretName
|
- path: spec/template/spec/volumes/secret/secretName
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||||
@@ -178,6 +192,8 @@ nameReference:
|
|||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/imagePullSecrets/name
|
- path: spec/template/spec/imagePullSecrets/name
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/secret/name
|
||||||
|
kind: DaemonSet
|
||||||
- path: spec/template/spec/volumes/secret/secretName
|
- path: spec/template/spec/volumes/secret/secretName
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||||
@@ -204,6 +220,8 @@ nameReference:
|
|||||||
kind: Job
|
kind: Job
|
||||||
- path: spec/template/spec/imagePullSecrets/name
|
- path: spec/template/spec/imagePullSecrets/name
|
||||||
kind: Job
|
kind: Job
|
||||||
|
- path: spec/template/spec/volumes/projected/sources/secret/name
|
||||||
|
kind: Job
|
||||||
- path: spec/jobTemplate/spec/template/spec/volumes/secret/secretName
|
- path: spec/jobTemplate/spec/template/spec/volumes/secret/secretName
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/secret/name
|
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/secret/name
|
||||||
|
|||||||
75
plugin/builtin/PatchStrategicMergeTransformer.go
Normal file
75
plugin/builtin/PatchStrategicMergeTransformer.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Code generated by pluginator on PatchStrategicMergeTransformer; DO NOT EDIT.
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PatchStrategicMergeTransformerPlugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
loadedPatches []*resource.Resource
|
||||||
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
|
Patches string `json:patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection GoUnusedGlobalVariable
|
||||||
|
func NewPatchStrategicMergeTransformerPlugin() *PatchStrategicMergeTransformerPlugin {
|
||||||
|
return &PatchStrategicMergeTransformerPlugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchStrategicMergeTransformerPlugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(p.Paths) == 0 && p.Patches == "" {
|
||||||
|
return fmt.Errorf("empty file path and empty patch content")
|
||||||
|
}
|
||||||
|
if len(p.Paths) != 0 {
|
||||||
|
res, err := p.rf.RF().SliceFromPatches(ldr, p.Paths)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = res
|
||||||
|
}
|
||||||
|
if p.Patches != "" {
|
||||||
|
res, err := p.rf.RF().SliceFromBytes([]byte(p.Patches))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = append(p.loadedPatches, res...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.loadedPatches) == 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
patches, err := p.rf.MergePatches(p.loadedPatches)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, patch := range patches.Resources() {
|
||||||
|
target, err := m.GetById(patch.OrgId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = target.Patch(patch.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
//go:generate go run sigs.k8s.io/kustomize/v3/cmd/pluginator
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type plugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
loadedPatches []*resource.Resource
|
||||||
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
|
Patches string `json:patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection GoUnusedGlobalVariable
|
||||||
|
var KustomizePlugin plugin
|
||||||
|
|
||||||
|
func (p *plugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(p.Paths) == 0 && p.Patches == "" {
|
||||||
|
return fmt.Errorf("empty file path and empty patch content")
|
||||||
|
}
|
||||||
|
if len(p.Paths) != 0 {
|
||||||
|
res, err := p.rf.RF().SliceFromPatches(ldr, p.Paths)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = res
|
||||||
|
}
|
||||||
|
if p.Patches != "" {
|
||||||
|
res, err := p.rf.RF().SliceFromBytes([]byte(p.Patches))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = append(p.loadedPatches, res...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.loadedPatches) == 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) Transform(m resmap.ResMap) error {
|
||||||
|
patches, err := p.rf.MergePatches(p.loadedPatches)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, patch := range patches.Resources() {
|
||||||
|
target, err := m.GetById(patch.OrgId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = target.Patch(patch.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,535 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
target = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
replica: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
`
|
||||||
|
targetWithNamespace = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
namespace: namespace1
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
replica: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
`
|
||||||
|
targetNoschema = `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
A: X
|
||||||
|
B: Y
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPatchStrategicMergeTransformerMissingFile(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch.yaml
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"cannot read file \"/app/patch.yaml\"") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBadPatchStrategicMergeTransformer(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
patches: 'thisIsNotAPatch'
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"cannot unmarshal string into Go value of type map[string]interface {}") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBothEmptyPatchStrategicMergeTransformer(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "empty file path and empty patch content") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchStrategicMergeTransformerFromFiles(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
replica: 3
|
||||||
|
`)
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch.yaml
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchStrategicMergeTransformerWithInline(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
patches: '{"apiVersion": "apps/v1", "metadata": {"name": "myDeploy"}, "kind": "Deployment", "spec": {"replica": 3}}'
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchStrategicMergeTransformerMultiplePatches(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch1.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:latest
|
||||||
|
env:
|
||||||
|
- name: SOMEENV
|
||||||
|
value: BAR
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteF("/app/patch2.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
env:
|
||||||
|
- name: ANOTHERENV
|
||||||
|
value: HELLO
|
||||||
|
- name: busybox
|
||||||
|
image: busybox
|
||||||
|
`)
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch1.yaml
|
||||||
|
- patch2.yaml
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: ANOTHERENV
|
||||||
|
value: HELLO
|
||||||
|
- name: SOMEENV
|
||||||
|
value: BAR
|
||||||
|
image: nginx:latest
|
||||||
|
name: nginx
|
||||||
|
- image: busybox
|
||||||
|
name: busybox
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergeTransformerMultiplePatchesWithConflicts(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch1.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:latest
|
||||||
|
env:
|
||||||
|
- name: SOMEENV
|
||||||
|
value: BAR
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteF("/app/patch2.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9
|
||||||
|
env:
|
||||||
|
- name: ANOTHERENV
|
||||||
|
value: HELLO
|
||||||
|
- name: busybox
|
||||||
|
image: busybox
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := th.ErrorFromLoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch1.yaml
|
||||||
|
- patch2.yaml
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("did not get expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "conflict") {
|
||||||
|
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergeTransformerWrongNamespace(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
namespace: namespace2
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:latest
|
||||||
|
env:
|
||||||
|
- name: SOMEENV
|
||||||
|
value: BAR
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := th.ErrorFromLoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch.yaml
|
||||||
|
`, targetWithNamespace)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("did not get expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "failed to find unique target for patch") {
|
||||||
|
t.Fatalf("expected error to contain %q but get %v", "failed to find target for patch", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergeTransformerNoSchema(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch.yaml", `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
B:
|
||||||
|
C: Z
|
||||||
|
`)
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch.yaml
|
||||||
|
`, targetNoschema)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
A: X
|
||||||
|
C: Z
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergeTransformerNoSchemaMultiPatches(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch1.yaml", `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
B:
|
||||||
|
C: Z
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/patch2.yaml", `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
C: Z
|
||||||
|
D: W
|
||||||
|
baz:
|
||||||
|
hello: world
|
||||||
|
`)
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch1.yaml
|
||||||
|
- patch2.yaml
|
||||||
|
`, targetNoschema)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
A: X
|
||||||
|
C: Z
|
||||||
|
D: W
|
||||||
|
baz:
|
||||||
|
hello: world
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergeTransformerNoSchemaMultiPatchesWithConflict(t *testing.T) {
|
||||||
|
tc := plugins.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchStrategicMergeTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch1.yaml", `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
C: Z
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/patch2.yaml", `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: my-foo
|
||||||
|
spec:
|
||||||
|
bar:
|
||||||
|
C: NOT_Z
|
||||||
|
|
||||||
|
`)
|
||||||
|
err := th.ErrorFromLoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchStrategicMergeTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
paths:
|
||||||
|
- patch1.yaml
|
||||||
|
- patch2.yaml
|
||||||
|
`, targetNoschema)
|
||||||
|
if !strings.Contains(err.Error(), "conflict") {
|
||||||
|
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user