diff --git a/pkg/commands/build/testdata/testcase-variable-ref/expected.yaml b/pkg/commands/build/testdata/testcase-variable-ref/expected.yaml index af28d3c61..ab030bf5b 100644 --- a/pkg/commands/build/testdata/testcase-variable-ref/expected.yaml +++ b/pkg/commands/build/testdata/testcase-variable-ref/expected.yaml @@ -77,16 +77,10 @@ metadata: apiVersion: v1 kind: Service metadata: - annotations: - prometheus.io/path: _status/vars - prometheus.io/port: "8080" - prometheus.io/scrape: "true" - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" labels: app: cockroachdb - name: dev-base-cockroachdb + name: dev-base-cockroachdb-public spec: - clusterIP: None ports: - name: grpc port: 26257 @@ -100,10 +94,16 @@ spec: apiVersion: v1 kind: Service metadata: + annotations: + prometheus.io/path: _status/vars + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" labels: app: cockroachdb - name: dev-base-cockroachdb-public + name: dev-base-cockroachdb spec: + clusterIP: None ports: - name: grpc port: 26257 diff --git a/pkg/resid/resid.go b/pkg/resid/resid.go index 57c401153..84d738d1b 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,19 +139,32 @@ 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 } -// 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} +// CopyWithNewPrefixSuffix make a new copy from current ResId and append a new prefix and suffix +func (n ResId) CopyWithNewPrefixSuffix(p, s string) ResId { + 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 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 +175,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 +193,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 bf6b25902..1723616a4 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -119,53 +119,147 @@ func TestDemandOneMatchForId(t *testing.T) { } func TestFilterBy(t *testing.T) { - rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "cm1", + 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{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map", + }, + }), }, - }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "cm2", - }, - }), - } - rm1 := ResMap{ - resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): rf.FromMap( - map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": "cm2", - }, - }), + 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{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "config-map", + }, + }), + }, + 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": { + 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 { - rm1[k] = v - } - - 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) + for name, test := range tests { + 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) + } + }) } } + func TestDeepCopy(t *testing.T) { rm1 := ResMap{ resid.NewResId(cmap, "cm1"): rf.FromMap( diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index 1db5c9a31..5e43fc0aa 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -282,8 +282,11 @@ func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers r = append(r, t) r = append(r, transformers.NewNamespaceTransformer( string(kt.kustomization.Namespace), kt.tConfig.NameSpace)) - t, err = transformers.NewNamePrefixTransformer( - string(kt.kustomization.NamePrefix), kt.tConfig.NamePrefix) + t, err = transformers.NewNamePrefixSuffixTransformer( + string(kt.kustomization.NamePrefix), + "", // TODO(zoncoen): pass the name suffix + kt.tConfig.NamePrefix, + ) if err != nil { return nil, err } diff --git a/pkg/transformers/config/transformerconfig.go b/pkg/transformers/config/transformerconfig.go index 71e8707de..5de589e19 100644 --- a/pkg/transformers/config/transformerconfig.go +++ b/pkg/transformers/config/transformerconfig.go @@ -25,6 +25,7 @@ import ( // TransformerConfig holds the data needed to perform transformations. type TransformerConfig struct { NamePrefix fsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` + NameSuffix fsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"` NameSpace fsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"` CommonLabels fsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,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) } +// 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 func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) { t.CommonLabels = append(t.CommonLabels, fs) @@ -69,6 +75,7 @@ func (t *TransformerConfig) Merge(input *TransformerConfig) *TransformerConfig { } merged := &TransformerConfig{} merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...) + merged.NameSuffix = append(input.NameSuffix, t.NameSuffix...) merged.NameSpace = append(t.NameSpace, input.NameSpace...) merged.CommonAnnotations = append(t.CommonAnnotations, input.CommonAnnotations...) merged.CommonLabels = append(t.CommonLabels, input.CommonLabels...) diff --git a/pkg/transformers/config/transformerconfig_test.go b/pkg/transformers/config/transformerconfig_test.go index b73b01c2e..a12fa6e38 100644 --- a/pkg/transformers/config/transformerconfig_test.go +++ b/pkg/transformers/config/transformerconfig_test.go @@ -61,6 +61,10 @@ func TestAddFieldSpecs(t *testing.T) { if len(cfg.NamePrefix) != 1 { 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) if len(cfg.CommonLabels) != 1 { t.Fatalf("failed to add nameprefix FieldSpec") @@ -117,10 +121,12 @@ func TestMerge(t *testing.T) { cfga := &TransformerConfig{} cfga.AddNamereferenceFieldSpec(nameReference[0]) cfga.AddPrefixFieldSpec(fieldSpecs[0]) + cfga.AddSuffixFieldSpec(fieldSpecs[0]) cfgb := &TransformerConfig{} cfgb.AddNamereferenceFieldSpec(nameReference[1]) cfgb.AddPrefixFieldSpec(fieldSpecs[1]) + cfga.AddSuffixFieldSpec(fieldSpecs[1]) actual := cfga.Merge(cfgb) @@ -128,6 +134,10 @@ func TestMerge(t *testing.T) { t.Fatal("merge failed for namePrefix FieldSpec") } + if len(actual.NameSuffix) != 2 { + t.Fatal("merge failed for nameSuffix FieldSpec") + } + if len(actual.NameReference) != 1 { t.Fatal("merge failed for namereference FieldSpec") } @@ -137,6 +147,8 @@ func TestMerge(t *testing.T) { expected.AddNamereferenceFieldSpec(nameReference[1]) expected.AddPrefixFieldSpec(fieldSpecs[0]) expected.AddPrefixFieldSpec(fieldSpecs[1]) + expected.AddSuffixFieldSpec(fieldSpecs[0]) + expected.AddSuffixFieldSpec(fieldSpecs[1]) if !reflect.DeepEqual(actual, expected) { t.Fatalf("expected: %v\n but got: %v\n", expected, actual) diff --git a/pkg/transformers/prefixname.go b/pkg/transformers/prefixsuffixname.go similarity index 58% rename from pkg/transformers/prefixname.go rename to pkg/transformers/prefixsuffixname.go index 2aa161c12..4dc97aba6 100644 --- a/pkg/transformers/prefixname.go +++ b/pkg/transformers/prefixsuffixname.go @@ -26,40 +26,41 @@ import ( "sigs.k8s.io/kustomize/pkg/transformers/config" ) -// namePrefixTransformer contains the prefix and the FieldSpecs -// for each field needing a name prefix. -type namePrefixTransformer struct { +// namePrefixSuffixTransformer contains the prefix, suffix, and the FieldSpecs +// for each field needing a name prefix and suffix. +type namePrefixSuffixTransformer struct { prefix string + suffix string fieldSpecsToUse []config.FieldSpec fieldSpecsToSkip []config.FieldSpec } -var _ Transformer = &namePrefixTransformer{} +var _ Transformer = &namePrefixSuffixTransformer{} -var prefixFieldSpecsToSkip = []config.FieldSpec{ +var prefixSuffixFieldSpecsToSkip = []config.FieldSpec{ { Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"}, }, } -// deprecateNamePrefixFieldSpec will be moved into prefixFieldSpecsToSkip in next release -var deprecateNamePrefixFieldSpec = config.FieldSpec{ +// deprecateNamePrefixSuffixFieldSpec will be moved into prefixSuffixFieldSpecsToSkip in next release +var deprecateNamePrefixSuffixFieldSpec = config.FieldSpec{ Gvk: gvk.Gvk{Kind: "Namespace"}, } -// NewNamePrefixTransformer construct a namePrefixTransformer. -func NewNamePrefixTransformer(np string, pc []config.FieldSpec) (Transformer, error) { - if len(np) == 0 { +// NewNamePrefixSuffixTransformer construct a namePrefixSuffixTransformer. +func NewNamePrefixSuffixTransformer(np, ns string, pc []config.FieldSpec) (Transformer, error) { + if len(np) == 0 && len(ns) == 0 { return NewNoOpTransformer(), nil } if pc == 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. -func (o *namePrefixTransformer) Transform(m resmap.ResMap) error { +// Transform prepends the name prefix and appends the name suffix. +func (o *namePrefixSuffixTransformer) Transform(m resmap.ResMap) error { // Fill map "mf" with entries subject to name modification, and // delete these entries from "m", so that for now m retains only // the entries whose names will not be modified. @@ -79,29 +80,29 @@ func (o *namePrefixTransformer) Transform(m resmap.ResMap) error { } for id := range mf { - if id.Gvk().IsSelected(&deprecateNamePrefixFieldSpec.Gvk) { - log.Println("Adding nameprefix to Namespace resource will be deprecated in next release.") + if id.Gvk().IsSelected(&deprecateNamePrefixSuffixFieldSpec.Gvk) { + log.Println("Adding nameprefix and namesuffix to Namespace resource will be deprecated in next release.") } objMap := mf[id].Map() for _, path := range o.fieldSpecsToUse { if !id.Gvk().IsSelected(&path.Gvk) { continue } - err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addPrefix) + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addPrefixSuffix) if err != nil { return err } - newId := id.CopyWithNewPrefix(o.prefix) + newId := id.CopyWithNewPrefixSuffix(o.prefix, o.suffix) m[newId] = mf[id] } } return nil } -func (o *namePrefixTransformer) addPrefix(in interface{}) (interface{}, error) { +func (o *namePrefixSuffixTransformer) addPrefixSuffix(in interface{}) (interface{}, error) { s, ok := in.(string) if !ok { 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 } diff --git a/pkg/transformers/prefixname_test.go b/pkg/transformers/prefixsuffixname_test.go similarity index 83% rename from pkg/transformers/prefixname_test.go rename to pkg/transformers/prefixsuffixname_test.go index e384f604b..d9fb9366c 100644 --- a/pkg/transformers/prefixname_test.go +++ b/pkg/transformers/prefixsuffixname_test.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/kustomize/pkg/resource" ) -func TestPrefixNameRun(t *testing.T) { +func TestPrefixSuffixNameRun(t *testing.T) { rf := resource.NewFactory( kunstruct.NewKunstructuredFactoryImpl()) m := resmap.ResMap{ @@ -56,20 +56,20 @@ func TestPrefixNameRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): rf.FromMap( + resid.NewResIdWithPrefixSuffix(cmap, "cm1", "someprefix-", "-somesuffix"): rf.FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", "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{}{ "apiVersion": "v1", "kind": "ConfigMap", "metadata": map[string]interface{}{ - "name": "someprefix-cm2", + "name": "someprefix-cm2-somesuffix", }, }), resid.NewResId(crd, "crd"): rf.FromMap( @@ -82,12 +82,12 @@ func TestPrefixNameRun(t *testing.T) { }), } - npt, err := NewNamePrefixTransformer( - "someprefix-", defaultTransformerConfig.NamePrefix) + npst, err := NewNamePrefixSuffixTransformer( + "someprefix-", "-somesuffix", defaultTransformerConfig.NamePrefix) if err != nil { t.Fatalf("unexpected error: %v", err) } - err = npt.Transform(m) + err = npst.Transform(m) if err != nil { t.Fatalf("unexpected error: %v", err) }