From 4eb275784758d7d23918bffab487a46897df08b2 Mon Sep 17 00:00:00 2001 From: jregan Date: Sat, 6 Oct 2018 10:44:34 -0700 Subject: [PATCH] Further isolate unstructured with factories. --- internal/k8sdeps/kunstructuredfactory.go | 60 +++++++++ internal/k8sdeps/kunstructuredfactory_test.go | 124 ++++++++++++++++++ internal/k8sdeps/unstructadapter.go | 46 +++---- internal/k8sdeps/unstructadapter_test.go | 123 +++-------------- kustomize.go | 1 + pkg/commands/build/build.go | 9 +- pkg/commands/build/build_test.go | 5 +- pkg/commands/commands.go | 5 +- pkg/ifc/ifc.go | 6 + pkg/patch/transformer/factory_test.go | 10 +- .../transformer/patchjson6902json_test.go | 7 +- pkg/resmap/configmap.go | 8 +- pkg/resmap/configmap_test.go | 11 +- pkg/resmap/resmap.go | 32 +++-- pkg/resmap/resmap_test.go | 62 ++++----- pkg/resmap/secret.go | 6 +- pkg/resmap/secret_test.go | 9 +- pkg/resource/resource.go | 59 +++++---- pkg/resource/resource_test.go | 15 ++- pkg/target/kusttarget.go | 25 ++-- pkg/target/kusttarget_test.go | 17 ++- pkg/transformers/imagetag_test.go | 14 +- pkg/transformers/labelsandannotations_test.go | 43 +++--- pkg/transformers/multitransformer.go | 4 +- pkg/transformers/namehash_test.go | 18 +-- pkg/transformers/namereference_test.go | 23 ++-- pkg/transformers/namespace_test.go | 31 +++-- pkg/transformers/patch.go | 10 +- pkg/transformers/patch_test.go | 55 ++++---- pkg/transformers/patchconflictdetector.go | 20 ++- pkg/transformers/prefixname_test.go | 15 ++- 31 files changed, 525 insertions(+), 348 deletions(-) create mode 100644 internal/k8sdeps/kunstructuredfactory.go create mode 100644 internal/k8sdeps/kunstructuredfactory_test.go diff --git a/internal/k8sdeps/kunstructuredfactory.go b/internal/k8sdeps/kunstructuredfactory.go new file mode 100644 index 000000000..d39322075 --- /dev/null +++ b/internal/k8sdeps/kunstructuredfactory.go @@ -0,0 +1,60 @@ +/* +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 k8sdeps + +import ( + "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// KustKunstructuredFactory hides construction using apimachinery types. +type KustKunstructuredFactory struct { + decoder ifc.Decoder +} + +var _ ifc.KunstructuredFactory = &KustKunstructuredFactory{} + +// NewKustKunstructuredFactory returns a factory. +func NewKustKunstructuredFactory(d ifc.Decoder) ifc.KunstructuredFactory { + return &KustKunstructuredFactory{decoder: d} +} + +// SliceFromBytes returns a slice of Kunstructured. +func (kf *KustKunstructuredFactory) SliceFromBytes( + in []byte) ([]ifc.Kunstructured, error) { + kf.decoder.SetInput(in) + var result []ifc.Kunstructured + var err error + for err == nil || isEmptyYamlError(err) { + var out unstructured.Unstructured + err = kf.decoder.Decode(&out) + if err == nil { + result = append(result, &UnstructAdapter{Unstructured: out}) + } + } + if err != io.EOF { + return nil, err + } + return result, nil +} + +// FromMap returns an instance of Kunstructured. +func (kf *KustKunstructuredFactory) FromMap( + m map[string]interface{}) ifc.Kunstructured { + return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}} +} diff --git a/internal/k8sdeps/kunstructuredfactory_test.go b/internal/k8sdeps/kunstructuredfactory_test.go new file mode 100644 index 000000000..5e77a1e7e --- /dev/null +++ b/internal/k8sdeps/kunstructuredfactory_test.go @@ -0,0 +1,124 @@ +/* +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 k8sdeps + +import ( + "reflect" + "testing" + + "sigs.k8s.io/kustomize/pkg/ifc" +) + +func TestSliceFromBytes(t *testing.T) { + factory := NewKustKunstructuredFactory(NewKustDecoder()) + testConfigMap := factory.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "winnie", + }, + }) + + tests := []struct { + name string + input []byte + expectedOut []ifc.Kunstructured + expectedErr bool + }{ + { + name: "garbage", + input: []byte("garbageIn: garbageOut"), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + { + name: "noBytes", + input: []byte{}, + expectedOut: []ifc.Kunstructured{}, + expectedErr: false, + }, + { + name: "goodJson", + input: []byte(` +{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}} +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml1", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml2", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap}, + expectedErr: false, + }, + { + name: "garbageInOneOfTwoObjects", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +WOOOOOOOOOOOOOOOOOOOOOOOOT: woot +`), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + } + + for _, test := range tests { + rs, err := factory.SliceFromBytes(test.input) + if test.expectedErr && err == nil { + t.Fatalf("%v: should return error", test.name) + } + if !test.expectedErr && err != nil { + t.Fatalf("%v: unexpected error: %s", test.name, err) + } + if len(rs) != len(test.expectedOut) { + t.Fatalf("%s: length mismatch %d != %d", + test.name, len(rs), len(test.expectedOut)) + } + for i := range rs { + if !reflect.DeepEqual(test.expectedOut[i], rs[i]) { + t.Fatalf("%s: Got: %v\nexpected:%v", + test.name, test.expectedOut[i], rs[i]) + } + } + } +} diff --git a/internal/k8sdeps/unstructadapter.go b/internal/k8sdeps/unstructadapter.go index 11e4a3fd9..d0605c1b7 100644 --- a/internal/k8sdeps/unstructadapter.go +++ b/internal/k8sdeps/unstructadapter.go @@ -1,9 +1,24 @@ +/* +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 k8sdeps import ( "encoding/json" "fmt" - "io" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,35 +52,6 @@ func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) { return &UnstructAdapter{Unstructured: u}, err } -// NewKunstructuredFromMap returns a new instance of Kunstructured. -func NewKunstructuredFromMap(m map[string]interface{}) ifc.Kunstructured { - return NewKunstructuredFromUnstruct(unstructured.Unstructured{Object: m}) -} - -// NewKunstructuredFromUnstruct returns a new instance of Kunstructured. -func NewKunstructuredFromUnstruct(u unstructured.Unstructured) ifc.Kunstructured { - return &UnstructAdapter{Unstructured: u} -} - -// NewKunstructuredSliceFromBytes unmarshalls bytes into a Kunstructured slice. -func NewKunstructuredSliceFromBytes( - in []byte, decoder ifc.Decoder) ([]ifc.Kunstructured, error) { - decoder.SetInput(in) - var result []ifc.Kunstructured - var err error - for err == nil || isEmptyYamlError(err) { - var out unstructured.Unstructured - err = decoder.Decode(&out) - if err == nil { - result = append(result, &UnstructAdapter{Unstructured: out}) - } - } - if err != io.EOF { - return nil, err - } - return result, nil -} - // GetGvk returns the Gvk name of the object. func (fs *UnstructAdapter) GetGvk() gvk.Gvk { return gvk.FromSchemaGvk(fs.GroupVersionKind()) diff --git a/internal/k8sdeps/unstructadapter_test.go b/internal/k8sdeps/unstructadapter_test.go index dabb4e409..e9cf685c0 100644 --- a/internal/k8sdeps/unstructadapter_test.go +++ b/internal/k8sdeps/unstructadapter_test.go @@ -1,113 +1,28 @@ +/* +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 k8sdeps import ( - "reflect" - "sigs.k8s.io/kustomize/pkg/ifc" "testing" ) -var testConfigMap = NewKunstructuredFromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "winnie", - }, - }) - -func TestNewKunstructuredSliceFromBytes(t *testing.T) { - tests := []struct { - name string - input []byte - expectedOut []ifc.Kunstructured - expectedErr bool - }{ - { - name: "garbage", - input: []byte("garbageIn: garbageOut"), - expectedOut: []ifc.Kunstructured{}, - expectedErr: true, - }, - { - name: "noBytes", - input: []byte{}, - expectedOut: []ifc.Kunstructured{}, - expectedErr: false, - }, - { - name: "goodJson", - input: []byte(` -{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}} -`), - expectedOut: []ifc.Kunstructured{testConfigMap}, - expectedErr: false, - }, - { - name: "goodYaml1", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie -`), - expectedOut: []ifc.Kunstructured{testConfigMap}, - expectedErr: false, - }, - { - name: "goodYaml2", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie -`), - expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap}, - expectedErr: false, - }, - { - name: "garbageInOneOfTwoObjects", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie ---- -WOOOOOOOOOOOOOOOOOOOOOOOOT: woot -`), - expectedOut: []ifc.Kunstructured{}, - expectedErr: true, - }, - } - - for _, test := range tests { - rs, err := NewKunstructuredSliceFromBytes( - test.input, NewKustDecoder()) - if test.expectedErr && err == nil { - t.Fatalf("%v: should return error", test.name) - } - if !test.expectedErr && err != nil { - t.Fatalf("%v: unexpected error: %s", test.name, err) - } - if len(rs) != len(test.expectedOut) { - t.Fatalf("%s: length mismatch %d != %d", - test.name, len(rs), len(test.expectedOut)) - } - for i := range rs { - if !reflect.DeepEqual(test.expectedOut[i], rs[i]) { - t.Fatalf("%s: Got: %v\nexpected:%v", - test.name, test.expectedOut[i], rs[i]) - } - } - } -} - func TestGetFieldValue(t *testing.T) { - funStruct := NewKunstructuredFromMap(map[string]interface{}{ + factory := NewKustKunstructuredFactory(NewKustDecoder()) + kunstructured := factory.FromMap(map[string]interface{}{ "Kind": "Service", "metadata": map[string]interface{}{ "labels": map[string]string{ @@ -150,7 +65,7 @@ func TestGetFieldValue(t *testing.T) { } for _, test := range tests { - s, err := funStruct.GetFieldValue(test.pathToField) + s, err := kunstructured.GetFieldValue(test.pathToField) if test.errorExpected && err == nil { t.Fatalf("should return error, but no error returned") } else { diff --git a/kustomize.go b/kustomize.go index 4e2da5e85..8720e01e8 100644 --- a/kustomize.go +++ b/kustomize.go @@ -28,6 +28,7 @@ func main() { defer glog.Flush() if err := commands.NewDefaultCommand( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()), k8sdeps.NewKustDecoder(), k8sdeps.NewKustValidator(), k8sdeps.NewKustHash()).Execute(); err != nil { diff --git a/pkg/commands/build/build.go b/pkg/commands/build/build.go index 854edb7f9..f9b43cafc 100644 --- a/pkg/commands/build/build.go +++ b/pkg/commands/build/build.go @@ -20,13 +20,15 @@ import ( "errors" "io" "log" - "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resmap" "strings" "github.com/spf13/cobra" "sigs.k8s.io/kustomize/pkg/constants" "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/loader" + "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/target" "sigs.k8s.io/kustomize/pkg/transformerconfig" ) @@ -60,6 +62,7 @@ Use different transformer configurations by passing files to kustomize // NewCmdBuild creates a new build command. func NewCmdBuild( out io.Writer, fs fs.FileSystem, + kf ifc.KunstructuredFactory, decoder ifc.Decoder, hash ifc.Hash) *cobra.Command { var o buildOptions var p string @@ -74,7 +77,7 @@ func NewCmdBuild( if err != nil { return err } - return o.RunBuild(out, fs, decoder, hash) + return o.RunBuild(out, fs, kf, decoder, hash) }, } cmd.Flags().StringVarP( @@ -119,6 +122,7 @@ func (o *buildOptions) Validate(args []string, p string, fs fs.FileSystem) error // RunBuild runs build command. func (o *buildOptions) RunBuild( out io.Writer, fSys fs.FileSystem, + kf ifc.KunstructuredFactory, decoder ifc.Decoder, hash ifc.Hash) error { rootLoader, err := loader.NewLoader(o.kustomizationPath, "", fSys) if err != nil { @@ -127,6 +131,7 @@ func (o *buildOptions) RunBuild( defer rootLoader.Cleanup() kt, err := target.NewKustTarget( rootLoader, fSys, + resmap.NewFactory(resource.NewFactory(kf)), makeTransformerconfig(fSys, o.transformerconfigPaths), decoder, hash) if err != nil { diff --git a/pkg/commands/build/build_test.go b/pkg/commands/build/build_test.go index 7458fc8fe..0c0f95e78 100644 --- a/pkg/commands/build/build_test.go +++ b/pkg/commands/build/build_test.go @@ -128,7 +128,10 @@ func runBuildTestCase(t *testing.T, testcaseName string, updateKustomizeExpected kustomizationPath: testcase.Filename, } buf := bytes.NewBuffer([]byte{}) - err = ops.RunBuild(buf, fSys, k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) + err = ops.RunBuild( + buf, fSys, + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()), + k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) switch { case err != nil && len(testcase.ExpectedError) == 0: t.Errorf("unexpected error: %v", err) diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index 61a95e05c..cec2eaa79 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -31,7 +31,8 @@ import ( // NewDefaultCommand returns the default (aka root) command for kustomize command. func NewDefaultCommand( - decoder ifc.Decoder, validator ifc.Validator, hash ifc.Hash) *cobra.Command { + kf ifc.KunstructuredFactory, decoder ifc.Decoder, + validator ifc.Validator, hash ifc.Hash) *cobra.Command { fsys := fs.MakeRealFS() stdOut := os.Stdout @@ -47,7 +48,7 @@ See https://sigs.k8s.io/kustomize c.AddCommand( // TODO: Make consistent API for newCmd* functions. - build.NewCmdBuild(stdOut, fsys, decoder, hash), + build.NewCmdBuild(stdOut, fsys, kf, decoder, hash), edit.NewCmdEdit(fsys, validator), misc.NewCmdConfig(fsys), misc.NewCmdVersion(stdOut), diff --git a/pkg/ifc/ifc.go b/pkg/ifc/ifc.go index c4a00ba12..d67b666dd 100644 --- a/pkg/ifc/ifc.go +++ b/pkg/ifc/ifc.go @@ -69,3 +69,9 @@ type Kunstructured interface { GetAnnotations() map[string]string SetAnnotations(map[string]string) } + +// KunstructuredFactory makes instances of Kunstructured. +type KunstructuredFactory interface { + SliceFromBytes([]byte) ([]Kunstructured, error) + FromMap(m map[string]interface{}) Kunstructured +} diff --git a/pkg/patch/transformer/factory_test.go b/pkg/patch/transformer/factory_test.go index 5791c2ba5..268c45686 100644 --- a/pkg/patch/transformer/factory_test.go +++ b/pkg/patch/transformer/factory_test.go @@ -22,6 +22,7 @@ import ( "testing" "gopkg.in/yaml.v2" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/patch" @@ -30,6 +31,9 @@ import ( "sigs.k8s.io/kustomize/pkg/resource" ) +var rf = resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) + func TestNewPatchJson6902FactoryNoTarget(t *testing.T) { p := patch.Json6902{} _, err := NewPatchJson6902Factory(nil).makeOnePatchJson6902Transformer(p) @@ -182,7 +186,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) { id := resid.NewResId(gvk.FromKind("foo"), "some-name") base := resmap.ResMap{ - id: resource.NewFromMap( + id: rf.FromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ @@ -208,7 +212,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) { }), } expected := resmap.ResMap{ - id: resource.NewFromMap( + id: rf.FromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ @@ -296,7 +300,7 @@ func TestNewPatchJson6902FactoryMultiConflict(t *testing.T) { id := resid.NewResId(gvk.FromKind("foo"), "some-name") base := resmap.ResMap{ - id: resource.NewFromMap( + id: rf.FromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ diff --git a/pkg/patch/transformer/patchjson6902json_test.go b/pkg/patch/transformer/patchjson6902json_test.go index 5be44f339..564933c54 100644 --- a/pkg/patch/transformer/patchjson6902json_test.go +++ b/pkg/patch/transformer/patchjson6902json_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/evanphx/json-patch" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" @@ -30,9 +31,11 @@ import ( var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} func TestJsonPatchJSONTransformer_Transform(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) id := resid.NewResId(deploy, "deploy1") base := resmap.ResMap{ - id: resource.NewFromMap( + id: rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -69,7 +72,7 @@ func TestJsonPatchJSONTransformer_Transform(t *testing.T) { t.Fatalf("unexpected error : %v", err) } expected := resmap.ResMap{ - id: resource.NewFromMap( + id: rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", diff --git a/pkg/resmap/configmap.go b/pkg/resmap/configmap.go index 05b8da92e..ed548e959 100644 --- a/pkg/resmap/configmap.go +++ b/pkg/resmap/configmap.go @@ -25,19 +25,19 @@ import ( // NewResMapFromConfigMapArgs returns a Resource slice given // a configmap metadata slice from kustomization file. -func NewResMapFromConfigMapArgs( - f *configmapandsecret.ConfigMapFactory, +func (rmF *Factory) NewResMapFromConfigMapArgs( + cf *configmapandsecret.ConfigMapFactory, cmArgsList []types.ConfigMapArgs) (ResMap, error) { var allResources []*resource.Resource for _, cmArgs := range cmArgsList { if cmArgs.Behavior == "" { cmArgs.Behavior = "create" } - cm, err := f.MakeConfigMap(&cmArgs) + cm, err := cf.MakeConfigMap(&cmArgs) if err != nil { return nil, err } - res, err := resource.NewWithBehavior( + res, err := rmF.resF.WithBehavior( cm, ifc.NewGenerationBehavior(cmArgs.Behavior)) if err != nil { return nil, err diff --git a/pkg/resmap/configmap_test.go b/pkg/resmap/configmap_test.go index fdf67a14b..e6c2902fb 100644 --- a/pkg/resmap/configmap_test.go +++ b/pkg/resmap/configmap_test.go @@ -26,7 +26,6 @@ import ( "sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/resid" - "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/types" ) @@ -42,7 +41,7 @@ func TestNewFromConfigMaps(t *testing.T) { } l := loadertest.NewFakeLoader("/home/seans/project/") - f := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l) + cf := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l) testCases := []testCase{ { description: "construct config map from env", @@ -57,7 +56,7 @@ func TestNewFromConfigMaps(t *testing.T) { filepath: "/home/seans/project/app.env", content: "DB_USERNAME=admin\nDB_PASSWORD=somepw", expected: ResMap{ - resid.NewResId(cmap, "envConfigMap"): resource.NewFromMap( + resid.NewResId(cmap, "envConfigMap"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -83,7 +82,7 @@ func TestNewFromConfigMaps(t *testing.T) { filepath: "/home/seans/project/app-init.ini", content: "FOO=bar\nBAR=baz\n", expected: ResMap{ - resid.NewResId(cmap, "fileConfigMap"): resource.NewFromMap( + resid.NewResId(cmap, "fileConfigMap"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -109,7 +108,7 @@ BAR=baz }, }, expected: ResMap{ - resid.NewResId(cmap, "literalConfigMap"): resource.NewFromMap( + resid.NewResId(cmap, "literalConfigMap"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -133,7 +132,7 @@ BAR=baz if ferr := l.AddFile(tc.filepath, []byte(tc.content)); ferr != nil { t.Fatalf("Error adding fake file: %v\n", ferr) } - r, err := NewResMapFromConfigMapArgs(f, tc.input) + r, err := rmF.NewResMapFromConfigMapArgs(cf, tc.input) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index 29c7dedbe..1a80ae84c 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -114,10 +114,10 @@ func (m ResMap) ErrorIfNotEqual(m2 ResMap) error { } // DeepCopy clone the resmap into a new one -func (m ResMap) DeepCopy() ResMap { +func (m ResMap) DeepCopy(rf *resource.Factory) ResMap { mcopy := make(ResMap) for id, obj := range m { - mcopy[id] = resource.NewFromKunstructured(obj.Copy()) + mcopy[id] = rf.FromKunstructured(obj.Copy()) mcopy[id].SetBehavior(obj.Behavior()) } return mcopy @@ -135,17 +135,31 @@ func (m ResMap) FilterBy(inputId resid.ResId) ResMap { return result } -// NewResMapFromFiles returns a ResMap given a resource path slice. -func NewResMapFromFiles( - loader ifc.Loader, paths []string, - d ifc.Decoder) (ResMap, error) { +// Factory makes instances of ResMap. +type Factory struct { + resF *resource.Factory +} + +// NewFactory returns a new resmap.Factory. +func NewFactory(rf *resource.Factory) *Factory { + return &Factory{resF: rf} +} + +// RF returns a resource.Factory. +func (rmF *Factory) RF() *resource.Factory { + return rmF.resF +} + +// FromFiles returns a ResMap given a resource path slice. +func (rmF *Factory) FromFiles( + loader ifc.Loader, paths []string) (ResMap, error) { var result []ResMap for _, path := range paths { content, err := loader.Load(path) if err != nil { return nil, errors.Wrap(err, "Load from path "+path+" failed") } - res, err := newResMapFromBytes(content, d) + res, err := rmF.newResMapFromBytes(content) if err != nil { return nil, internal.Handler(err, path) } @@ -155,8 +169,8 @@ func NewResMapFromFiles( } // newResMapFromBytes decodes a list of objects in byte array format. -func newResMapFromBytes(b []byte, d ifc.Decoder) (ResMap, error) { - resources, err := resource.NewSliceFromBytes(b, d) +func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) { + resources, err := rmF.resF.SliceFromBytes(b) if err != nil { return nil, err } diff --git a/pkg/resmap/resmap_test.go b/pkg/resmap/resmap_test.go index d3653e31c..357413d00 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -31,6 +31,9 @@ import ( var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} var statefulset = gvk.Gvk{Group: "apps", Version: "v1", Kind: "StatefulSet"} +var rf = resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) +var rmF = NewFactory(rf) func TestEncodeAsYaml(t *testing.T) { encoded := []byte(`apiVersion: v1 @@ -44,7 +47,7 @@ metadata: name: cm2 `) input := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -52,7 +55,7 @@ metadata: "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -72,7 +75,7 @@ metadata: func TestDemandOneMatchForId(t *testing.T) { rm1 := ResMap{ - resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -80,7 +83,7 @@ func TestDemandOneMatchForId(t *testing.T) { "name": "cm1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -118,7 +121,7 @@ func TestDemandOneMatchForId(t *testing.T) { } func TestFilterBy(t *testing.T) { - rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( + rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -126,7 +129,7 @@ func TestFilterBy(t *testing.T) { "name": "cm1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -136,7 +139,7 @@ func TestFilterBy(t *testing.T) { }), } rm1 := ResMap{ - resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -162,7 +165,7 @@ func TestFilterBy(t *testing.T) { } func TestDeepCopy(t *testing.T) { rm1 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -170,7 +173,7 @@ func TestDeepCopy(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -180,7 +183,7 @@ func TestDeepCopy(t *testing.T) { }), } - rm2 := rm1.DeepCopy() + rm2 := rm1.DeepCopy(rf) if &rm1 == &rm2 { t.Fatal("DeepCopy returned a reference to itself instead of a copy") @@ -194,7 +197,7 @@ func TestDeepCopy(t *testing.T) { func TestErrorIfNotEqual(t *testing.T) { rm1 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -202,7 +205,7 @@ func TestErrorIfNotEqual(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -218,7 +221,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm2 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -235,7 +238,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm3 := ResMap{ - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -252,7 +255,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm4 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -291,7 +294,7 @@ metadata: if ferr := l.AddFile("/home/seans/project/deployment.yaml", []byte(resourceStr)); ferr != nil { t.Fatalf("Error adding fake file: %v\n", ferr) } - expected := ResMap{resid.NewResId(deploy, "dply1"): resource.NewFromMap( + expected := ResMap{resid.NewResId(deploy, "dply1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -299,7 +302,7 @@ metadata: "name": "dply1", }, }), - resid.NewResId(deploy, "dply2"): resource.NewFromMap( + resid.NewResId(deploy, "dply2"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -309,9 +312,8 @@ metadata: }), } - m, _ := NewResMapFromFiles( - l, []string{"/home/seans/project/deployment.yaml"}, - k8sdeps.NewKustDecoder()) + m, _ := rmF.FromFiles( + l, []string{"/home/seans/project/deployment.yaml"}) if len(m) != 2 { t.Fatalf("%#v should contain 2 appResource, but got %d", m, len(m)) } @@ -333,7 +335,7 @@ metadata: name: cm2 `) expected := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -341,7 +343,7 @@ metadata: "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -350,7 +352,7 @@ metadata: }, }), } - m, err := newResMapFromBytes(encoded, k8sdeps.NewKustDecoder()) + m, err := rmF.newResMapFromBytes(encoded) fmt.Printf("%v\n", m) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -362,7 +364,7 @@ metadata: func TestMergeWithoutOverride(t *testing.T) { input1 := ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -372,7 +374,7 @@ func TestMergeWithoutOverride(t *testing.T) { }), } input2 := ResMap{ - resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( + resid.NewResId(statefulset, "stateful1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "StatefulSet", @@ -383,7 +385,7 @@ func TestMergeWithoutOverride(t *testing.T) { } input := []ResMap{input1, input2} expected := ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -391,7 +393,7 @@ func TestMergeWithoutOverride(t *testing.T) { "name": "foo-deploy1", }, }), - resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( + resid.NewResId(statefulset, "stateful1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "StatefulSet", @@ -428,7 +430,7 @@ func TestMergeWithoutOverride(t *testing.T) { func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { input1 := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewFromMap( + resid.NewResId(cmap, "cmap"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", @@ -442,7 +444,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { }), } input2 := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewFromMap( + resid.NewResId(cmap, "cmap"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", @@ -463,7 +465,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { func TestMergeWithOverride(t *testing.T) { expected := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewFromMap( + resid.NewResId(cmap, "cmap"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", diff --git a/pkg/resmap/secret.go b/pkg/resmap/secret.go index 06e27f8c3..f3557864b 100644 --- a/pkg/resmap/secret.go +++ b/pkg/resmap/secret.go @@ -26,7 +26,7 @@ import ( // NewResMapFromSecretArgs takes a SecretArgs slice, generates // secrets from each entry, and accumulates them in a ResMap. -func NewResMapFromSecretArgs( +func (rmF *Factory) NewResMapFromSecretArgs( f *configmapandsecret.SecretFactory, secretList []types.SecretArgs) (ResMap, error) { var allResources []*resource.Resource @@ -38,10 +38,10 @@ func NewResMapFromSecretArgs( if args.Behavior == "" { args.Behavior = "create" } - res, err := resource.NewWithBehavior( + res, err := rmF.resF.WithBehavior( s, ifc.NewGenerationBehavior(args.Behavior)) if err != nil { - return nil, errors.Wrap(err, "NewWithBehavior") + return nil, errors.Wrap(err, "WithBehavior") } allResources = append(allResources, res) } diff --git a/pkg/resmap/secret_test.go b/pkg/resmap/secret_test.go index 53242b6f3..5cbcea365 100644 --- a/pkg/resmap/secret_test.go +++ b/pkg/resmap/secret_test.go @@ -27,7 +27,6 @@ import ( "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/resid" - "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/types" ) @@ -55,7 +54,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { } fakeFs := fs.MakeFakeFS() fakeFs.Mkdir(".") - actual, err := NewResMapFromSecretArgs( + actual, err := rmF.NewResMapFromSecretArgs( configmapandsecret.NewSecretFactory(fakeFs, "."), secrets) if err != nil { @@ -63,7 +62,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { } expected := ResMap{ - resid.NewResId(secret, "apple"): resource.NewFromMap( + resid.NewResId(secret, "apple"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -76,7 +75,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResId(secret, "peanuts"): resource.NewFromMap( + resid.NewResId(secret, "peanuts"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -111,7 +110,7 @@ func TestSecretTimeout(t *testing.T) { } fakeFs := fs.MakeFakeFS() fakeFs.Mkdir(".") - _, err := NewResMapFromSecretArgs( + _, err := rmF.NewResMapFromSecretArgs( configmapandsecret.NewSecretFactory(fakeFs, "."), secrets) if err == nil { diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 9ef6683b1..36b378af6 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -29,46 +29,53 @@ import ( "sigs.k8s.io/kustomize/pkg/resid" ) -// Resource is map representation of a Kubernetes API resource object -// paired with a GenerationBehavior. -type Resource struct { - ifc.Kunstructured - b ifc.GenerationBehavior +// Factory makes instances of Resource. +type Factory struct { + kf ifc.KunstructuredFactory } -// NewWithBehavior returns a new instance of Resource. -func NewWithBehavior(obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) { +// NewFactory makes an instance of Factory. +func NewFactory(kf ifc.KunstructuredFactory) *Factory { + return &Factory{kf: kf} +} + +// WithBehavior returns a new instance of Resource. +// TODO(monopole): This runtime dependence must be refactored away. +// The logic calling this has to move to k8sdeps. +func (rf *Factory) WithBehavior( + obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) { + // TODO(monopole): This k8sdeps dependence must be refactored away. u, err := k8sdeps.NewKunstructuredFromObject(obj) return &Resource{Kunstructured: u, b: b}, err } -// NewFromMap returns a new instance of Resource. -func NewFromMap(m map[string]interface{}) *Resource { +// FromMap returns a new instance of Resource. +func (rf *Factory) FromMap(m map[string]interface{}) *Resource { return &Resource{ - Kunstructured: k8sdeps.NewKunstructuredFromMap(m), + Kunstructured: rf.kf.FromMap(m), b: ifc.BehaviorUnspecified} } -// NewFromKunstructured returns a new instance of Resource. -func NewFromKunstructured(u ifc.Kunstructured) *Resource { +// FromKunstructured returns a new instance of Resource. +func (rf *Factory) FromKunstructured( + u ifc.Kunstructured) *Resource { if u == nil { log.Fatal("unstruct ifc must not be null") } return &Resource{Kunstructured: u, b: ifc.BehaviorUnspecified} } -// NewSliceFromPatches returns a slice of resources given a patch path +// SliceFromPatches returns a slice of resources given a patch path // slice from a kustomization file. -func NewSliceFromPatches( - ldr ifc.Loader, paths []patch.StrategicMerge, - decoder ifc.Decoder) ([]*Resource, error) { +func (rf *Factory) SliceFromPatches( + ldr ifc.Loader, paths []patch.StrategicMerge) ([]*Resource, error) { var result []*Resource for _, path := range paths { content, err := ldr.Load(string(path)) if err != nil { return nil, err } - res, err := NewSliceFromBytes(content, decoder) + res, err := rf.SliceFromBytes(content) if err != nil { return nil, internal.Handler(err, string(path)) } @@ -77,20 +84,26 @@ func NewSliceFromPatches( return result, nil } -// NewSliceFromBytes unmarshalls bytes into a Resource slice. -func NewSliceFromBytes( - in []byte, decoder ifc.Decoder) ([]*Resource, error) { - funStructs, err := k8sdeps.NewKunstructuredSliceFromBytes(in, decoder) +// SliceFromBytes unmarshalls bytes into a Resource slice. +func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) { + kunStructs, err := rf.kf.SliceFromBytes(in) if err != nil { return nil, err } var result []*Resource - for _, u := range funStructs { - result = append(result, NewFromKunstructured(u)) + for _, u := range kunStructs { + result = append(result, rf.FromKunstructured(u)) } return result, nil } +// Resource is map representation of a Kubernetes API resource object +// paired with a GenerationBehavior. +type Resource struct { + ifc.Kunstructured + b ifc.GenerationBehavior +} + // String returns resource as JSON. func (r *Resource) String() string { bs, err := r.MarshalJSON() diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index 500ec04ba..08b454b8e 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -18,14 +18,17 @@ package resource import ( "reflect" - "sigs.k8s.io/kustomize/internal/k8sdeps" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/patch" ) -var testConfigMap = NewFromMap( +var factory = NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) + +var testConfigMap = factory.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +39,7 @@ var testConfigMap = NewFromMap( const testConfigMapString = `unspecified:{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}` -var testDeployment = NewFromMap( +var testDeployment = factory.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -68,7 +71,8 @@ func TestResourceString(t *testing.T) { } } -func TestNewResourceSliceFromPatches(t *testing.T) { +func TestSliceFromPatches(t *testing.T) { + patchGood1 := patch.StrategicMerge("/foo/patch1.yaml") patch1 := ` apiVersion: apps/v1 @@ -122,8 +126,7 @@ WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot }, } for _, test := range tests { - rs, err := NewSliceFromPatches( - l, test.input, k8sdeps.NewKustDecoder()) + rs, err := factory.SliceFromPatches(l, test.input) if test.expectedErr && err == nil { t.Fatalf("%v: should return error", test.name) } diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index 4c1000828..37eee3202 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -47,12 +47,14 @@ type KustTarget struct { hash ifc.Hash ldr ifc.Loader fSys fs.FileSystem + rf *resmap.Factory tcfg *transformerconfig.TransformerConfig } // NewKustTarget returns a new instance of KustTarget primed with a Loader. func NewKustTarget( ldr ifc.Loader, fSys fs.FileSystem, + rf *resmap.Factory, tcfg *transformerconfig.TransformerConfig, d ifc.Decoder, h ifc.Hash) (*KustTarget, error) { content, err := ldr.Load(constants.KustomizationFileName) @@ -70,6 +72,7 @@ func NewKustTarget( kustomization: &k, ldr: ldr, fSys: fSys, + rf: rf, tcfg: tcfg, decoder: d, hash: h, @@ -146,10 +149,10 @@ func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) { return nil, err } - patches, err := resource.NewSliceFromPatches( - kt.ldr, kt.kustomization.PatchesStrategicMerge, kt.decoder) + patches, err := kt.rf.RF().SliceFromPatches( + kt.ldr, kt.kustomization.PatchesStrategicMerge) if err != nil { - errs.Append(errors.Wrap(err, "NewSliceFromPatches")) + errs.Append(errors.Wrap(err, "SliceFromPatches")) } if len(errs.Get()) > 0 { @@ -183,13 +186,13 @@ func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) { func (kt *KustTarget) generateConfigMapsAndSecrets( errs *interror.KustomizationErrors) (resmap.ResMap, error) { - cms, err := resmap.NewResMapFromConfigMapArgs( + cms, err := kt.rf.NewResMapFromConfigMapArgs( configmapandsecret.NewConfigMapFactory(kt.fSys, kt.ldr), kt.kustomization.ConfigMapGenerator) if err != nil { errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs")) } - secrets, err := resmap.NewResMapFromSecretArgs( + secrets, err := kt.rf.NewResMapFromSecretArgs( configmapandsecret.NewSecretFactory(kt.fSys, kt.ldr.Root()), kt.kustomization.SecretGenerator) if err != nil { @@ -201,8 +204,8 @@ func (kt *KustTarget) generateConfigMapsAndSecrets( // Gets Bases and Resources as advertised. func (kt *KustTarget) loadResMapFromBasesAndResources() (resmap.ResMap, error) { bases, errs := kt.loadCustomizedBases() - resources, err := resmap.NewResMapFromFiles( - kt.ldr, kt.kustomization.Resources, kt.decoder) + resources, err := kt.rf.FromFiles( + kt.ldr, kt.kustomization.Resources) if err != nil { errs.Append(errors.Wrap(err, "rawResources failed to read Resources")) } @@ -223,7 +226,8 @@ func (kt *KustTarget) loadCustomizedBases() (resmap.ResMap, *interror.Kustomizat errs.Append(errors.Wrap(err, "couldn't make ldr for "+path)) continue } - target, err := NewKustTarget(ldr, kt.fSys, kt.tcfg, kt.decoder, kt.hash) + target, err := NewKustTarget( + ldr, kt.fSys, kt.rf, kt.tcfg, kt.decoder, kt.hash) if err != nil { errs.Append(errors.Wrap(err, "couldn't make target for "+path)) continue @@ -252,7 +256,8 @@ func (kt *KustTarget) loadBasesAsFlatList() ([]*KustTarget, error) { errs.Append(err) continue } - target, err := NewKustTarget(ldr, kt.fSys, kt.tcfg, kt.decoder, kt.hash) + target, err := NewKustTarget( + ldr, kt.fSys, kt.rf, kt.tcfg, kt.decoder, kt.hash) if err != nil { errs.Append(err) continue @@ -268,7 +273,7 @@ func (kt *KustTarget) loadBasesAsFlatList() ([]*KustTarget, error) { // newTransformer makes a Transformer that does everything except resolve generated names. func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers.Transformer, error) { var r []transformers.Transformer - t, err := transformers.NewPatchTransformer(patches) + t, err := transformers.NewPatchTransformer(patches, kt.rf.RF()) if err != nil { return nil, err } diff --git a/pkg/target/kusttarget_test.go b/pkg/target/kusttarget_test.go index 4b064eda7..e989f2786 100644 --- a/pkg/target/kusttarget_test.go +++ b/pkg/target/kusttarget_test.go @@ -88,6 +88,9 @@ metadata: ]` ) +var rf = resmap.NewFactory(resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))) + func makeLoader1(t *testing.T) ifc.Loader { ldr := loadertest.NewFakeLoader("/testpath") err := ldr.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1)) @@ -116,7 +119,7 @@ var ns = gvk.Gvk{Version: "v1", Kind: "Namespace"} func TestResources1(t *testing.T) { expected := resmap.ResMap{ - resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -149,7 +152,7 @@ func TestResources1(t *testing.T) { }, }, }), - resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -168,7 +171,7 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": "somepw", }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -188,7 +191,7 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -207,7 +210,7 @@ func TestResources1(t *testing.T) { fakeFs := fs.MakeFakeFS() fakeFs.Mkdir("/") kt, err := NewKustTarget( - l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), + l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(), k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) if err != nil { t.Fatalf("unexpected construction error %v", err) @@ -232,7 +235,7 @@ func TestResourceNotFound(t *testing.T) { fakeFs := fs.MakeFakeFS() fakeFs.Mkdir("/") kt, err := NewKustTarget( - l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), + l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(), k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) if err != nil { t.Fatalf("Unexpected construction error %v", err) @@ -255,7 +258,7 @@ func TestSecretTimeout(t *testing.T) { fakeFs := fs.MakeFakeFS() fakeFs.Mkdir("/") kt, err := NewKustTarget( - l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), + l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(), k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) if err != nil { t.Fatalf("Unexpected construction error %v", err) diff --git a/pkg/transformers/imagetag_test.go b/pkg/transformers/imagetag_test.go index 1156a9eda..99c56d5d8 100644 --- a/pkg/transformers/imagetag_test.go +++ b/pkg/transformers/imagetag_test.go @@ -18,18 +18,22 @@ package transformers import ( "reflect" - "sigs.k8s.io/kustomize/pkg/resid" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/types" ) func TestImageTagTransformer(t *testing.T) { + var rf = resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) + m := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -60,7 +64,7 @@ func TestImageTagTransformer(t *testing.T) { }, }, }), - resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( + resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): rf.FromMap( map[string]interface{}{ "spec": map[string]interface{}{ "template": map[string]interface{}{ @@ -97,7 +101,7 @@ func TestImageTagTransformer(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -128,7 +132,7 @@ func TestImageTagTransformer(t *testing.T) { }, }, }), - resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( + resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): rf.FromMap( map[string]interface{}{ "spec": map[string]interface{}{ "template": map[string]interface{}{ diff --git a/pkg/transformers/labelsandannotations_test.go b/pkg/transformers/labelsandannotations_test.go index d4814f47d..f86ddb357 100644 --- a/pkg/transformers/labelsandannotations_test.go +++ b/pkg/transformers/labelsandannotations_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" @@ -41,10 +42,12 @@ var pvc = gvk.Gvk{Version: "v1", Kind: "PersistentVolumeClaim"} var crb = gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"} var sa = gvk.Gvk{Version: "v1", Kind: "ServiceAccount"} var ingress = gvk.Gvk{Kind: "Ingress"} +var rf = resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) func TestLabelsRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -52,7 +55,7 @@ func TestLabelsRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -78,7 +81,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -94,7 +97,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job1"): resource.NewFromMap( + resid.NewResId(job, "job1"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -114,7 +117,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job2"): resource.NewFromMap( + resid.NewResId(job, "job2"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -139,7 +142,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( + resid.NewResId(cronjob, "cronjob1"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -164,7 +167,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( + resid.NewResId(cronjob, "cronjob2"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -196,7 +199,7 @@ func TestLabelsRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -208,7 +211,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -246,7 +249,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -270,7 +273,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job1"): resource.NewFromMap( + resid.NewResId(job, "job1"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -300,7 +303,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job2"): resource.NewFromMap( + resid.NewResId(job, "job2"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -337,7 +340,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( + resid.NewResId(cronjob, "cronjob1"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -372,7 +375,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( + resid.NewResId(cronjob, "cronjob2"): rf.FromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -433,7 +436,7 @@ func TestLabelsRun(t *testing.T) { func TestAnnotationsRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -441,7 +444,7 @@ func TestAnnotationsRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -467,7 +470,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -485,7 +488,7 @@ func TestAnnotationsRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -497,7 +500,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -531,7 +534,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", diff --git a/pkg/transformers/multitransformer.go b/pkg/transformers/multitransformer.go index 1dcc793c8..d5921d1a9 100644 --- a/pkg/transformers/multitransformer.go +++ b/pkg/transformers/multitransformer.go @@ -18,6 +18,7 @@ package transformers import ( "fmt" + "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resmap" ) @@ -26,6 +27,7 @@ import ( type multiTransformer struct { transformers []Transformer checkConflictEnabled bool + rf *resource.Factory } var _ Transformer = &multiTransformer{} @@ -69,7 +71,7 @@ func (o *multiTransformer) transform(m resmap.ResMap) error { // A spot check to perform when the transformations are supposed to be commutative. // Fail if there's a difference in the result. func (o *multiTransformer) transformWithCheckConflict(m resmap.ResMap) error { - mcopy := m.DeepCopy() + mcopy := m.DeepCopy(o.rf) err := o.transform(m) if err != nil { return err diff --git a/pkg/transformers/namehash_test.go b/pkg/transformers/namehash_test.go index 81ec42e47..e8aa0c7d1 100644 --- a/pkg/transformers/namehash_test.go +++ b/pkg/transformers/namehash_test.go @@ -28,8 +28,10 @@ import ( ) func TestNameHashTransformer(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) objs := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -37,7 +39,7 @@ func TestNameHashTransformer(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -63,7 +65,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -79,7 +81,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(secret, "secret1"): resource.NewFromMap( + resid.NewResId(secret, "secret1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -90,7 +92,7 @@ func TestNameHashTransformer(t *testing.T) { } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -98,7 +100,7 @@ func TestNameHashTransformer(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -124,7 +126,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewFromMap( + resid.NewResId(service, "svc1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -140,7 +142,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(secret, "secret1"): resource.NewFromMap( + resid.NewResId(secret, "secret1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", diff --git a/pkg/transformers/namereference_test.go b/pkg/transformers/namereference_test.go index 5fc7e3b7a..ce3951918 100644 --- a/pkg/transformers/namereference_test.go +++ b/pkg/transformers/namereference_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" @@ -27,8 +28,10 @@ import ( ) func TestNameReferenceRun(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +39,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-cm1-somehash", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -44,7 +47,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-cm2-somehash", }, }), - resid.NewResId(secret, "secret1"): resource.NewFromMap( + resid.NewResId(secret, "secret1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -52,7 +55,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-secret1-somehash", }, }), - resid.NewResId(pvc, "claim1"): resource.NewFromMap( + resid.NewResId(pvc, "claim1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "PersistentVolumeClaim", @@ -60,7 +63,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-claim1", }, }), - resid.NewResId(ingress, "ingress1"): resource.NewFromMap( + resid.NewResId(ingress, "ingress1"): rf.FromMap( map[string]interface{}{ "group": "extensions", "apiVersion": "v1beta1", @@ -80,7 +83,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, ), - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -158,7 +161,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }), - resid.NewResId(statefulset, "statefulset1"): resource.NewFromMap( + resid.NewResId(statefulset, "statefulset1"): rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -195,7 +198,7 @@ func TestNameReferenceRun(t *testing.T) { expected[k] = v } - expected[resid.NewResId(deploy, "deploy1")] = resource.NewFromMap( + expected[resid.NewResId(deploy, "deploy1")] = rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -273,7 +276,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }) - expected[resid.NewResId(statefulset, "statefulset1")] = resource.NewFromMap( + expected[resid.NewResId(statefulset, "statefulset1")] = rf.FromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -303,7 +306,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }) - expected[resid.NewResId(ingress, "ingress1")] = resource.NewFromMap( + expected[resid.NewResId(ingress, "ingress1")] = rf.FromMap( map[string]interface{}{ "group": "extensions", "apiVersion": "v1beta1", diff --git a/pkg/transformers/namespace_test.go b/pkg/transformers/namespace_test.go index eb8ca25c8..a30c52049 100644 --- a/pkg/transformers/namespace_test.go +++ b/pkg/transformers/namespace_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" @@ -27,8 +28,10 @@ import ( ) func TestNamespaceRun(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +39,7 @@ func TestNamespaceRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -45,7 +48,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "foo", }, }), - resid.NewResId(ns, "ns1"): resource.NewFromMap( + resid.NewResId(ns, "ns1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -53,7 +56,7 @@ func TestNamespaceRun(t *testing.T) { "name": "ns1", }, }), - resid.NewResId(sa, "default"): resource.NewFromMap( + resid.NewResId(sa, "default"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -62,7 +65,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "system", }, }), - resid.NewResId(sa, "service-account"): resource.NewFromMap( + resid.NewResId(sa, "service-account"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -71,7 +74,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "system", }, }), - resid.NewResId(crb, "crb"): resource.NewFromMap( + resid.NewResId(crb, "crb"): rf.FromMap( map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -96,7 +99,7 @@ func TestNamespaceRun(t *testing.T) { }, }, }), - resid.NewResId(crd, "crd"): resource.NewFromMap( + resid.NewResId(crd, "crd"): rf.FromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", @@ -106,7 +109,7 @@ func TestNamespaceRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -114,7 +117,7 @@ func TestNamespaceRun(t *testing.T) { "name": "ns1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -123,7 +126,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -132,7 +135,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -141,7 +144,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): resource.NewFromMap( + resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -150,7 +153,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResId(crb, "crb"): resource.NewFromMap( + resid.NewResId(crb, "crb"): rf.FromMap( map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -175,7 +178,7 @@ func TestNamespaceRun(t *testing.T) { }, }, }), - resid.NewResId(crd, "crd"): resource.NewFromMap( + resid.NewResId(crd, "crd"): rf.FromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", diff --git a/pkg/transformers/patch.go b/pkg/transformers/patch.go index af5d6f7e1..ad0abca4e 100644 --- a/pkg/transformers/patch.go +++ b/pkg/transformers/patch.go @@ -31,16 +31,18 @@ import ( // patchTransformer applies patches. type patchTransformer struct { patches []*resource.Resource + rf *resource.Factory } var _ Transformer = &patchTransformer{} // NewPatchTransformer constructs a patchTransformer. -func NewPatchTransformer(slice []*resource.Resource) (Transformer, error) { +func NewPatchTransformer( + slice []*resource.Resource, rf *resource.Factory) (Transformer, error) { if len(slice) == 0 { return NewNoOpTransformer(), nil } - return &patchTransformer{slice}, nil + return &patchTransformer{patches: slice, rf: rf}, nil } // Transform apply the patches on top of the base resources. @@ -129,9 +131,9 @@ func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) { } var cd conflictDetector if err != nil { - cd = newJMPConflictDetector() + cd = newJMPConflictDetector(pt.rf) } else { - cd, err = newSMPConflictDetector(versionedObj) + cd, err = newSMPConflictDetector(versionedObj, pt.rf) if err != nil { return nil, err } diff --git a/pkg/transformers/patch_test.go b/pkg/transformers/patch_test.go index aca087f28..1b6f09fb4 100644 --- a/pkg/transformers/patch_test.go +++ b/pkg/transformers/patch_test.go @@ -21,14 +21,17 @@ import ( "strings" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" ) func TestOverlayRun(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -55,7 +58,7 @@ func TestOverlayRun(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -88,7 +91,7 @@ func TestOverlayRun(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -121,7 +124,7 @@ func TestOverlayRun(t *testing.T) { }, }), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -137,7 +140,7 @@ func TestOverlayRun(t *testing.T) { func TestMultiplePatches(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -159,7 +162,7 @@ func TestMultiplePatches(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -185,7 +188,7 @@ func TestMultiplePatches(t *testing.T) { }, }, ), - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -216,7 +219,7 @@ func TestMultiplePatches(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -251,7 +254,7 @@ func TestMultiplePatches(t *testing.T) { }, }), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -267,7 +270,7 @@ func TestMultiplePatches(t *testing.T) { func TestMultiplePatchesWithConflict(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewFromMap( + resid.NewResId(deploy, "deploy1"): rf.FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -289,7 +292,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -315,7 +318,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { }, }, ), - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -337,7 +340,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { ), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -352,7 +355,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { func TestNoSchemaOverlayRun(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewFromMap( + resid.NewResId(foo, "my-foo"): rf.FromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -368,7 +371,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -384,7 +387,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewFromMap( + resid.NewResId(foo, "my-foo"): rf.FromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -400,7 +403,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { }), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -415,7 +418,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { func TestNoSchemaMultiplePatches(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewFromMap( + resid.NewResId(foo, "my-foo"): rf.FromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -431,7 +434,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -445,7 +448,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { }, }, ), - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -464,7 +467,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewFromMap( + resid.NewResId(foo, "my-foo"): rf.FromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -484,7 +487,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { }), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -499,7 +502,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewFromMap( + resid.NewResId(foo, "my-foo"): rf.FromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -515,7 +518,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -528,7 +531,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { }, }, }), - resource.NewFromMap(map[string]interface{}{ + rf.FromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -542,7 +545,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { }), } - lt, err := NewPatchTransformer(patch) + lt, err := NewPatchTransformer(patch, rf) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/pkg/transformers/patchconflictdetector.go b/pkg/transformers/patchconflictdetector.go index 2a8fe1d52..a766b8ff1 100644 --- a/pkg/transformers/patchconflictdetector.go +++ b/pkg/transformers/patchconflictdetector.go @@ -18,6 +18,7 @@ package transformers import ( "encoding/json" + "github.com/evanphx/json-patch" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/mergepatch" @@ -31,12 +32,14 @@ type conflictDetector interface { mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) } -type jsonMergePatch struct{} +type jsonMergePatch struct { + rf *resource.Factory +} var _ conflictDetector = &jsonMergePatch{} -func newJMPConflictDetector() conflictDetector { - return &jsonMergePatch{} +func newJMPConflictDetector(rf *resource.Factory) conflictDetector { + return &jsonMergePatch{rf: rf} } func (jmp *jsonMergePatch) hasConflict( @@ -82,18 +85,21 @@ func (jmp *jsonMergePatch) mergePatches( } mergedMap := make(map[string]interface{}) err = json.Unmarshal(mergedBytes, &mergedMap) - return resource.NewFromMap(mergedMap), err + return jmp.rf.FromMap(mergedMap), err } type strategicMergePatch struct { lookupPatchMeta strategicpatch.LookupPatchMeta + rf *resource.Factory } var _ conflictDetector = &strategicMergePatch{} -func newSMPConflictDetector(versionedObj runtime.Object) (conflictDetector, error) { +func newSMPConflictDetector( + versionedObj runtime.Object, + rf *resource.Factory) (conflictDetector, error) { lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) - return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta}, err + return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err } func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) { @@ -127,5 +133,5 @@ func (smp *strategicMergePatch) findConflict( func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { mergeJsonMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta( smp.lookupPatchMeta, patch1.Map(), patch2.Map()) - return resource.NewFromMap(mergeJsonMap), err + return smp.rf.FromMap(mergeJsonMap), err } diff --git a/pkg/transformers/prefixname_test.go b/pkg/transformers/prefixname_test.go index b7bd89980..d6befeb3a 100644 --- a/pkg/transformers/prefixname_test.go +++ b/pkg/transformers/prefixname_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" @@ -27,8 +28,10 @@ import ( ) func TestPrefixNameRun(t *testing.T) { + rf := resource.NewFactory( + k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())) m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewFromMap( + resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +39,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewFromMap( + resid.NewResId(cmap, "cm2"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -44,7 +47,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "cm2", }, }), - resid.NewResId(crd, "crd"): resource.NewFromMap( + resid.NewResId(crd, "crd"): rf.FromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", @@ -54,7 +57,7 @@ func TestPrefixNameRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): resource.NewFromMap( + resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -62,7 +65,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "someprefix-cm1", }, }), - resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): resource.NewFromMap( + resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -70,7 +73,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "someprefix-cm2", }, }), - resid.NewResId(crd, "crd"): resource.NewFromMap( + resid.NewResId(crd, "crd"): rf.FromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition",