add suffix field to ResId

This commit is contained in:
zoncoen
2018-11-14 12:43:49 +09:00
parent a8984578e4
commit a14609f730
4 changed files with 161 additions and 39 deletions

View File

@@ -32,22 +32,46 @@ type ResId struct {
// an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes // an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes
// concatenated together. // concatenated together.
prefix string 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 // namespace the resource belongs to
// an untransformed resource has no namespace, fully transformed resource has the namespace from // an untransformed resource has no namespace, fully transformed resource has the namespace from
// the top most overlay // the top most overlay
namespace string 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 // NewResIdWithPrefixNamespace creates new resource identifier with a prefix and a namespace
func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId { func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId {
return ResId{gvKind: k, name: n, prefix: p, namespace: ns} 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 // NewResIdWithPrefix creates new resource identifier with a prefix
func NewResIdWithPrefix(k gvk.Gvk, n, p string) ResId { func NewResIdWithPrefix(k gvk.Gvk, n, p string) ResId {
return ResId{gvKind: k, name: n, prefix: p} 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 // NewResId creates new resource identifier
func NewResId(k gvk.Gvk, n string) ResId { func NewResId(k gvk.Gvk, n string) ResId {
return ResId{gvKind: k, name: n} return ResId{gvKind: k, name: n}
@@ -62,6 +86,7 @@ const (
noNamespace = "noNamespace" noNamespace = "noNamespace"
noPrefix = "noPrefix" noPrefix = "noPrefix"
noName = "noName" noName = "noName"
noSuffix = "noSuffix"
separator = "|" separator = "|"
) )
@@ -79,9 +104,13 @@ func (n ResId) String() string {
if nm == "" { if nm == "" {
nm = noName nm = noName
} }
s := n.suffix
if s == "" {
s = noSuffix
}
return strings.Join( 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 // 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 // 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 { func (n ResId) GvknEquals(id ResId) bool {
return n.gvKind.Equals(id.gvKind) && n.name == id.name return n.gvKind.Equals(id.gvKind) && n.name == id.name
} }
@@ -110,6 +139,11 @@ func (n ResId) Prefix() string {
return n.prefix return n.prefix
} }
// Suffix returns name suffix.
func (n ResId) Suffix() string {
return n.suffix
}
// Namespace returns resource namespace. // Namespace returns resource namespace.
func (n ResId) Namespace() string { func (n ResId) Namespace() string {
return n.namespace 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 // CopyWithNewPrefix make a new copy from current ResId and append a new prefix
func (n ResId) CopyWithNewPrefix(p string) ResId { 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 // CopyWithNewNamespace make a new copy from current ResId and set a new namespace
func (n ResId) CopyWithNewNamespace(ns string) ResId { 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 // HasSameLeftmostPrefix check if two ResIds have the same
@@ -133,6 +172,14 @@ func (n ResId) HasSameLeftmostPrefix(id ResId) bool {
return prefixes1[0] == prefixes2[0] 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 { func (n ResId) concatPrefix(p string) string {
if p == "" { if p == "" {
return n.prefix return n.prefix
@@ -143,6 +190,20 @@ func (n ResId) concatPrefix(p string) string {
return p + ":" + n.prefix 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 { func (n ResId) prefixList() []string {
return strings.Split(n.prefix, ":") return strings.Split(n.prefix, ":")
} }
func (n ResId) suffixList() []string {
return strings.Split(n.suffix, ":")
}

View File

@@ -11,27 +11,30 @@ var stringTests = []struct {
s string s string
}{ }{
{ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, {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|ns|p|nm"}, "g_v_k|ns|p|nm|s"},
{ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, {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|ns|p|nm"}, "noGroup_v_k|ns|p|nm|s"},
{ResId{gvKind: gvk.Gvk{Kind: "k"}, {ResId{gvKind: gvk.Gvk{Kind: "k"},
name: "nm", prefix: "p", namespace: "ns"}, name: "nm", prefix: "p", suffix: "s", namespace: "ns"},
"noGroup_noVersion_k|ns|p|nm"}, "noGroup_noVersion_k|ns|p|nm|s"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm", prefix: "p", namespace: "ns"}, name: "nm", prefix: "p", suffix: "s", namespace: "ns"},
"noGroup_noVersion_noKind|ns|p|nm"}, "noGroup_noVersion_noKind|ns|p|nm|s"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm", prefix: "p"}, name: "nm", prefix: "p", suffix: "s"},
"noGroup_noVersion_noKind|noNamespace|p|nm"}, "noGroup_noVersion_noKind|noNamespace|p|nm|s"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm"}, name: "nm", suffix: "s"},
"noGroup_noVersion_noKind|noNamespace|noPrefix|nm"}, "noGroup_noVersion_noKind|noNamespace|noPrefix|nm|s"},
{ResId{gvKind: gvk.Gvk{},
suffix: "s"},
"noGroup_noVersion_noKind|noNamespace|noPrefix|noName|s"},
{ResId{gvKind: gvk.Gvk{}}, {ResId{gvKind: gvk.Gvk{}},
"noGroup_noVersion_noKind|noNamespace|noPrefix|noName"}, "noGroup_noVersion_noKind|noNamespace|noPrefix|noName|noSuffix"},
{ResId{}, {ResId{},
"noGroup_noVersion_noKind|noNamespace|noPrefix|noName"}, "noGroup_noVersion_noKind|noNamespace|noPrefix|noName|noSuffix"},
} }
func TestString(t *testing.T) { func TestString(t *testing.T) {
@@ -47,23 +50,26 @@ var gvknStringTests = []struct {
s string s string
}{ }{
{ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, {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"}, "g_v_k|nm"},
{ResId{gvKind: gvk.Gvk{Version: "v", Kind: "k"}, {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"}, "noGroup_v_k|nm"},
{ResId{gvKind: gvk.Gvk{Kind: "k"}, {ResId{gvKind: gvk.Gvk{Kind: "k"},
name: "nm", prefix: "p", namespace: "ns"}, name: "nm", prefix: "p", suffix: "s", namespace: "ns"},
"noGroup_noVersion_k|nm"}, "noGroup_noVersion_k|nm"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm", prefix: "p", namespace: "ns"}, name: "nm", prefix: "p", suffix: "s", namespace: "ns"},
"noGroup_noVersion_noKind|nm"}, "noGroup_noVersion_noKind|nm"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm", prefix: "p"}, name: "nm", prefix: "p", suffix: "s"},
"noGroup_noVersion_noKind|nm"}, "noGroup_noVersion_noKind|nm"},
{ResId{gvKind: gvk.Gvk{}, {ResId{gvKind: gvk.Gvk{},
name: "nm"}, name: "nm", suffix: "s"},
"noGroup_noVersion_noKind|nm"}, "noGroup_noVersion_noKind|nm"},
{ResId{gvKind: gvk.Gvk{},
suffix: "s"},
"noGroup_noVersion_noKind|"},
{ResId{gvKind: gvk.Gvk{}}, {ResId{gvKind: gvk.Gvk{}},
"noGroup_noVersion_noKind|"}, "noGroup_noVersion_noKind|"},
{ResId{}, {ResId{},
@@ -83,19 +89,19 @@ var GvknEqualsTest = []struct {
x2 ResId x2 ResId
}{ }{
{ResId{gvKind: gvk.Gvk{Group: "g", Version: "v", Kind: "k"}, {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"}, 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"}, {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"}, 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"}, {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"}, ResId{gvKind: gvk.Gvk{Kind: "k"},
name: "nm", prefix: "BB", namespace: "Z"}}, name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}},
{ResId{name: "nm", prefix: "AA", namespace: "X"}, {ResId{name: "nm", prefix: "AA", suffix: "aa", namespace: "X"},
ResId{name: "nm", prefix: "BB", namespace: "Z"}}, ResId{name: "nm", prefix: "BB", suffix: "bb", namespace: "Z"}},
} }
func TestEquals(t *testing.T) { func TestEquals(t *testing.T) {

View File

@@ -122,8 +122,8 @@ func (m ResMap) DeepCopy(rf *resource.Factory) ResMap {
} }
// FilterBy returns a subset ResMap containing ResIds with // FilterBy returns a subset ResMap containing ResIds with
// the same namespace and leftmost name prefix as the // the same namespace and leftmost name prefix and rightmost name
// inputId. If inputId is a cluster level resource, this // as the inputId. If inputId is a cluster level resource, this
// returns the original ResMap. // returns the original ResMap.
func (m ResMap) FilterBy(inputId resid.ResId) ResMap { func (m ResMap) FilterBy(inputId resid.ResId) ResMap {
if inputId.Gvk().IsClusterKind() { if inputId.Gvk().IsClusterKind() {
@@ -131,7 +131,7 @@ func (m ResMap) FilterBy(inputId resid.ResId) ResMap {
} }
result := ResMap{} result := ResMap{}
for id, res := range m { 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 result[id] = res
} }
} }

View File

@@ -125,7 +125,7 @@ func TestFilterBy(t *testing.T) {
expected ResMap expected ResMap
}{ }{
"different namespace": { "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{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "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{}, expected: ResMap{},
}, },
"different prefix": { "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{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "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{}, expected: ResMap{},
}, },
"same namespace, same prefix": { "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": { "filter by cluster-level Gvk": {
resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace"): rf.FromMap( resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{