From a14609f73012bcb4b6feae5e880d44c321c7c685 Mon Sep 17 00:00:00 2001 From: zoncoen Date: Wed, 14 Nov 2018 12:43:49 +0900 Subject: [PATCH] add suffix field to ResId --- pkg/resid/resid.go | 69 ++++++++++++++++++++++++++++++++++++--- pkg/resid/resid_test.go | 62 +++++++++++++++++++---------------- pkg/resmap/resmap.go | 6 ++-- pkg/resmap/resmap_test.go | 63 ++++++++++++++++++++++++++++++++--- 4 files changed, 161 insertions(+), 39 deletions(-) diff --git a/pkg/resid/resid.go b/pkg/resid/resid.go index 57c401153..94584dea4 100644 --- a/pkg/resid/resid.go +++ b/pkg/resid/resid.go @@ -32,22 +32,46 @@ type ResId struct { // an untransformed resource has no prefix, 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. + 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 string } +// NewResIdWithPrefixSuffixNamespace creates new resource identifier with a prefix, suffix and a namespace +func NewResIdWithPrefixSuffixNamespace(k gvk.Gvk, n, p, s, ns string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s, namespace: ns} +} + // NewResIdWithPrefixNamespace creates new resource identifier with a prefix and a namespace func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId { return ResId{gvKind: k, name: n, prefix: p, namespace: ns} } +// NewResIdWithSuffixNamespace creates new resource identifier with a suffix and a namespace +func NewResIdWithSuffixNamespace(k gvk.Gvk, n, s, ns string) ResId { + return ResId{gvKind: k, name: n, suffix: s, namespace: ns} +} + +// NewResIdWithPrefixSuffix creates new resource identifier with a prefix and suffix +func NewResIdWithPrefixSuffix(k gvk.Gvk, n, p, s string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s} +} + // NewResIdWithPrefix creates new resource identifier with a prefix func NewResIdWithPrefix(k gvk.Gvk, n, p string) ResId { return ResId{gvKind: k, name: n, prefix: p} } +// NewResIdWithSuffix creates new resource identifier with a suffix +func NewResIdWithSuffix(k gvk.Gvk, n, s string) ResId { + return ResId{gvKind: k, name: n, suffix: s} +} + // NewResId creates new resource identifier func NewResId(k gvk.Gvk, n string) ResId { return ResId{gvKind: k, name: n} @@ -62,6 +86,7 @@ const ( noNamespace = "noNamespace" noPrefix = "noPrefix" noName = "noName" + noSuffix = "noSuffix" separator = "|" ) @@ -79,9 +104,13 @@ func (n ResId) String() string { if nm == "" { nm = noName } + s := n.suffix + if s == "" { + s = noSuffix + } return strings.Join( - []string{n.gvKind.String(), ns, p, nm}, separator) + []string{n.gvKind.String(), ns, p, nm, s}, separator) } // GvknString of ResId based on GVK and name @@ -90,7 +119,7 @@ func (n ResId) GvknString() string { } // GvknEquals return if two ResId have the same Group/Version/Kind and name -// The comparison excludes prefix +// The comparison excludes prefix and suffix func (n ResId) GvknEquals(id ResId) bool { return n.gvKind.Equals(id.gvKind) && n.name == id.name } @@ -110,6 +139,11 @@ func (n ResId) Prefix() string { return n.prefix } +// Suffix returns name suffix. +func (n ResId) Suffix() string { + return n.suffix +} + // Namespace returns resource namespace. func (n ResId) Namespace() string { return n.namespace @@ -117,12 +151,17 @@ func (n ResId) Namespace() string { // CopyWithNewPrefix make a new copy from current ResId and append a new prefix func (n ResId) CopyWithNewPrefix(p string) ResId { - return ResId{gvKind: n.gvKind, name: n.name, prefix: n.concatPrefix(p), namespace: n.namespace} + return ResId{gvKind: n.gvKind, name: n.name, prefix: n.concatPrefix(p), suffix: n.suffix, namespace: n.namespace} +} + +// CopyWithNewSuffix make a new copy from current ResId and append a new suffix +func (n ResId) CopyWithNewSuffix(p string) ResId { + return ResId{gvKind: n.gvKind, name: n.name, prefix: n.prefix, suffix: n.concatSuffix(p), namespace: n.namespace} } // CopyWithNewNamespace make a new copy from current ResId and set a new namespace func (n ResId) CopyWithNewNamespace(ns string) ResId { - return ResId{gvKind: n.gvKind, name: n.name, prefix: n.prefix, namespace: ns} + return ResId{gvKind: n.gvKind, name: n.name, prefix: n.prefix, suffix: n.suffix, namespace: ns} } // HasSameLeftmostPrefix check if two ResIds have the same @@ -133,6 +172,14 @@ func (n ResId) HasSameLeftmostPrefix(id ResId) bool { return prefixes1[0] == prefixes2[0] } +// HasSameRightmostSuffix check if two ResIds have the same +// right most suffix. +func (n ResId) HasSameRightmostSuffix(id ResId) bool { + suffixes1 := n.suffixList() + suffixes2 := id.suffixList() + return suffixes1[len(suffixes1)-1] == suffixes2[len(suffixes2)-1] +} + func (n ResId) concatPrefix(p string) string { if p == "" { return n.prefix @@ -143,6 +190,20 @@ func (n ResId) concatPrefix(p string) string { return p + ":" + n.prefix } +func (n ResId) concatSuffix(s string) string { + if s == "" { + return n.suffix + } + if n.suffix == "" { + return s + } + return n.suffix + ":" + s +} + func (n ResId) prefixList() []string { return strings.Split(n.prefix, ":") } + +func (n ResId) suffixList() []string { + return strings.Split(n.suffix, ":") +} diff --git a/pkg/resid/resid_test.go b/pkg/resid/resid_test.go index 70151bf2e..53fb431d4 100644 --- a/pkg/resid/resid_test.go +++ b/pkg/resid/resid_test.go @@ -11,27 +11,30 @@ var stringTests = []struct { s string }{ {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "p", namespace: "ns"}, - "g_v_k|ns|p|nm"}, + 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", namespace: "ns"}, - "noGroup_v_k|ns|p|nm"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, + "noGroup_v_k|ns|p|nm|s"}, {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "p", namespace: "ns"}, - "noGroup_noVersion_k|ns|p|nm"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, + "noGroup_noVersion_k|ns|p|nm|s"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", namespace: "ns"}, - "noGroup_noVersion_noKind|ns|p|nm"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, + "noGroup_noVersion_noKind|ns|p|nm|s"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p"}, - "noGroup_noVersion_noKind|noNamespace|p|nm"}, + name: "nm", prefix: "p", suffix: "s"}, + "noGroup_noVersion_noKind|noNamespace|p|nm|s"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm"}, - "noGroup_noVersion_noKind|noNamespace|noPrefix|nm"}, + name: "nm", suffix: "s"}, + "noGroup_noVersion_noKind|noNamespace|noPrefix|nm|s"}, + {ResId{gvKind: gvk.Gvk{}, + suffix: "s"}, + "noGroup_noVersion_noKind|noNamespace|noPrefix|noName|s"}, {ResId{gvKind: gvk.Gvk{}}, - "noGroup_noVersion_noKind|noNamespace|noPrefix|noName"}, + "noGroup_noVersion_noKind|noNamespace|noPrefix|noName|noSuffix"}, {ResId{}, - "noGroup_noVersion_noKind|noNamespace|noPrefix|noName"}, + "noGroup_noVersion_noKind|noNamespace|noPrefix|noName|noSuffix"}, } func TestString(t *testing.T) { @@ -47,23 +50,26 @@ var gvknStringTests = []struct { s string }{ {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "p", namespace: "ns"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, "g_v_k|nm"}, {ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "p", namespace: "ns"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, "noGroup_v_k|nm"}, {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "p", namespace: "ns"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, "noGroup_noVersion_k|nm"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p", namespace: "ns"}, + name: "nm", prefix: "p", suffix: "s", namespace: "ns"}, "noGroup_noVersion_noKind|nm"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm", prefix: "p"}, + name: "nm", prefix: "p", suffix: "s"}, "noGroup_noVersion_noKind|nm"}, {ResId{gvKind: gvk.Gvk{}, - name: "nm"}, + name: "nm", suffix: "s"}, "noGroup_noVersion_noKind|nm"}, + {ResId{gvKind: gvk.Gvk{}, + suffix: "s"}, + "noGroup_noVersion_noKind|"}, {ResId{gvKind: gvk.Gvk{}}, "noGroup_noVersion_noKind|"}, {ResId{}, @@ -83,19 +89,19 @@ var GvknEqualsTest = []struct { x2 ResId }{ {ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "AA", namespace: "X"}, + name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, - name: "nm", prefix: "BB", namespace: "Z"}}, + name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, {ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "AA", namespace: "X"}, + name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, - name: "nm", prefix: "BB", namespace: "Z"}}, + name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}}, {ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "AA", namespace: "X"}, + name: "nm", prefix: "AA", suffix: "aa", namespace: "X"}, ResId{gvKind: gvk.Gvk{Kind: "k"}, - name: "nm", prefix: "BB", namespace: "Z"}}, - {ResId{name: "nm", prefix: "AA", namespace: "X"}, - ResId{name: "nm", prefix: "BB", namespace: "Z"}}, + 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"}}, } func TestEquals(t *testing.T) { diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index 2c3f8d543..68c409063 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -122,8 +122,8 @@ func (m ResMap) DeepCopy(rf *resource.Factory) ResMap { } // FilterBy returns a subset ResMap containing ResIds with -// the same namespace and leftmost name prefix as the -// inputId. If inputId is a cluster level resource, this +// the same namespace and leftmost name prefix and rightmost name +// as the inputId. If inputId is a cluster level resource, this // returns the original ResMap. func (m ResMap) FilterBy(inputId resid.ResId) ResMap { if inputId.Gvk().IsClusterKind() { @@ -131,7 +131,7 @@ func (m ResMap) FilterBy(inputId resid.ResId) ResMap { } result := ResMap{} for id, res := range m { - if id.Namespace() == inputId.Namespace() && id.HasSameLeftmostPrefix(inputId) { + if id.Namespace() == inputId.Namespace() && id.HasSameLeftmostPrefix(inputId) && id.HasSameRightmostSuffix(inputId) { result[id] = res } } diff --git a/pkg/resmap/resmap_test.go b/pkg/resmap/resmap_test.go index 3d2216650..1723616a4 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -125,7 +125,7 @@ func TestFilterBy(t *testing.T) { expected ResMap }{ "different namespace": { - resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace1"): rf.FromMap( + resMap: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix", "namespace1"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -134,11 +134,11 @@ func TestFilterBy(t *testing.T) { }, }), }, - filter: resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace2"), + filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix", "namespace2"), expected: ResMap{}, }, "different prefix": { - resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix1", "namespace"): rf.FromMap( + resMap: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix1", "suffix", "namespace"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -147,7 +147,20 @@ func TestFilterBy(t *testing.T) { }, }), }, - filter: resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix2", "namespace"), + filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix2", "suffix", "namespace"), + expected: ResMap{}, + }, + "different suffix": { + resMap: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix1", "namespace"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map", + }, + }), + }, + filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix2", "namespace"), expected: ResMap{}, }, "same namespace, same prefix": { @@ -171,6 +184,48 @@ func TestFilterBy(t *testing.T) { }), }, }, + "same namespace, same suffix": { + resMap: ResMap{resid.NewResIdWithSuffixNamespace(cmap, "config-map1", "suffix", "namespace"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map1", + }, + }), + }, + filter: resid.NewResIdWithSuffixNamespace(cmap, "config-map2", "suffix", "namespace"), + expected: ResMap{resid.NewResIdWithSuffixNamespace(cmap, "config-map1", "suffix", "namespace"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map1", + }, + }), + }, + }, + "same namespace, same prefix, same suffix": { + resMap: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map1", "prefix", "suffix", "namespace"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map", + }, + }), + }, + filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map2", "prefix", "suffix", "namespace"), + expected: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map1", "prefix", "suffix", "namespace"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map", + }, + }), + }, + }, "filter by cluster-level Gvk": { resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace"): rf.FromMap( map[string]interface{}{