From 1af119db80214747b5e8ee02541382a2c64b7d8c Mon Sep 17 00:00:00 2001 From: Jeffrey Regan Date: Mon, 8 Oct 2018 14:17:50 -0700 Subject: [PATCH] Further isolate unstructured with factories. --- internal/k8sdeps/kunstructuredfactory.go | 12 +-- pkg/resmap/factory.go | 89 ++++++++++++++++++ pkg/resmap/factory_test.go | 115 +++++++++++++++++++++++ pkg/resmap/resmap.go | 65 ------------- pkg/resmap/resmap_test.go | 91 ------------------ pkg/resource/factory.go | 95 +++++++++++++++++++ pkg/resource/factory_test.go | 100 ++++++++++++++++++++ pkg/resource/resource.go | 73 -------------- pkg/resource/resource_test.go | 78 --------------- 9 files changed, 405 insertions(+), 313 deletions(-) create mode 100644 pkg/resmap/factory.go create mode 100644 pkg/resmap/factory_test.go create mode 100644 pkg/resource/factory.go create mode 100644 pkg/resource/factory_test.go diff --git a/internal/k8sdeps/kunstructuredfactory.go b/internal/k8sdeps/kunstructuredfactory.go index d39322075..39dd2acb4 100644 --- a/internal/k8sdeps/kunstructuredfactory.go +++ b/internal/k8sdeps/kunstructuredfactory.go @@ -22,20 +22,20 @@ import ( "sigs.k8s.io/kustomize/pkg/ifc" ) -// KustKunstructuredFactory hides construction using apimachinery types. -type KustKunstructuredFactory struct { +// KunstructurerFactoryImpl hides construction using apimachinery types. +type KunstructurerFactoryImpl struct { decoder ifc.Decoder } -var _ ifc.KunstructuredFactory = &KustKunstructuredFactory{} +var _ ifc.KunstructuredFactory = &KunstructurerFactoryImpl{} // NewKustKunstructuredFactory returns a factory. func NewKustKunstructuredFactory(d ifc.Decoder) ifc.KunstructuredFactory { - return &KustKunstructuredFactory{decoder: d} + return &KunstructurerFactoryImpl{decoder: d} } // SliceFromBytes returns a slice of Kunstructured. -func (kf *KustKunstructuredFactory) SliceFromBytes( +func (kf *KunstructurerFactoryImpl) SliceFromBytes( in []byte) ([]ifc.Kunstructured, error) { kf.decoder.SetInput(in) var result []ifc.Kunstructured @@ -54,7 +54,7 @@ func (kf *KustKunstructuredFactory) SliceFromBytes( } // FromMap returns an instance of Kunstructured. -func (kf *KustKunstructuredFactory) FromMap( +func (kf *KunstructurerFactoryImpl) FromMap( m map[string]interface{}) ifc.Kunstructured { return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}} } diff --git a/pkg/resmap/factory.go b/pkg/resmap/factory.go new file mode 100644 index 000000000..a11d3bbb4 --- /dev/null +++ b/pkg/resmap/factory.go @@ -0,0 +1,89 @@ +/* +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 resmap + +import ( + "fmt" + + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/resource" +) + +// 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 := rmF.newResMapFromBytes(content) + if err != nil { + return nil, internal.Handler(err, path) + } + result = append(result, res) + } + return MergeWithoutOverride(result...) +} + +// newResMapFromBytes decodes a list of objects in byte array format. +func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) { + resources, err := rmF.resF.SliceFromBytes(b) + if err != nil { + return nil, err + } + + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id) + } + result[id] = res + } + return result, nil +} + +func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) { + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return nil, fmt.Errorf("duplicated %#v is not allowed", id) + } + result[id] = res + } + return result, nil +} diff --git a/pkg/resmap/factory_test.go b/pkg/resmap/factory_test.go new file mode 100644 index 000000000..8e6da8cd9 --- /dev/null +++ b/pkg/resmap/factory_test.go @@ -0,0 +1,115 @@ +/* +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 resmap + +import ( + "fmt" + "reflect" + "testing" + + "sigs.k8s.io/kustomize/pkg/internal/loadertest" + "sigs.k8s.io/kustomize/pkg/resid" +) + +func TestFromFiles(t *testing.T) { + + resourceStr := `apiVersion: apps/v1 +kind: Deployment +metadata: + name: dply1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dply2 +--- +# some comment +--- +--- +` + + l := loadertest.NewFakeLoader("/home/seans/project") + 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"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "dply1", + }, + }), + resid.NewResId(deploy, "dply2"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "dply2", + }, + }), + } + + 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)) + } + + if err := expected.ErrorIfNotEqual(m); err != nil { + t.Fatalf("actual doesn't match expected: %v", err) + } +} + +func TestFromBytes(t *testing.T) { + encoded := []byte(`apiVersion: v1 +kind: ConfigMap +metadata: + name: cm1 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cm2 +`) + expected := ResMap{ + resid.NewResId(cmap, "cm1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm1", + }, + }), + resid.NewResId(cmap, "cm2"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm2", + }, + }), + } + m, err := rmF.newResMapFromBytes(encoded) + fmt.Printf("%v\n", m) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(m, expected) { + t.Fatalf("%#v doesn't match expected %#v", m, expected) + } +} diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index 1a80ae84c..4b22e8a54 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -25,9 +25,7 @@ import ( "github.com/ghodss/yaml" "github.com/golang/glog" - "github.com/pkg/errors" "sigs.k8s.io/kustomize/pkg/ifc" - internal "sigs.k8s.io/kustomize/pkg/internal/error" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resource" ) @@ -135,69 +133,6 @@ func (m ResMap) FilterBy(inputId resid.ResId) ResMap { return result } -// 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 := rmF.newResMapFromBytes(content) - if err != nil { - return nil, internal.Handler(err, path) - } - result = append(result, res) - } - return MergeWithoutOverride(result...) -} - -// newResMapFromBytes decodes a list of objects in byte array format. -func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) { - resources, err := rmF.resF.SliceFromBytes(b) - if err != nil { - return nil, err - } - - result := ResMap{} - for _, res := range resources { - id := res.Id() - if _, found := result[id]; found { - return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id) - } - result[id] = res - } - return result, nil -} - -func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) { - result := ResMap{} - for _, res := range resources { - id := res.Id() - if _, found := result[id]; found { - return nil, fmt.Errorf("duplicated %#v is not allowed", id) - } - result[id] = res - } - return result, nil -} - // MergeWithoutOverride combines multiple ResMap instances, failing on key collision // and skipping nil maps. In case if all of the maps are nil, an empty ResMap is returned. func MergeWithoutOverride(maps ...ResMap) (ResMap, error) { diff --git a/pkg/resmap/resmap_test.go b/pkg/resmap/resmap_test.go index 357413d00..a48d8a106 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -17,14 +17,12 @@ limitations under the License. package resmap import ( - "fmt" "reflect" "testing" "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/gvk" "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" ) @@ -273,95 +271,6 @@ func TestErrorIfNotEqual(t *testing.T) { } -func TestNewMapFromFiles(t *testing.T) { - - resourceStr := `apiVersion: apps/v1 -kind: Deployment -metadata: - name: dply1 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: dply2 ---- -# some comment ---- ---- -` - - l := loadertest.NewFakeLoader("/home/seans/project") - 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"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": map[string]interface{}{ - "name": "dply1", - }, - }), - resid.NewResId(deploy, "dply2"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": map[string]interface{}{ - "name": "dply2", - }, - }), - } - - 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)) - } - - if err := expected.ErrorIfNotEqual(m); err != nil { - t.Fatalf("actual doesn't match expected: %v", err) - } -} - -func TestNewMapFromBytes(t *testing.T) { - encoded := []byte(`apiVersion: v1 -kind: ConfigMap -metadata: - name: cm1 ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: cm2 -`) - expected := ResMap{ - resid.NewResId(cmap, "cm1"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "cm1", - }, - }), - resid.NewResId(cmap, "cm2"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "cm2", - }, - }), - } - m, err := rmF.newResMapFromBytes(encoded) - fmt.Printf("%v\n", m) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(m, expected) { - t.Fatalf("%#v doesn't match expected %#v", m, expected) - } -} - func TestMergeWithoutOverride(t *testing.T) { input1 := ResMap{ resid.NewResId(deploy, "deploy1"): rf.FromMap( diff --git a/pkg/resource/factory.go b/pkg/resource/factory.go new file mode 100644 index 000000000..8de804a76 --- /dev/null +++ b/pkg/resource/factory.go @@ -0,0 +1,95 @@ +/* +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 resource + +import ( + "log" + + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/kustomize/internal/k8sdeps" + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/patch" +) + +// Factory makes instances of Resource. +type Factory struct { + kf ifc.KunstructuredFactory +} + +// 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 +} + +// FromMap returns a new instance of Resource. +func (rf *Factory) FromMap(m map[string]interface{}) *Resource { + return &Resource{ + Kunstructured: rf.kf.FromMap(m), + b: ifc.BehaviorUnspecified} +} + +// 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} +} + +// SliceFromPatches returns a slice of resources given a patch path +// slice from a kustomization file. +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 := rf.SliceFromBytes(content) + if err != nil { + return nil, internal.Handler(err, string(path)) + } + result = append(result, res...) + } + return result, nil +} + +// 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 kunStructs { + result = append(result, rf.FromKunstructured(u)) + } + return result, nil +} diff --git a/pkg/resource/factory_test.go b/pkg/resource/factory_test.go new file mode 100644 index 000000000..786a6440b --- /dev/null +++ b/pkg/resource/factory_test.go @@ -0,0 +1,100 @@ +/* +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 resource + +import ( + "reflect" + "testing" + + "sigs.k8s.io/kustomize/pkg/internal/loadertest" + "sigs.k8s.io/kustomize/pkg/patch" +) + +func TestSliceFromPatches(t *testing.T) { + + patchGood1 := patch.StrategicMerge("/foo/patch1.yaml") + patch1 := ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pooh +` + patchGood2 := patch.StrategicMerge("/foo/patch2.yaml") + patch2 := ` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +# some comment +--- +--- +` + patchBad := patch.StrategicMerge("/foo/patch3.yaml") + patch3 := ` +WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot +` + l := loadertest.NewFakeLoader("/foo") + l.AddFile(string(patchGood1), []byte(patch1)) + l.AddFile(string(patchGood2), []byte(patch2)) + l.AddFile(string(patchBad), []byte(patch3)) + + tests := []struct { + name string + input []patch.StrategicMerge + expectedOut []*Resource + expectedErr bool + }{ + { + name: "happy", + input: []patch.StrategicMerge{patchGood1, patchGood2}, + expectedOut: []*Resource{testDeployment, testConfigMap}, + expectedErr: false, + }, + { + name: "badFileName", + input: []patch.StrategicMerge{patchGood1, "doesNotExist"}, + expectedOut: []*Resource{}, + expectedErr: true, + }, + { + name: "badData", + input: []patch.StrategicMerge{patchGood1, patchBad}, + expectedOut: []*Resource{}, + expectedErr: true, + }, + } + for _, test := range tests { + rs, err := factory.SliceFromPatches(l, 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/pkg/resource/resource.go b/pkg/resource/resource.go index 36b378af6..9bea6f2fc 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -18,85 +18,12 @@ limitations under the License. package resource import ( - "log" "strings" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/ifc" - internal "sigs.k8s.io/kustomize/pkg/internal/error" - "sigs.k8s.io/kustomize/pkg/patch" "sigs.k8s.io/kustomize/pkg/resid" ) -// Factory makes instances of Resource. -type Factory struct { - kf ifc.KunstructuredFactory -} - -// 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 -} - -// FromMap returns a new instance of Resource. -func (rf *Factory) FromMap(m map[string]interface{}) *Resource { - return &Resource{ - Kunstructured: rf.kf.FromMap(m), - b: ifc.BehaviorUnspecified} -} - -// 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} -} - -// SliceFromPatches returns a slice of resources given a patch path -// slice from a kustomization file. -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 := rf.SliceFromBytes(content) - if err != nil { - return nil, internal.Handler(err, string(path)) - } - result = append(result, res...) - } - return result, nil -} - -// 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 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 { diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index 08b454b8e..4a4677e19 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -17,12 +17,9 @@ limitations under the License. package resource import ( - "reflect" "testing" "sigs.k8s.io/kustomize/internal/k8sdeps" - "sigs.k8s.io/kustomize/pkg/internal/loadertest" - "sigs.k8s.io/kustomize/pkg/patch" ) var factory = NewFactory( @@ -70,78 +67,3 @@ func TestResourceString(t *testing.T) { } } } - -func TestSliceFromPatches(t *testing.T) { - - patchGood1 := patch.StrategicMerge("/foo/patch1.yaml") - patch1 := ` -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pooh -` - patchGood2 := patch.StrategicMerge("/foo/patch2.yaml") - patch2 := ` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie ---- -# some comment ---- ---- -` - patchBad := patch.StrategicMerge("/foo/patch3.yaml") - patch3 := ` -WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot -` - l := loadertest.NewFakeLoader("/foo") - l.AddFile(string(patchGood1), []byte(patch1)) - l.AddFile(string(patchGood2), []byte(patch2)) - l.AddFile(string(patchBad), []byte(patch3)) - - tests := []struct { - name string - input []patch.StrategicMerge - expectedOut []*Resource - expectedErr bool - }{ - { - name: "happy", - input: []patch.StrategicMerge{patchGood1, patchGood2}, - expectedOut: []*Resource{testDeployment, testConfigMap}, - expectedErr: false, - }, - { - name: "badFileName", - input: []patch.StrategicMerge{patchGood1, "doesNotExist"}, - expectedOut: []*Resource{}, - expectedErr: true, - }, - { - name: "badData", - input: []patch.StrategicMerge{patchGood1, patchBad}, - expectedOut: []*Resource{}, - expectedErr: true, - }, - } - for _, test := range tests { - rs, err := factory.SliceFromPatches(l, 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]) - } - } - } -}