Merge pull request #550 from zoncoen/name-suffix-1

Enable namePrefixTransformer to append name suffix
This commit is contained in:
k8s-ci-robot
2018-11-16 09:07:44 -08:00
committed by GitHub
10 changed files with 303 additions and 116 deletions

View File

@@ -77,16 +77,10 @@ metadata:
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels: labels:
app: cockroachdb app: cockroachdb
name: dev-base-cockroachdb name: dev-base-cockroachdb-public
spec: spec:
clusterIP: None
ports: ports:
- name: grpc - name: grpc
port: 26257 port: 26257
@@ -100,10 +94,16 @@ spec:
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels: labels:
app: cockroachdb app: cockroachdb
name: dev-base-cockroachdb-public name: dev-base-cockroachdb
spec: spec:
clusterIP: None
ports: ports:
- name: grpc - name: grpc
port: 26257 port: 26257

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,19 +139,32 @@ 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
} }
// CopyWithNewPrefix make a new copy from current ResId and append a new prefix // CopyWithNewPrefixSuffix make a new copy from current ResId and append a new prefix and suffix
func (n ResId) CopyWithNewPrefix(p string) ResId { func (n ResId) CopyWithNewPrefixSuffix(p, s string) ResId {
return ResId{gvKind: n.gvKind, name: n.name, prefix: n.concatPrefix(p), namespace: n.namespace} prefix := n.prefix
if p != "" {
prefix = n.concatPrefix(p)
}
suffix := n.suffix
if s != "" {
suffix = n.concatSuffix(s)
}
return ResId{gvKind: n.gvKind, name: n.name, prefix: prefix, suffix: suffix, 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 +175,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 +193,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

@@ -119,53 +119,147 @@ func TestDemandOneMatchForId(t *testing.T) {
} }
func TestFilterBy(t *testing.T) { func TestFilterBy(t *testing.T) {
rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap( tests := map[string]struct {
resMap ResMap
filter resid.ResId
expected ResMap
}{
"different namespace": {
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",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "cm1", "name": "config-map",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap( },
filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix", "namespace2"),
expected: ResMap{},
},
"different prefix": {
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",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "cm2", "name": "config-map",
}, },
}), }),
} },
rm1 := ResMap{ filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix2", "suffix", "namespace"),
resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): rf.FromMap( expected: ResMap{},
},
"different suffix": {
resMap: ResMap{resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix1", "namespace"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "cm2", "name": "config-map",
}, },
}), }),
},
filter: resid.NewResIdWithPrefixSuffixNamespace(cmap, "config-map", "prefix", "suffix2", "namespace"),
expected: ResMap{},
},
"same namespace, same prefix": {
resMap: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map1", "prefix", "namespace"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-map1",
},
}),
},
filter: resid.NewResIdWithPrefixNamespace(cmap, "config-map2", "prefix", "namespace"),
expected: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map1", "prefix", "namespace"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-map1",
},
}),
},
},
"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{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-map",
},
}),
},
filter: resid.NewResId(gvk.Gvk{Kind: "ClusterRoleBinding"}, "cluster-role-binding"),
expected: ResMap{resid.NewResIdWithPrefixNamespace(cmap, "config-map", "prefix", "namespace"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-map",
},
}),
},
},
} }
for k, v := range rm { for name, test := range tests {
rm1[k] = v test := test
t.Run(name, func(t *testing.T) {
got := test.resMap.FilterBy(test.filter)
if !reflect.DeepEqual(test.expected, got) {
t.Fatalf("Expected %v but got back %v", test.expected, got)
}
})
}
} }
empty := rm1.FilterBy(resid.NewResIdWithPrefixNamespace(cmap, "cm4", "prefix1", "ns3"))
if len(empty) != 0 {
t.Fatalf("Expected empty filtered map but got %v", empty)
}
ns1map := rm1.FilterBy(resid.NewResIdWithPrefixNamespace(cmap, "cm4", "prefix1", "ns1"))
if !reflect.DeepEqual(rm, ns1map) {
t.Fatalf("Expected %v but got back %v", rm, ns1map)
}
clmap := rm1.FilterBy(resid.NewResId(gvk.Gvk{Kind: "ClusterRoleBinding"}, "crb"))
if !reflect.DeepEqual(rm1, clmap) {
t.Fatalf("Expected %v but got back %v", rm1, clmap)
}
}
func TestDeepCopy(t *testing.T) { func TestDeepCopy(t *testing.T) {
rm1 := ResMap{ rm1 := ResMap{
resid.NewResId(cmap, "cm1"): rf.FromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(

View File

@@ -282,8 +282,11 @@ func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers
r = append(r, t) r = append(r, t)
r = append(r, transformers.NewNamespaceTransformer( r = append(r, transformers.NewNamespaceTransformer(
string(kt.kustomization.Namespace), kt.tConfig.NameSpace)) string(kt.kustomization.Namespace), kt.tConfig.NameSpace))
t, err = transformers.NewNamePrefixTransformer( t, err = transformers.NewNamePrefixSuffixTransformer(
string(kt.kustomization.NamePrefix), kt.tConfig.NamePrefix) string(kt.kustomization.NamePrefix),
"", // TODO(zoncoen): pass the name suffix
kt.tConfig.NamePrefix,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -25,6 +25,7 @@ import (
// TransformerConfig holds the data needed to perform transformations. // TransformerConfig holds the data needed to perform transformations.
type TransformerConfig struct { type TransformerConfig struct {
NamePrefix fsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` NamePrefix fsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
NameSuffix fsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
NameSpace fsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"` NameSpace fsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
CommonLabels fsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` CommonLabels fsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
@@ -47,6 +48,11 @@ func (t *TransformerConfig) AddPrefixFieldSpec(fs FieldSpec) {
t.NamePrefix = append(t.NamePrefix, fs) t.NamePrefix = append(t.NamePrefix, fs)
} }
// AddSuffixFieldSpec adds a FieldSpec to NameSuffix
func (t *TransformerConfig) AddSuffixFieldSpec(fs FieldSpec) {
t.NameSuffix = append([]FieldSpec{fs}, t.NameSuffix...)
}
// AddLabelFieldSpec adds a FieldSpec to CommonLabels // AddLabelFieldSpec adds a FieldSpec to CommonLabels
func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) { func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) {
t.CommonLabels = append(t.CommonLabels, fs) t.CommonLabels = append(t.CommonLabels, fs)
@@ -69,6 +75,7 @@ func (t *TransformerConfig) Merge(input *TransformerConfig) *TransformerConfig {
} }
merged := &TransformerConfig{} merged := &TransformerConfig{}
merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...) merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...)
merged.NameSuffix = append(input.NameSuffix, t.NameSuffix...)
merged.NameSpace = append(t.NameSpace, input.NameSpace...) merged.NameSpace = append(t.NameSpace, input.NameSpace...)
merged.CommonAnnotations = append(t.CommonAnnotations, input.CommonAnnotations...) merged.CommonAnnotations = append(t.CommonAnnotations, input.CommonAnnotations...)
merged.CommonLabels = append(t.CommonLabels, input.CommonLabels...) merged.CommonLabels = append(t.CommonLabels, input.CommonLabels...)

View File

@@ -61,6 +61,10 @@ func TestAddFieldSpecs(t *testing.T) {
if len(cfg.NamePrefix) != 1 { if len(cfg.NamePrefix) != 1 {
t.Fatalf("failed to add nameprefix FieldSpec") t.Fatalf("failed to add nameprefix FieldSpec")
} }
cfg.AddSuffixFieldSpec(fieldSpec)
if len(cfg.NameSuffix) != 1 {
t.Fatalf("failed to add namesuffix FieldSpec")
}
cfg.AddLabelFieldSpec(fieldSpec) cfg.AddLabelFieldSpec(fieldSpec)
if len(cfg.CommonLabels) != 1 { if len(cfg.CommonLabels) != 1 {
t.Fatalf("failed to add nameprefix FieldSpec") t.Fatalf("failed to add nameprefix FieldSpec")
@@ -117,10 +121,12 @@ func TestMerge(t *testing.T) {
cfga := &TransformerConfig{} cfga := &TransformerConfig{}
cfga.AddNamereferenceFieldSpec(nameReference[0]) cfga.AddNamereferenceFieldSpec(nameReference[0])
cfga.AddPrefixFieldSpec(fieldSpecs[0]) cfga.AddPrefixFieldSpec(fieldSpecs[0])
cfga.AddSuffixFieldSpec(fieldSpecs[0])
cfgb := &TransformerConfig{} cfgb := &TransformerConfig{}
cfgb.AddNamereferenceFieldSpec(nameReference[1]) cfgb.AddNamereferenceFieldSpec(nameReference[1])
cfgb.AddPrefixFieldSpec(fieldSpecs[1]) cfgb.AddPrefixFieldSpec(fieldSpecs[1])
cfga.AddSuffixFieldSpec(fieldSpecs[1])
actual := cfga.Merge(cfgb) actual := cfga.Merge(cfgb)
@@ -128,6 +134,10 @@ func TestMerge(t *testing.T) {
t.Fatal("merge failed for namePrefix FieldSpec") t.Fatal("merge failed for namePrefix FieldSpec")
} }
if len(actual.NameSuffix) != 2 {
t.Fatal("merge failed for nameSuffix FieldSpec")
}
if len(actual.NameReference) != 1 { if len(actual.NameReference) != 1 {
t.Fatal("merge failed for namereference FieldSpec") t.Fatal("merge failed for namereference FieldSpec")
} }
@@ -137,6 +147,8 @@ func TestMerge(t *testing.T) {
expected.AddNamereferenceFieldSpec(nameReference[1]) expected.AddNamereferenceFieldSpec(nameReference[1])
expected.AddPrefixFieldSpec(fieldSpecs[0]) expected.AddPrefixFieldSpec(fieldSpecs[0])
expected.AddPrefixFieldSpec(fieldSpecs[1]) expected.AddPrefixFieldSpec(fieldSpecs[1])
expected.AddSuffixFieldSpec(fieldSpecs[0])
expected.AddSuffixFieldSpec(fieldSpecs[1])
if !reflect.DeepEqual(actual, expected) { if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %v\n but got: %v\n", expected, actual) t.Fatalf("expected: %v\n but got: %v\n", expected, actual)

View File

@@ -26,40 +26,41 @@ import (
"sigs.k8s.io/kustomize/pkg/transformers/config" "sigs.k8s.io/kustomize/pkg/transformers/config"
) )
// namePrefixTransformer contains the prefix and the FieldSpecs // namePrefixSuffixTransformer contains the prefix, suffix, and the FieldSpecs
// for each field needing a name prefix. // for each field needing a name prefix and suffix.
type namePrefixTransformer struct { type namePrefixSuffixTransformer struct {
prefix string prefix string
suffix string
fieldSpecsToUse []config.FieldSpec fieldSpecsToUse []config.FieldSpec
fieldSpecsToSkip []config.FieldSpec fieldSpecsToSkip []config.FieldSpec
} }
var _ Transformer = &namePrefixTransformer{} var _ Transformer = &namePrefixSuffixTransformer{}
var prefixFieldSpecsToSkip = []config.FieldSpec{ var prefixSuffixFieldSpecsToSkip = []config.FieldSpec{
{ {
Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"}, Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"},
}, },
} }
// deprecateNamePrefixFieldSpec will be moved into prefixFieldSpecsToSkip in next release // deprecateNamePrefixSuffixFieldSpec will be moved into prefixSuffixFieldSpecsToSkip in next release
var deprecateNamePrefixFieldSpec = config.FieldSpec{ var deprecateNamePrefixSuffixFieldSpec = config.FieldSpec{
Gvk: gvk.Gvk{Kind: "Namespace"}, Gvk: gvk.Gvk{Kind: "Namespace"},
} }
// NewNamePrefixTransformer construct a namePrefixTransformer. // NewNamePrefixSuffixTransformer construct a namePrefixSuffixTransformer.
func NewNamePrefixTransformer(np string, pc []config.FieldSpec) (Transformer, error) { func NewNamePrefixSuffixTransformer(np, ns string, pc []config.FieldSpec) (Transformer, error) {
if len(np) == 0 { if len(np) == 0 && len(ns) == 0 {
return NewNoOpTransformer(), nil return NewNoOpTransformer(), nil
} }
if pc == nil { if pc == nil {
return nil, errors.New("fieldSpecs is not expected to be nil") return nil, errors.New("fieldSpecs is not expected to be nil")
} }
return &namePrefixTransformer{fieldSpecsToUse: pc, prefix: np, fieldSpecsToSkip: prefixFieldSpecsToSkip}, nil return &namePrefixSuffixTransformer{fieldSpecsToUse: pc, prefix: np, suffix: ns, fieldSpecsToSkip: prefixSuffixFieldSpecsToSkip}, nil
} }
// Transform prepends the name prefix. // Transform prepends the name prefix and appends the name suffix.
func (o *namePrefixTransformer) Transform(m resmap.ResMap) error { func (o *namePrefixSuffixTransformer) Transform(m resmap.ResMap) error {
// Fill map "mf" with entries subject to name modification, and // Fill map "mf" with entries subject to name modification, and
// delete these entries from "m", so that for now m retains only // delete these entries from "m", so that for now m retains only
// the entries whose names will not be modified. // the entries whose names will not be modified.
@@ -79,29 +80,29 @@ func (o *namePrefixTransformer) Transform(m resmap.ResMap) error {
} }
for id := range mf { for id := range mf {
if id.Gvk().IsSelected(&deprecateNamePrefixFieldSpec.Gvk) { if id.Gvk().IsSelected(&deprecateNamePrefixSuffixFieldSpec.Gvk) {
log.Println("Adding nameprefix to Namespace resource will be deprecated in next release.") log.Println("Adding nameprefix and namesuffix to Namespace resource will be deprecated in next release.")
} }
objMap := mf[id].Map() objMap := mf[id].Map()
for _, path := range o.fieldSpecsToUse { for _, path := range o.fieldSpecsToUse {
if !id.Gvk().IsSelected(&path.Gvk) { if !id.Gvk().IsSelected(&path.Gvk) {
continue continue
} }
err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addPrefix) err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addPrefixSuffix)
if err != nil { if err != nil {
return err return err
} }
newId := id.CopyWithNewPrefix(o.prefix) newId := id.CopyWithNewPrefixSuffix(o.prefix, o.suffix)
m[newId] = mf[id] m[newId] = mf[id]
} }
} }
return nil return nil
} }
func (o *namePrefixTransformer) addPrefix(in interface{}) (interface{}, error) { func (o *namePrefixSuffixTransformer) addPrefixSuffix(in interface{}) (interface{}, error) {
s, ok := in.(string) s, ok := in.(string)
if !ok { if !ok {
return nil, fmt.Errorf("%#v is expected to be %T", in, s) return nil, fmt.Errorf("%#v is expected to be %T", in, s)
} }
return o.prefix + s, nil return fmt.Sprintf("%s%s%s", o.prefix, s, o.suffix), nil
} }

View File

@@ -26,7 +26,7 @@ import (
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
) )
func TestPrefixNameRun(t *testing.T) { func TestPrefixSuffixNameRun(t *testing.T) {
rf := resource.NewFactory( rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()) kunstruct.NewKunstructuredFactoryImpl())
m := resmap.ResMap{ m := resmap.ResMap{
@@ -56,20 +56,20 @@ func TestPrefixNameRun(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): rf.FromMap( resid.NewResIdWithPrefixSuffix(cmap, "cm1", "someprefix-", "-somesuffix"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "someprefix-cm1", "name": "someprefix-cm1-somesuffix",
}, },
}), }),
resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): rf.FromMap( resid.NewResIdWithPrefixSuffix(cmap, "cm2", "someprefix-", "-somesuffix"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "someprefix-cm2", "name": "someprefix-cm2-somesuffix",
}, },
}), }),
resid.NewResId(crd, "crd"): rf.FromMap( resid.NewResId(crd, "crd"): rf.FromMap(
@@ -82,12 +82,12 @@ func TestPrefixNameRun(t *testing.T) {
}), }),
} }
npt, err := NewNamePrefixTransformer( npst, err := NewNamePrefixSuffixTransformer(
"someprefix-", defaultTransformerConfig.NamePrefix) "someprefix-", "-somesuffix", defaultTransformerConfig.NamePrefix)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
err = npt.Transform(m) err = npst.Transform(m)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }