mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 10:00:56 +00:00
Function to set labels.
This commit is contained in:
@@ -4,15 +4,18 @@
|
|||||||
package annotations
|
package annotations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type annoMap map[string]string
|
||||||
|
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
// Annotations is the set of annotations to apply to the inputs
|
// Annotations is the set of annotations to apply to the inputs
|
||||||
Annotations map[string]string `yaml:"annotations,omitempty"`
|
Annotations annoMap `yaml:"annotations,omitempty"`
|
||||||
|
|
||||||
// FsSlice contains the FieldSpecs to locate the namespace field
|
// FsSlice contains the FieldSpecs to locate the namespace field
|
||||||
FsSlice types.FsSlice
|
FsSlice types.FsSlice
|
||||||
@@ -21,24 +24,19 @@ type Filter struct {
|
|||||||
var _ kio.Filter = Filter{}
|
var _ kio.Filter = Filter{}
|
||||||
|
|
||||||
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
for i := range nodes {
|
keys := filtersutil.SortedMapKeys(f.Annotations)
|
||||||
if err := f.run(nodes[i]); err != nil {
|
_, err := kio.FilterAll(yaml.FilterFunc(
|
||||||
return nil, err
|
func(node *yaml.RNode) (*yaml.RNode, error) {
|
||||||
}
|
for _, k := range keys {
|
||||||
}
|
if err := node.PipeE(fsslice.Filter{
|
||||||
return nodes, nil
|
FsSlice: f.FsSlice,
|
||||||
}
|
SetValue: fsslice.SetEntry(k, f.Annotations[k]),
|
||||||
|
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
||||||
// run applies the filter to a single node.
|
}); err != nil {
|
||||||
func (f Filter) run(node *yaml.RNode) error {
|
return nil, err
|
||||||
for key, value := range f.Annotations {
|
}
|
||||||
if err := node.PipeE(fsslice.Filter{
|
}
|
||||||
FsSlice: f.FsSlice,
|
return node, nil
|
||||||
SetValue: fsslice.SetEntry(key, value),
|
})).Filter(nodes)
|
||||||
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
return nodes, err
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,17 @@
|
|||||||
package annotations
|
package annotations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var annosFs = builtinconfig.MakeDefaultConfig().CommonAnnotations
|
||||||
|
|
||||||
func TestAnnotations_Filter(t *testing.T) {
|
func TestAnnotations_Filter(t *testing.T) {
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
input string
|
input string
|
||||||
@@ -28,11 +28,9 @@ apiVersion: example.com/v1
|
|||||||
kind: Foo
|
kind: Foo
|
||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: instance
|
||||||
---
|
annotations:
|
||||||
apiVersion: example.com/v1
|
hero: batman
|
||||||
kind: Bar
|
fiend: riddler
|
||||||
metadata:
|
|
||||||
name: instance
|
|
||||||
`,
|
`,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
@@ -40,17 +38,18 @@ kind: Foo
|
|||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: instance
|
||||||
annotations:
|
annotations:
|
||||||
sleater: kinney
|
hero: batman
|
||||||
---
|
fiend: riddler
|
||||||
apiVersion: example.com/v1
|
auto: ford
|
||||||
kind: Bar
|
bean: cannellini
|
||||||
metadata:
|
clown: emmett kelley
|
||||||
name: instance
|
dragon: smaug
|
||||||
annotations:
|
|
||||||
sleater: kinney
|
|
||||||
`,
|
`,
|
||||||
filter: Filter{Annotations: map[string]string{
|
filter: Filter{Annotations: annoMap{
|
||||||
"sleater": "kinney",
|
"clown": "emmett kelley",
|
||||||
|
"auto": "ford",
|
||||||
|
"dragon": "smaug",
|
||||||
|
"bean": "cannellini",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
@@ -60,7 +59,8 @@ kind: Foo
|
|||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: instance
|
||||||
annotations:
|
annotations:
|
||||||
foo: foo
|
hero: batman
|
||||||
|
fiend: riddler
|
||||||
`,
|
`,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
@@ -68,10 +68,16 @@ kind: Foo
|
|||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: instance
|
||||||
annotations:
|
annotations:
|
||||||
foo: bar
|
hero: superman
|
||||||
|
fiend: luthor
|
||||||
|
bean: cannellini
|
||||||
|
clown: emmett kelley
|
||||||
`,
|
`,
|
||||||
filter: Filter{Annotations: map[string]string{
|
filter: Filter{Annotations: annoMap{
|
||||||
"foo": "bar",
|
"clown": "emmett kelley",
|
||||||
|
"hero": "superman",
|
||||||
|
"fiend": "luthor",
|
||||||
|
"bean": "cannellini",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
"data-fieldspecs": {
|
"data-fieldspecs": {
|
||||||
@@ -107,7 +113,7 @@ a:
|
|||||||
b:
|
b:
|
||||||
sleater: kinney
|
sleater: kinney
|
||||||
`,
|
`,
|
||||||
filter: Filter{Annotations: map[string]string{
|
filter: Filter{Annotations: annoMap{
|
||||||
"sleater": "kinney",
|
"sleater": "kinney",
|
||||||
}},
|
}},
|
||||||
fsslice: []types.FieldSpec{
|
fsslice: []types.FieldSpec{
|
||||||
@@ -121,126 +127,13 @@ a:
|
|||||||
|
|
||||||
for tn, tc := range testCases {
|
for tn, tc := range testCases {
|
||||||
t.Run(tn, func(t *testing.T) {
|
t.Run(tn, func(t *testing.T) {
|
||||||
config := builtinconfig.MakeDefaultConfig()
|
|
||||||
|
|
||||||
filter := tc.filter
|
filter := tc.filter
|
||||||
filter.FsSlice = append(config.CommonAnnotations, tc.fsslice...)
|
filter.FsSlice = append(annosFs, tc.fsslice...)
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
rw := kio.ByteReadWriter{
|
|
||||||
Reader: bytes.NewBufferString(tc.input),
|
|
||||||
Writer: &out,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := kio.Pipeline{
|
|
||||||
Inputs: []kio.Reader{&rw},
|
|
||||||
Filters: []kio.Filter{filter},
|
|
||||||
Outputs: []kio.Writer{&rw},
|
|
||||||
}.Execute()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
strings.TrimSpace(tc.expectedOutput),
|
strings.TrimSpace(tc.expectedOutput),
|
||||||
strings.TrimSpace(out.String())) {
|
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnotations_Filter_Multiple(t *testing.T) {
|
|
||||||
input := `
|
|
||||||
apiVersion: example.com/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
name: instance
|
|
||||||
---
|
|
||||||
apiVersion: example.com/v1
|
|
||||||
kind: Bar
|
|
||||||
metadata:
|
|
||||||
name: instance
|
|
||||||
`
|
|
||||||
annos := map[string]string{
|
|
||||||
"sleater": "kinney",
|
|
||||||
"sonic": "youth",
|
|
||||||
}
|
|
||||||
config := builtinconfig.MakeDefaultConfig()
|
|
||||||
filter := Filter{Annotations: annos}
|
|
||||||
filter.FsSlice = config.CommonAnnotations
|
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
rw := kio.ByteReadWriter{
|
|
||||||
Reader: bytes.NewBufferString(input),
|
|
||||||
Writer: &out,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := kio.Pipeline{
|
|
||||||
Inputs: []kio.Reader{&rw},
|
|
||||||
Filters: []kio.Filter{filter},
|
|
||||||
Outputs: []kio.Writer{&rw},
|
|
||||||
}.Execute()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertHasAnnotation(t, out.String(), annos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertHasAnnotation(t *testing.T, y string, exp map[string]string) bool {
|
|
||||||
var out bytes.Buffer
|
|
||||||
rw := kio.ByteReadWriter{
|
|
||||||
Reader: bytes.NewBufferString(y),
|
|
||||||
Writer: &out,
|
|
||||||
}
|
|
||||||
filter := &captureAnnotationFilter{
|
|
||||||
annotations: make(map[string]annotations),
|
|
||||||
}
|
|
||||||
err := kio.Pipeline{
|
|
||||||
Inputs: []kio.Reader{&rw},
|
|
||||||
Filters: []kio.Filter{filter},
|
|
||||||
Outputs: []kio.Writer{&rw},
|
|
||||||
}.Execute()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, annos := range filter.annotations {
|
|
||||||
for key, val := range exp {
|
|
||||||
v, found := annos[key]
|
|
||||||
if !found {
|
|
||||||
t.Errorf("expected annotation with key %s in object %s, but didn't find it",
|
|
||||||
key, name)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if want, got := val, v; got != want {
|
|
||||||
t.Errorf("exected annotation %s in object %s to have value %s, but found %s",
|
|
||||||
key, name, want, got)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type annotations map[string]string
|
|
||||||
|
|
||||||
type captureAnnotationFilter struct {
|
|
||||||
annotations map[string]annotations
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c captureAnnotationFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode,
|
|
||||||
error) {
|
|
||||||
for _, n := range nodes {
|
|
||||||
meta, err := n.GetMeta()
|
|
||||||
if err != nil {
|
|
||||||
return nodes, err
|
|
||||||
}
|
|
||||||
name := meta.Name
|
|
||||||
annos := meta.Annotations
|
|
||||||
c.annotations[name] = annos
|
|
||||||
}
|
|
||||||
return nodes, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,11 +5,25 @@ package filtersutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SortedMapKeys returns a sorted slice of keys to the given map.
|
||||||
|
// Writing this function never gets old.
|
||||||
|
func SortedMapKeys(m map[string]string) []string {
|
||||||
|
keys := make([]string, len(m))
|
||||||
|
i := 0
|
||||||
|
for k := range m {
|
||||||
|
keys[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
// ApplyToJSON applies the filter to the json objects.
|
// ApplyToJSON applies the filter to the json objects.
|
||||||
func ApplyToJSON(filter kio.Filter, objs ...marshalerUnmarshaler) error {
|
func ApplyToJSON(filter kio.Filter, objs ...marshalerUnmarshaler) error {
|
||||||
var nodes []*yaml.RNode
|
var nodes []*yaml.RNode
|
||||||
|
|||||||
@@ -11,6 +11,32 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSortedKeys(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
input map[string]string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
"empty": {
|
||||||
|
input: map[string]string{},
|
||||||
|
expected: []string{}},
|
||||||
|
"one": {
|
||||||
|
input: map[string]string{"a": "aaa"},
|
||||||
|
expected: []string{"a"}},
|
||||||
|
"three": {
|
||||||
|
input: map[string]string{"c": "ccc", "b": "bbb", "a": "aaa"},
|
||||||
|
expected: []string{"a", "b", "c"}},
|
||||||
|
}
|
||||||
|
for tn, tc := range testCases {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
if !assert.Equal(t,
|
||||||
|
filtersutil.SortedMapKeys(tc.input),
|
||||||
|
tc.expected) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestApplyToJSON(t *testing.T) {
|
func TestApplyToJSON(t *testing.T) {
|
||||||
instance1 := bytes.NewBufferString(`{"kind": "Foo"}`)
|
instance1 := bytes.NewBufferString(`{"kind": "Foo"}`)
|
||||||
instance2 := bytes.NewBufferString(`{"kind": "Bar"}`)
|
instance2 := bytes.NewBufferString(`{"kind": "Bar"}`)
|
||||||
|
|||||||
6
api/filters/labels/doc.go
Normal file
6
api/filters/labels/doc.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package labels contains a kio.Filter implementation of the kustomize
|
||||||
|
// labels transformer.
|
||||||
|
package labels
|
||||||
55
api/filters/labels/example_test.go
Normal file
55
api/filters/labels/example_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package labels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleFilter() {
|
||||||
|
fss := builtinconfig.MakeDefaultConfig().CommonLabels
|
||||||
|
err := kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
---
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Bar
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
`)}},
|
||||||
|
Filters: []kio.Filter{Filter{
|
||||||
|
Labels: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
FsSlice: fss,
|
||||||
|
}},
|
||||||
|
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
|
||||||
|
}.Execute()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// apiVersion: example.com/v1
|
||||||
|
// kind: Foo
|
||||||
|
// metadata:
|
||||||
|
// name: instance
|
||||||
|
// labels:
|
||||||
|
// foo: bar
|
||||||
|
// ---
|
||||||
|
// apiVersion: example.com/v1
|
||||||
|
// kind: Bar
|
||||||
|
// metadata:
|
||||||
|
// name: instance
|
||||||
|
// labels:
|
||||||
|
// foo: bar
|
||||||
|
}
|
||||||
43
api/filters/labels/labels.go
Normal file
43
api/filters/labels/labels.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package labels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||||
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type labelMap map[string]string
|
||||||
|
|
||||||
|
// Filter sets labels.
|
||||||
|
type Filter struct {
|
||||||
|
// Labels is the set of labels to apply to the inputs
|
||||||
|
Labels labelMap `yaml:"labels,omitempty"`
|
||||||
|
|
||||||
|
// FsSlice identifies the label fields.
|
||||||
|
FsSlice types.FsSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ kio.Filter = Filter{}
|
||||||
|
|
||||||
|
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
|
keys := filtersutil.SortedMapKeys(f.Labels)
|
||||||
|
_, err := kio.FilterAll(yaml.FilterFunc(
|
||||||
|
func(node *yaml.RNode) (*yaml.RNode, error) {
|
||||||
|
for _, k := range keys {
|
||||||
|
if err := node.PipeE(fsslice.Filter{
|
||||||
|
FsSlice: f.FsSlice,
|
||||||
|
SetValue: fsslice.SetEntry(k, f.Labels[k]),
|
||||||
|
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node, nil
|
||||||
|
})).Filter(nodes)
|
||||||
|
return nodes, err
|
||||||
|
}
|
||||||
139
api/filters/labels/labels_test.go
Normal file
139
api/filters/labels/labels_test.go
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package labels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var labelsFs = builtinconfig.MakeDefaultConfig().CommonLabels
|
||||||
|
|
||||||
|
func TestLabels_Filter(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
input string
|
||||||
|
expectedOutput string
|
||||||
|
filter Filter
|
||||||
|
fsSlice types.FsSlice
|
||||||
|
}{
|
||||||
|
"add": {
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
hero: batman
|
||||||
|
fiend: riddler
|
||||||
|
`,
|
||||||
|
expectedOutput: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
hero: batman
|
||||||
|
fiend: riddler
|
||||||
|
auto: ford
|
||||||
|
bean: cannellini
|
||||||
|
clown: emmett kelley
|
||||||
|
dragon: smaug
|
||||||
|
`,
|
||||||
|
filter: Filter{Labels: labelMap{
|
||||||
|
"clown": "emmett kelley",
|
||||||
|
"auto": "ford",
|
||||||
|
"dragon": "smaug",
|
||||||
|
"bean": "cannellini",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
hero: batman
|
||||||
|
fiend: riddler
|
||||||
|
`,
|
||||||
|
expectedOutput: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
hero: superman
|
||||||
|
fiend: luthor
|
||||||
|
bean: cannellini
|
||||||
|
clown: emmett kelley
|
||||||
|
`,
|
||||||
|
filter: Filter{Labels: labelMap{
|
||||||
|
"clown": "emmett kelley",
|
||||||
|
"hero": "superman",
|
||||||
|
"fiend": "luthor",
|
||||||
|
"bean": "cannellini",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"data-fieldspecs": {
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
---
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Bar
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
`,
|
||||||
|
expectedOutput: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
sleater: kinney
|
||||||
|
a:
|
||||||
|
b:
|
||||||
|
sleater: kinney
|
||||||
|
---
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Bar
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
sleater: kinney
|
||||||
|
a:
|
||||||
|
b:
|
||||||
|
sleater: kinney
|
||||||
|
`,
|
||||||
|
filter: Filter{Labels: labelMap{
|
||||||
|
"sleater": "kinney",
|
||||||
|
}},
|
||||||
|
fsSlice: []types.FieldSpec{
|
||||||
|
{
|
||||||
|
Path: "a/b",
|
||||||
|
CreateIfNotPresent: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tn, tc := range testCases {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
filter := tc.filter
|
||||||
|
filter.FsSlice = append(labelsFs, tc.fsSlice...)
|
||||||
|
if !assert.Equal(t,
|
||||||
|
strings.TrimSpace(tc.expectedOutput),
|
||||||
|
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,19 +21,14 @@ type Filter struct {
|
|||||||
var _ kio.Filter = Filter{}
|
var _ kio.Filter = Filter{}
|
||||||
|
|
||||||
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
for i := range nodes {
|
return kio.FilterAll(yaml.FilterFunc(ns.run)).Filter(nodes)
|
||||||
if err := ns.run(nodes[i]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the filter on a single node rather than a slice
|
// Run runs the filter on a single node rather than a slice
|
||||||
func (ns Filter) run(node *yaml.RNode) error {
|
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
||||||
// hacks for hardcoded types -- :(
|
// hacks for hardcoded types -- :(
|
||||||
if err := ns.hacks(node); err != nil {
|
if err := ns.hacks(node); err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the fieldspecs that are for hardcoded fields. The fieldspecs
|
// Remove the fieldspecs that are for hardcoded fields. The fieldspecs
|
||||||
@@ -45,11 +40,12 @@ func (ns Filter) run(node *yaml.RNode) error {
|
|||||||
ns.FsSlice = ns.removeFieldSpecsForHacks(ns.FsSlice)
|
ns.FsSlice = ns.removeFieldSpecsForHacks(ns.FsSlice)
|
||||||
|
|
||||||
// transformations based on data -- :)
|
// transformations based on data -- :)
|
||||||
return node.PipeE(fsslice.Filter{
|
err := node.PipeE(fsslice.Filter{
|
||||||
FsSlice: ns.FsSlice,
|
FsSlice: ns.FsSlice,
|
||||||
SetValue: fsslice.SetScalar(ns.Namespace),
|
SetValue: fsslice.SetScalar(ns.Namespace),
|
||||||
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
||||||
})
|
})
|
||||||
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// hacks applies the namespace transforms that are hardcoded rather
|
// hacks applies the namespace transforms that are hardcoded rather
|
||||||
|
|||||||
@@ -4,15 +4,14 @@
|
|||||||
package namespace_test
|
package namespace_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filters/namespace"
|
"sigs.k8s.io/kustomize/api/filters/namespace"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var tests = []TestCase{
|
var tests = []TestCase{
|
||||||
@@ -270,27 +269,10 @@ func TestNamespace_Filter(t *testing.T) {
|
|||||||
test := tests[i]
|
test := tests[i]
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
test.filter.FsSlice = append(config.NameSpace, test.fsslice...)
|
test.filter.FsSlice = append(config.NameSpace, test.fsslice...)
|
||||||
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
rw := &kio.ByteReadWriter{
|
|
||||||
Reader: bytes.NewBufferString(test.input),
|
|
||||||
Writer: out,
|
|
||||||
}
|
|
||||||
|
|
||||||
// run the filter
|
|
||||||
err := kio.Pipeline{
|
|
||||||
Inputs: []kio.Reader{rw},
|
|
||||||
Filters: []kio.Filter{test.filter},
|
|
||||||
Outputs: []kio.Writer{rw},
|
|
||||||
}.Execute()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
// check results
|
|
||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
strings.TrimSpace(test.expected),
|
strings.TrimSpace(test.expected),
|
||||||
strings.TrimSpace(out.String())) {
|
strings.TrimSpace(
|
||||||
|
filtertest_test.RunFilter(t, test.input, test.filter))) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
30
api/testutils/filtertest/runfilter.go
Normal file
30
api/testutils/filtertest/runfilter.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filtertest_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunFilter(t *testing.T, input string, f kio.Filter) string {
|
||||||
|
var out bytes.Buffer
|
||||||
|
rw := kio.ByteReadWriter{
|
||||||
|
Reader: bytes.NewBufferString(input),
|
||||||
|
Writer: &out,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{&rw},
|
||||||
|
Filters: []kio.Filter{f},
|
||||||
|
Outputs: []kio.Writer{&rw},
|
||||||
|
}.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user