diff --git a/k8sdeps/transformer/patch/patch.go b/k8sdeps/transformer/patch/patch.go index 4a2764bfb..357f3daba 100644 --- a/k8sdeps/transformer/patch/patch.go +++ b/k8sdeps/transformer/patch/patch.go @@ -60,7 +60,7 @@ func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error { for _, patch := range patches { // Merge patches with base resource. id := patch.Id() - matchedIds := baseResourceMap.FindByGVKN(id) + matchedIds := baseResourceMap.GetMatchingIds(id.GvknEquals) if len(matchedIds) == 0 { return fmt.Errorf("failed to find an object with %s to apply the patch", id.GvknString()) } diff --git a/pkg/patch/transformer/patchjson6902json.go b/pkg/patch/transformer/patchjson6902json.go index fa2fce49a..c8f6e9e3e 100644 --- a/pkg/patch/transformer/patchjson6902json.go +++ b/pkg/patch/transformer/patchjson6902json.go @@ -35,17 +35,18 @@ type patchJson6902JSONTransformer struct { var _ transformers.Transformer = &patchJson6902JSONTransformer{} // newPatchJson6902JSONTransformer constructs a PatchJson6902 transformer. -func newPatchJson6902JSONTransformer(t resid.ResId, p jsonpatch.Patch) (transformers.Transformer, error) { +func newPatchJson6902JSONTransformer( + id resid.ResId, p jsonpatch.Patch) (transformers.Transformer, error) { if len(p) == 0 { return transformers.NewNoOpTransformer(), nil } - return &patchJson6902JSONTransformer{target: t, patch: p}, nil + return &patchJson6902JSONTransformer{target: id, patch: p}, nil } // Transform apply the json patches on top of the base resources. func (t *patchJson6902JSONTransformer) Transform(m resmap.ResMap) error { obj, err := t.findTargetObj(m) - if obj == nil { + if err != nil { return err } rawObj, err := obj.MarshalJSON() @@ -65,15 +66,18 @@ func (t *patchJson6902JSONTransformer) Transform(m resmap.ResMap) error { func (t *patchJson6902JSONTransformer) findTargetObj( m resmap.ResMap) (*resource.Resource, error) { - matched := m.FindByGVKN(t.target) + var matched []resid.ResId + // TODO(monopole): namespace bug in json patch? + // Since introduction in PR #300 + // (see pkg/patch/transformer/util.go), + // this code has treated an empty namespace like a wildcard + // rather than like an additional restriction to match + // only the empty namespace. No test coverage to confirm. + // Not sure if desired, keeping it for now. if t.target.Namespace() != "" { - var ids []resid.ResId - for _, id := range matched { - if id.Namespace() == t.target.Namespace() { - ids = append(ids, id) - } - } - matched = ids + matched = m.GetMatchingIds(t.target.NsGvknEquals) + } else { + matched = m.GetMatchingIds(t.target.GvknEquals) } if len(matched) == 0 { return nil, fmt.Errorf( diff --git a/pkg/resid/resid.go b/pkg/resid/resid.go index 2af7c02a5..dbf9a3e92 100644 --- a/pkg/resid/resid.go +++ b/pkg/resid/resid.go @@ -22,23 +22,30 @@ import ( "sigs.k8s.io/kustomize/pkg/gvk" ) -// ResId conflates GroupVersionKind with a textual name to uniquely identify a kubernetes resource (object). +// ResId is an immutable identifier of a k8s resource object. type ResId struct { // Gvk of the resource. gvKind gvk.Gvk - // original name of the resource before transformation. + + // name of the resource before transformation. name string - // namePrefix of the resource - // an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes - // concatenated together. + + // namePrefix of the resource. + // An untransformed resource has no prefix. + // A fully transformed resource has an arbitrary + // number of prefixes concatenated together. prefix string - // nameSuffix of the resource - // an untransformed resource has no suffix, fully transformed resource has an arbitrary number of suffixes - // concatenated together. + + // nameSuffix of the resource. + // An untransformed resource has no suffix. + // A fully transformed resource has an arbitrary + // number of suffixes concatenated together. suffix string - // namespace the resource belongs to - // an untransformed resource has no namespace, fully transformed resource has the namespace from - // the top most overlay + + // Namespace the resource belongs to. + // An untransformed resource has no namespace. + // A fully transformed resource has the namespace + // from the top most overlay. namespace string } @@ -108,10 +115,16 @@ func (n ResId) GvknString() string { return n.gvKind.String() + separator + n.name } -// GvknEquals return if two ResId have the same Group/Version/Kind and name -// The comparison excludes prefix and suffix +// GvknEquals returns true if the other id matches +// Group/Version/Kind/name. func (n ResId) GvknEquals(id ResId) bool { - return n.gvKind.Equals(id.gvKind) && n.name == id.name + return n.name == id.name && n.gvKind.Equals(id.gvKind) +} + +// NsGvknEquals returns true if the other id matches +// namespace/Group/Version/Kind/name. +func (n ResId) NsGvknEquals(id ResId) bool { + return n.namespace == id.namespace && n.GvknEquals(id) } // Gvk returns Group/Version/Kind of the resource. diff --git a/pkg/resid/resid_test.go b/pkg/resid/resid_test.go index 85bafd447..cf3d46a82 100644 --- a/pkg/resid/resid_test.go +++ b/pkg/resid/resid_test.go @@ -10,31 +10,80 @@ var stringTests = []struct { x ResId s string }{ - {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "g_v_k|ns|p|nm|s"}, - {ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_v_k|ns|p|nm|s"}, - {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_~V_k|ns|p|nm|s"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_~V_~K|ns|p|nm|s"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", suffix: "s"}, - "~G_~V_~K|~X|p|nm|s"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", suffix: "s"}, - "~G_~V_~K|~X|~P|nm|s"}, - {ResId{gvKind: gvk.Gvk{}, - suffix: "s"}, - "~G_~V_~K|~X|~P|~N|s"}, - {ResId{gvKind: gvk.Gvk{}}, - "~G_~V_~K|~X|~P|~N|~S"}, - {ResId{}, - "~G_~V_~K|~X|~P|~N|~S"}, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "g_v_k|ns|p|nm|s", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Version: "v", Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_v_k|ns|p|nm|s", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_k|ns|p|nm|s", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_~K|ns|p|nm|s", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_~K|~X|p|nm|s", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + name: "nm", + suffix: "s", + }, + "~G_~V_~K|~X|~P|nm|s", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + suffix: "s", + }, + "~G_~V_~K|~X|~P|~N|s", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + }, + "~G_~V_~K|~X|~P|~N|~S", + }, + { + ResId{}, + "~G_~V_~K|~X|~P|~N|~S", + }, } func TestString(t *testing.T) { @@ -49,31 +98,80 @@ var gvknStringTests = []struct { x ResId s string }{ - {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "g_v_k|nm"}, - {ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_v_k|nm"}, - {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_~V_k|nm"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, - "~G_~V_~K|nm"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", suffix: "s"}, - "~G_~V_~K|nm"}, - {ResId{gvKind: gvk.Gvk{}, - name: "nm", suffix: "s"}, - "~G_~V_~K|nm"}, - {ResId{gvKind: gvk.Gvk{}, - suffix: "s"}, - "~G_~V_~K|"}, - {ResId{gvKind: gvk.Gvk{}}, - "~G_~V_~K|"}, - {ResId{}, - "~G_~V_~K|"}, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "g_v_k|nm", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Version: "v", Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_v_k|nm", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{Kind: "k"}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_k|nm", + }, + { + ResId{ + namespace: "ns", + gvKind: gvk.Gvk{}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_~K|nm", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + name: "nm", + prefix: "p", + suffix: "s", + }, + "~G_~V_~K|nm", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + name: "nm", + suffix: "s", + }, + "~G_~V_~K|nm", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + suffix: "s", + }, + "~G_~V_~K|", + }, + { + ResId{ + gvKind: gvk.Gvk{}, + }, + "~G_~V_~K|", + }, + { + ResId{}, + "~G_~V_~K|", + }, } func TestGvknString(t *testing.T) { @@ -85,47 +183,147 @@ func TestGvknString(t *testing.T) { } var GvknEqualsTest = []struct { - x1 ResId - x2 ResId + id1 ResId + id2 ResId + gVknResult bool + nSgVknResult bool }{ - {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, - ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, - {ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, - ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, - {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, - ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, - {ResId{name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, - ResId{name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, + { + id1: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: true, + }, + { + id1: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + namespace: "Z", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: false, + }, + { + id1: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: false, + }, + { + id1: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Version: "v", Kind: "k"}, + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + namespace: "Z", + gvKind: gvk.Gvk{Version: "v", Kind: "k"}, + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: false, + }, + { + id1: ResId{ + namespace: "X", + gvKind: gvk.Gvk{Kind: "k"}, + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + namespace: "Z", + gvKind: gvk.Gvk{Kind: "k"}, + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: false, + }, + { + id1: ResId{ + namespace: "X", + name: "nm", + prefix: "AA", + suffix: "aa", + }, + id2: ResId{ + namespace: "Z", + name: "nm", + prefix: "BB", + suffix: "bb", + }, + gVknResult: true, + nSgVknResult: false, + }, } func TestEquals(t *testing.T) { - for _, hey := range GvknEqualsTest { - if !hey.x1.GvknEquals(hey.x2) { - t.Fatalf("%v should equal %v", hey.x1, hey.x2) + for _, tst := range GvknEqualsTest { + if tst.id1.GvknEquals(tst.id2) != tst.gVknResult { + t.Fatalf("GvknEquals(\n%v,\n%v\n) should be %v", + tst.id1, tst.id2, tst.gVknResult) + } + if tst.id1.NsGvknEquals(tst.id2) != tst.nSgVknResult { + t.Fatalf("NsGvknEquals(\n%v,\n%v\n) should be %v", + tst.id1, tst.id2, tst.nSgVknResult) } } } func TestCopyWithNewPrefixSuffix(t *testing.T) { r1 := ResId{ + namespace: "X", gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, name: "nm", prefix: "a", suffix: "b", - namespace: "X"} + } r2 := r1.CopyWithNewPrefixSuffix("p-", "-s") expected := ResId{ + namespace: "X", gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, name: "nm", prefix: "p-a", suffix: "b-s", - namespace: "X"} + } if !r2.GvknEquals(expected) { t.Fatalf("%v should equal %v", r2, expected) } @@ -133,18 +331,20 @@ func TestCopyWithNewPrefixSuffix(t *testing.T) { func TestCopyWithNewNamespace(t *testing.T) { r1 := ResId{ + namespace: "X", gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, name: "nm", prefix: "a", suffix: "b", - namespace: "X"} + } r2 := r1.CopyWithNewNamespace("zzz") expected := ResId{ + namespace: "zzz", gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, name: "nm", prefix: "a", suffix: "b", - namespace: "zzz"} + } if !r2.GvknEquals(expected) { t.Fatalf("%v should equal %v", r2, expected) } diff --git a/pkg/resmap/factory.go b/pkg/resmap/factory.go index 9e64dbee4..923cde232 100644 --- a/pkg/resmap/factory.go +++ b/pkg/resmap/factory.go @@ -50,7 +50,7 @@ func (rmF *Factory) FromFiles( if err != nil { return nil, errors.Wrap(err, "Load from path "+path+" failed") } - res, err := rmF.newResMapFromBytes(content) + res, err := rmF.NewResMapFromBytes(content) if err != nil { return nil, internal.Handler(err, path) } @@ -60,7 +60,7 @@ func (rmF *Factory) FromFiles( } // newResMapFromBytes decodes a list of objects in byte array format. -func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) { +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/factory_test.go b/pkg/resmap/factory_test.go index 5d20250b1..272871b0f 100644 --- a/pkg/resmap/factory_test.go +++ b/pkg/resmap/factory_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package resmap +package resmap_test import ( "encoding/base64" @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/loader" "sigs.k8s.io/kustomize/pkg/resid" + . "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/types" ) @@ -124,7 +125,7 @@ metadata: }, }), } - m, err := rmF.newResMapFromBytes(encoded) + m, err := rmF.NewResMapFromBytes(encoded) fmt.Printf("%v\n", m) if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index d6936f6d5..bb6dec478 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -32,20 +32,23 @@ import ( // ResMap is a map from ResId to Resource. type ResMap map[resid.ResId]*resource.Resource -// FindByGVKN find the matched ResIds by Group/Version/Kind and Name -func (m ResMap) FindByGVKN(inputId resid.ResId) []resid.ResId { +type IdMatcher func(resid.ResId) bool + +// GetMatchingIds returns a slice of ResId keys from the map +// that all satisfy the given matcher function. +func (m ResMap) GetMatchingIds(matches IdMatcher) []resid.ResId { var result []resid.ResId for id := range m { - if id.GvknEquals(inputId) { + if matches(id) { result = append(result, id) } } return result } -// DemandOneMatchForId find the matched resource by Group/Version/Kind and Name -func (m ResMap) DemandOneMatchForId(inputId resid.ResId) (*resource.Resource, bool) { - result := m.FindByGVKN(inputId) +// DemandOneGvknMatchForId find the matched resource by Group/Version/Kind and Name +func (m ResMap) DemandOneGvknMatchForId(inputId resid.ResId) (*resource.Resource, bool) { + result := m.GetMatchingIds(inputId.GvknEquals) if len(result) == 1 { return m[result[0]], true } @@ -177,7 +180,7 @@ func MergeWithOverride(maps ...ResMap) (ResMap, error) { continue } for id, r := range m { - matchedId := result.FindByGVKN(id) + matchedId := result.GetMatchingIds(id.GvknEquals) if len(matchedId) == 1 { id = matchedId[0] switch r.Behavior() { diff --git a/pkg/resmap/resmap_test.go b/pkg/resmap/resmap_test.go index 7b1f569b1..74a43cdd6 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package resmap +package resmap_test import ( "reflect" @@ -23,6 +23,7 @@ import ( "sigs.k8s.io/kustomize/k8sdeps/kunstruct" "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" ) @@ -71,7 +72,7 @@ metadata: } } -func TestDemandOneMatchForId(t *testing.T) { +func TestDemandOneGvknMatchForId(t *testing.T) { rm1 := ResMap{ resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap( map[string]interface{}{ @@ -91,19 +92,22 @@ func TestDemandOneMatchForId(t *testing.T) { }), } - _, ok := rm1.DemandOneMatchForId(resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1")) + _, ok := rm1.DemandOneGvknMatchForId( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1")) if !ok { t.Fatal("Expected single map entry but got none") } // confirm that ns and prefix are not included in match - _, ok = rm1.DemandOneMatchForId(resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix", "ns")) + _, ok = rm1.DemandOneGvknMatchForId( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix", "ns")) if !ok { t.Fatal("Expected single map entry but got none") } // confirm that name is matched correctly - result, ok := rm1.DemandOneMatchForId(resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns1")) + result, ok := rm1.DemandOneGvknMatchForId( + resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns1")) if ok { t.Fatalf("Expected no map entries but got %v", result) } @@ -111,7 +115,8 @@ func TestDemandOneMatchForId(t *testing.T) { cmap2 := gvk.Gvk{Version: "v2", Kind: "ConfigMap"} // confirm that gvk is matched correctly - result, ok = rm1.DemandOneMatchForId(resid.NewResIdWithPrefixNamespace(cmap2, "cm2", "prefix1", "ns1")) + result, ok = rm1.DemandOneGvknMatchForId( + resid.NewResIdWithPrefixNamespace(cmap2, "cm2", "prefix1", "ns1")) if ok { t.Fatalf("Expected no map entries but got %v", result) } @@ -291,8 +296,73 @@ func TestDeepCopy(t *testing.T) { } } -func TestErrorIfNotEqual(t *testing.T) { +func TestGetMatchingIds(t *testing.T) { + // These ids used as map keys. + // They must be different to avoid overwriting + // map entries during construction. + ids := []resid.ResId{ + resid.NewResId( + gvk.Gvk{Kind: "vegetable"}, + "bedlam"), + resid.NewResId( + gvk.Gvk{Group: "g1", Version: "v1", Kind: "vegetable"}, + "domino"), + resid.NewResIdWithPrefixNamespace( + gvk.Gvk{Kind: "vegetable"}, + "peter", "p", "happy"), + resid.NewResIdWithPrefixNamespace( + gvk.Gvk{Version: "v1", Kind: "fruit"}, + "shatterstar", "p", "happy"), + } + m := ResMap{} + for _, id := range ids { + // Resources values don't matter in this test. + m[id] = nil + } + if len(m) != len(ids) { + t.Fatalf("unexpected map len %d presumably due to duplicate keys", len(m)) + } + + tests := []struct { + name string + matcher IdMatcher + count int + }{ + { + "match everything", + func(resid.ResId) bool { return true }, + 4, + }, + { + "match nothing", + func(resid.ResId) bool { return false }, + 0, + }, + { + "name is peter", + func(x resid.ResId) bool { return x.Name() == "peter" }, + 1, + }, + { + "happy vegetable", + func(x resid.ResId) bool { + return x.Namespace() == "happy" && + x.Gvk().Kind == "vegetable" + }, + 1, + }, + } + for _, tst := range tests { + result := m.GetMatchingIds(tst.matcher) + if len(result) != tst.count { + t.Fatalf("test '%s'; actual: %d, expected: %d", + tst.name, len(result), tst.count) + } + } +} + +func TestErrorIfNotEqual(t *testing.T) { rm1 := ResMap{ resid.NewResId(cmap, "cm1"): rf.FromMap( map[string]interface{}{ @@ -436,7 +506,6 @@ func TestMergeWithoutOverride(t *testing.T) { } func generateMergeFixtures(b types.GenerationBehavior) []ResMap { - input1 := ResMap{ resid.NewResId(cmap, "cmap"): rf.FromMapAndOption( map[string]interface{}{ diff --git a/pkg/target/resaccumulator.go b/pkg/target/resaccumulator.go index 2ae05ba2c..c6ba0cd84 100644 --- a/pkg/target/resaccumulator.go +++ b/pkg/target/resaccumulator.go @@ -103,7 +103,7 @@ func (ra *ResAccumulator) makeVarReplacementMap() (map[string]string, error) { result := map[string]string{} for _, v := range ra.varSet.Set() { id := resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name) - if r, found := ra.resMap.DemandOneMatchForId(id); found { + if r, found := ra.resMap.DemandOneGvknMatchForId(id); found { s, err := r.GetFieldValue(v.FieldRef.FieldPath) if err != nil { return nil, fmt.Errorf("field path err for var: %+v", v) diff --git a/pkg/transformers/namereference.go b/pkg/transformers/namereference.go index 899813776..a4e8a7f8e 100644 --- a/pkg/transformers/namereference.go +++ b/pkg/transformers/namereference.go @@ -89,7 +89,7 @@ func (o *nameReferenceTransformer) updateNameReference( s, _ := in.(string) for id, res := range m { if id.Gvk().IsSelected(&backRef) && id.Name() == s { - matchedIds := m.FindByGVKN(id) + matchedIds := m.GetMatchingIds(id.GvknEquals) // If there's more than one match, there's no way // to know which one to pick, so emit error. if len(matchedIds) > 1 { @@ -115,7 +115,7 @@ func (o *nameReferenceTransformer) updateNameReference( for id, res := range m { indexes := indexOf(id.Name(), names) if id.Gvk().IsSelected(&backRef) && len(indexes) > 0 { - matchedIds := m.FindByGVKN(id) + matchedIds := m.GetMatchingIds(id.GvknEquals) if len(matchedIds) > 1 { return nil, fmt.Errorf( "Multiple matches for name %s:\n %v", id, matchedIds)