From 93094c78eb99a8c62172c205d38fa14e6b572971 Mon Sep 17 00:00:00 2001 From: zoncoen Date: Wed, 14 Nov 2018 12:45:21 +0900 Subject: [PATCH] add transformer for appending suffix --- .../config/defaultconfig/defaultconfig.go | 2 + .../config/defaultconfig/namesuffix.go | 24 ++++ pkg/transformers/config/transformerconfig.go | 7 ++ .../config/transformerconfig_test.go | 12 ++ pkg/transformers/suffixname.go | 107 ++++++++++++++++++ pkg/transformers/suffixname_test.go | 98 ++++++++++++++++ 6 files changed, 250 insertions(+) create mode 100644 pkg/transformers/config/defaultconfig/namesuffix.go create mode 100644 pkg/transformers/suffixname.go create mode 100644 pkg/transformers/suffixname_test.go diff --git a/pkg/transformers/config/defaultconfig/defaultconfig.go b/pkg/transformers/config/defaultconfig/defaultconfig.go index d96639a8a..0a62e359d 100644 --- a/pkg/transformers/config/defaultconfig/defaultconfig.go +++ b/pkg/transformers/config/defaultconfig/defaultconfig.go @@ -26,6 +26,7 @@ import ( func GetDefaultFieldSpecs() []byte { configData := [][]byte{ []byte(namePrefixFieldSpecs), + []byte(nameSuffixFieldSpecs), []byte(commonLabelFieldSpecs), []byte(commonAnnotationFieldSpecs), []byte(namespaceFieldSpecs), @@ -40,6 +41,7 @@ func GetDefaultFieldSpecs() []byte { func GetDefaultFieldSpecsAsMap() map[string]string { result := make(map[string]string) result["nameprefix"] = namePrefixFieldSpecs + result["namesuffix"] = nameSuffixFieldSpecs result["commonlabels"] = commonLabelFieldSpecs result["commonannotations"] = commonAnnotationFieldSpecs result["namespace"] = namespaceFieldSpecs diff --git a/pkg/transformers/config/defaultconfig/namesuffix.go b/pkg/transformers/config/defaultconfig/namesuffix.go new file mode 100644 index 000000000..eec7ee54a --- /dev/null +++ b/pkg/transformers/config/defaultconfig/namesuffix.go @@ -0,0 +1,24 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + nameSuffixFieldSpecs = ` +nameSuffix: +- path: metadata/name +` +) 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/suffixname.go b/pkg/transformers/suffixname.go new file mode 100644 index 000000000..ccc3d3790 --- /dev/null +++ b/pkg/transformers/suffixname.go @@ -0,0 +1,107 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + "log" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +// nameSuffixTransformer contains the suffix and the FieldSpecs +// for each field needing a name suffix. +type nameSuffixTransformer struct { + suffix string + fieldSpecsToUse []config.FieldSpec + fieldSpecsToSkip []config.FieldSpec +} + +var _ Transformer = &nameSuffixTransformer{} + +var suffixFieldSpecsToSkip = []config.FieldSpec{ + { + Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"}, + }, +} + +// deprecateNameSuffixFieldSpec will be moved into suffixFieldSpecsToSkip in next release +var deprecateNameSuffixFieldSpec = config.FieldSpec{ + Gvk: gvk.Gvk{Kind: "Namespace"}, +} + +// NewNameSuffixTransformer construct a nameSuffixTransformer. +func NewNameSuffixTransformer(ns string, pc []config.FieldSpec) (Transformer, error) { + if len(ns) == 0 { + return NewNoOpTransformer(), nil + } + if pc == nil { + return nil, errors.New("fieldSpecs is not expected to be nil") + } + return &nameSuffixTransformer{fieldSpecsToUse: pc, suffix: ns, fieldSpecsToSkip: suffixFieldSpecsToSkip}, nil +} + +// Transform appends the name suffix. +func (o *nameSuffixTransformer) 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. + mf := resmap.ResMap{} + for id := range m { + found := false + for _, path := range o.fieldSpecsToSkip { + if id.Gvk().IsSelected(&path.Gvk) { + found = true + break + } + } + if !found { + mf[id] = m[id] + delete(m, id) + } + } + + for id := range mf { + if id.Gvk().IsSelected(&deprecateNameSuffixFieldSpec.Gvk) { + log.Println("Adding name suffix 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.addSuffix) + if err != nil { + return err + } + newId := id.CopyWithNewSuffix(o.suffix) + m[newId] = mf[id] + } + } + return nil +} + +func (o *nameSuffixTransformer) addSuffix(in interface{}) (interface{}, error) { + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expectd to be %T", in, s) + } + return s + o.suffix, nil +} diff --git a/pkg/transformers/suffixname_test.go b/pkg/transformers/suffixname_test.go new file mode 100644 index 000000000..6a23930a4 --- /dev/null +++ b/pkg/transformers/suffixname_test.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "reflect" + "testing" + + "sigs.k8s.io/kustomize/k8sdeps/kunstruct" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +func TestSuffixNameRun(t *testing.T) { + rf := resource.NewFactory( + kunstruct.NewKunstructuredFactoryImpl()) + m := resmap.ResMap{ + resid.NewResId(cmap, "cm1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm1", + }, + }), + resid.NewResId(cmap, "cm2"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm2", + }, + }), + resid.NewResId(crd, "crd"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apiextensions.k8s.io/v1beta1", + "kind": "CustomResourceDefinition", + "metadata": map[string]interface{}{ + "name": "crd", + }, + }), + } + expected := resmap.ResMap{ + resid.NewResIdWithSuffix(cmap, "cm1", "-somesuffix"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm1-somesuffix", + }, + }), + resid.NewResIdWithSuffix(cmap, "cm2", "-somesuffix"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm2-somesuffix", + }, + }), + resid.NewResId(crd, "crd"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apiextensions.k8s.io/v1beta1", + "kind": "CustomResourceDefinition", + "metadata": map[string]interface{}{ + "name": "crd", + }, + }), + } + + npt, err := NewNameSuffixTransformer( + "-somesuffix", defaultTransformerConfig.NameSuffix) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = npt.Transform(m) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(m, expected) { + err = expected.ErrorIfNotEqual(m) + t.Fatalf("actual doesn't match expected: %v", err) + } +}