diff --git a/kyaml/fn/framework/example_test.go b/kyaml/fn/framework/example_test.go index 477c45c16..cd6c3af15 100644 --- a/kyaml/fn/framework/example_test.go +++ b/kyaml/fn/framework/example_test.go @@ -603,3 +603,186 @@ func ExampleTemplateCommand_files() { // annotations: // a: b } + +// ExampleTemplateCommand_preprocess provides an example for using the TemplateCommand +// with PreProcess to configure the template based on the input resources observed. +func ExampleTemplateCommand_preprocess() { + config := &struct { + Key string `json:"key" yaml:"key"` + Value string `json:"value" yaml:"value"` + Short bool + }{} + + // create the template + cmd := framework.TemplateCommand{ + // Template input + API: config, + PreProcess: func(rl *framework.ResourceList) error { + config.Short = len(rl.Items) < 3 + return nil + }, + // Template + Template: template.Must(template.New("example").Parse(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +{{- if .Short }} + short: 'true' +{{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bar + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +{{- if .Short }} + short: 'true' +{{- end }} +`)), + }.GetCommand() + + cmd.SetArgs([]string{filepath.Join("testdata", "template", "config.yaml")}) + if err := cmd.Execute(); err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%v\n", err) + } + + // Output: + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: foo + // namespace: default + // annotations: + // a: b + // short: 'true' + // --- + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: bar + // namespace: default + // annotations: + // a: b + // short: 'true' +} + +// ExampleTemplateCommand_postprocess provides an example for using the TemplateCommand +// with PostProcess to modify the results. +func ExampleTemplateCommand_postprocess() { + config := &struct { + Key string `json:"key" yaml:"key"` + Value string `json:"value" yaml:"value"` + }{} + + // create the template + cmd := framework.TemplateCommand{ + // Template input + API: config, + // Template + Template: template.Must(template.New("example").Parse(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bar + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +`)), + PostProcess: func(rl *framework.ResourceList) error { + // trim the first resources + rl.Items = rl.Items[1:] + return nil + }, + }.GetCommand() + + cmd.SetArgs([]string{filepath.Join("testdata", "template", "config.yaml")}) + if err := cmd.Execute(); err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%v\n", err) + } + + // Output: + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: bar + // namespace: default + // annotations: + // a: b +} + +// ExampleTemplateCommand_patch provides an example for using the TemplateCommand to +// create a function which patches resources. +func ExampleTemplateCommand_patch() { + // patch the foo resource only + s := framework.Selector{Names: []string{"foo"}} + + cmd := framework.TemplateCommand{ + API: &struct { + Key string `json:"key" yaml:"key"` + Value string `json:"value" yaml:"value"` + }{}, + Template: template.Must(template.New("example").Parse(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bar + namespace: default + annotations: + {{ .Key }}: {{ .Value }} +`)), + // PatchTemplates are applied to BOTH ResourceList input resources AND templated resources + PatchTemplates: []framework.PatchTemplate{{ + Selector: &s, + Template: template.Must(template.New("test").Parse(` +metadata: + annotations: + patched: 'true' +`)), + }}, + }.GetCommand() + + cmd.SetArgs([]string{filepath.Join("testdata", "template", "config.yaml")}) + if err := cmd.Execute(); err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%v\n", err) + } + + // Output: + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: foo + // namespace: default + // annotations: + // a: b + // patched: 'true' + // --- + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: bar + // namespace: default + // annotations: + // a: b +} diff --git a/kyaml/fn/framework/framework.go b/kyaml/fn/framework/framework.go index e45f78b02..3af4d3854 100644 --- a/kyaml/fn/framework/framework.go +++ b/kyaml/fn/framework/framework.go @@ -256,6 +256,9 @@ type TemplateCommand struct { // Templates is a list of templates to render. Templates []*template.Template + // PatchTemplates is a list of templates to render into Patches and apply. + PatchTemplates []PatchTemplate + // TemplateFiles list of templates to read from disk which are appended // to Templates. TemplatesFiles []string @@ -342,6 +345,12 @@ func (tc TemplateCommand) GetCommand() cobra.Command { } } + for i := range tc.PatchTemplates { + if err := tc.PatchTemplates[i].Apply(&rl); err != nil { + return err + } + } + var err error if tc.MergeResources { rl.Items, err = filters.MergeFilter{}.Filter(rl.Items) diff --git a/kyaml/fn/framework/frameworktestutil/frameworktestutil.go b/kyaml/fn/framework/frameworktestutil/frameworktestutil.go index a6dfabda5..785df9c4e 100644 --- a/kyaml/fn/framework/frameworktestutil/frameworktestutil.go +++ b/kyaml/fn/framework/frameworktestutil/frameworktestutil.go @@ -35,10 +35,10 @@ type ResultsChecker struct { // Defaults to "input*.yaml" InputFilenameGlob string - // ExpectedOutputFilname is the file with the expected output of the function + // ExpectedOutputFilename is the file with the expected output of the function // Defaults to "expected.yaml". Directories containing neither this file // nore ExpectedErrorFilename will be skipped. - ExpectedOutputFilname string + ExpectedOutputFilename string // ExpectedErrorFilename is the file containing part of an expected error message // Defaults to "error.yaml". Directories containing neither this file @@ -57,8 +57,8 @@ func (rc ResultsChecker) Assert(t *testing.T) bool { if rc.ConfigInputFilename == "" { rc.ConfigInputFilename = "config.yaml" } - if rc.ExpectedOutputFilname == "" { - rc.ExpectedOutputFilname = "expected.yaml" + if rc.ExpectedOutputFilename == "" { + rc.ExpectedOutputFilename = "expected.yaml" } if rc.ExpectedErrorFilename == "" { rc.ExpectedErrorFilename = "error.yaml" @@ -90,64 +90,67 @@ func (rc ResultsChecker) compare(t *testing.T, path string) { // missing input return } - if !assert.NoError(t, err) { - t.FailNow() - } args := []string{configPath} - if rc.InputFilenameGlob != "" { - inputs, err := filepath.Glob(filepath.Join(path, rc.InputFilenameGlob)) - if !assert.NoError(t, err) { - t.FailNow() - } - args = append(args, inputs...) - } - - var actualOutput, actualError bytes.Buffer - cmd := rc.Command() - cmd.SetArgs(args) - cmd.SetOut(&actualOutput) - cmd.SetErr(&actualError) - expectedOutput, expectedError := rc.getExpected(t, path) if expectedError == "" && expectedOutput == "" { // missing expected return } + if !assert.NoError(t, err) { + t.FailNow() + } - err = cmd.Execute() + // run the test + t.Run(path, func(t *testing.T) { + if rc.InputFilenameGlob != "" { + inputs, err := filepath.Glob(filepath.Join(path, rc.InputFilenameGlob)) + if !assert.NoError(t, err) { + t.FailNow() + } + args = append(args, inputs...) + } - // Compae the results - if expectedError != "" && !assert.Error(t, err, actualOutput.String()) { - t.FailNow() - } - if expectedError == "" && !assert.NoError(t, err, actualError.String()) { - t.FailNow() - } - if !assert.Equal(t, - strings.TrimSpace(expectedOutput), - strings.TrimSpace(actualOutput.String()), actualError.String()) { - t.FailNow() - } - if !assert.Contains(t, - strings.TrimSpace(actualError.String()), - strings.TrimSpace(expectedError), actualOutput.String()) { - t.FailNow() - } + var actualOutput, actualError bytes.Buffer + cmd := rc.Command() + cmd.SetArgs(args) + cmd.SetOut(&actualOutput) + cmd.SetErr(&actualError) + + err = cmd.Execute() + + // Compae the results + if expectedError != "" && !assert.Error(t, err, actualOutput.String()) { + t.FailNow() + } + if expectedError == "" && !assert.NoError(t, err, actualError.String()) { + t.FailNow() + } + if !assert.Equal(t, + strings.TrimSpace(expectedOutput), + strings.TrimSpace(actualOutput.String()), actualError.String()) { + t.FailNow() + } + if !assert.Contains(t, + strings.TrimSpace(actualError.String()), + strings.TrimSpace(expectedError), actualOutput.String()) { + t.FailNow() + } + }) } // getExpected reads the expected results and error files func (rc ResultsChecker) getExpected(t *testing.T, path string) (string, string) { // read the expected results var expectedOutput, expectedError string - if rc.ExpectedOutputFilname != "" { - _, err := os.Stat(filepath.Join(path, rc.ExpectedOutputFilname)) + if rc.ExpectedOutputFilename != "" { + _, err := os.Stat(filepath.Join(path, rc.ExpectedOutputFilename)) if !os.IsNotExist(err) && err != nil { t.FailNow() } if err == nil { // only read the file if it exists - b, err := ioutil.ReadFile(filepath.Join(path, rc.ExpectedOutputFilname)) + b, err := ioutil.ReadFile(filepath.Join(path, rc.ExpectedOutputFilename)) if !assert.NoError(t, err) { t.FailNow() } diff --git a/kyaml/fn/framework/patch.go b/kyaml/fn/framework/patch.go new file mode 100644 index 000000000..c8654bf31 --- /dev/null +++ b/kyaml/fn/framework/patch.go @@ -0,0 +1,202 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package framework + +import ( + "bytes" + "fmt" + "strings" + "text/template" + + "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/sets" + "sigs.k8s.io/kustomize/kyaml/yaml" + "sigs.k8s.io/kustomize/kyaml/yaml/merge2" +) + +// Applier applies some modification to a ResourceList +type Applier interface { + Apply(rl *ResourceList) error +} + +var _ Applier = PatchTemplate{} + +// PatchTemplate applies a patch to a collection of Resources +type PatchTemplate struct { + // Template is a template to render into one or more patches. + Template *template.Template + + // Selector targets the rendered patch to specific resources. + Selector *Selector +} + +// Apply applies the patch to all matching resources in the list. The rl.FunctionConfig +// is provided to the template as input. +func (p PatchTemplate) Apply(rl *ResourceList) error { + if p.Selector == nil { + // programming error -- user shouldn't see this + return errors.Errorf("must specify PatchTemplate.Selector") + } + + matches, err := p.Selector.GetMatches(rl) + if err != nil { + return err + } + if len(matches) == 0 { + return nil + } + return p.apply(rl, p.Template, matches) +} + +func (p *PatchTemplate) apply(rl *ResourceList, t *template.Template, matches []*yaml.RNode) error { + // render the patches + var b bytes.Buffer + if err := t.Execute(&b, rl.FunctionConfig); err != nil { + return errors.WrapPrefixf(err, "failed to render patch template %v", t.DefinedTemplates()) + } + + // parse the patches into RNodes + var nodes []*yaml.RNode + for _, s := range strings.Split(b.String(), "\n---\n") { + s = strings.TrimSpace(s) + if s == "" { + continue + } + newNodes, err := (&kio.ByteReader{Reader: bytes.NewBufferString(s)}).Read() + if err != nil { + // create the debug string + lines := strings.Split(s, "\n") + for j := range lines { + lines[j] = fmt.Sprintf("%03d %s", j+1, lines[j]) + } + s = strings.Join(lines, "\n") + return errors.WrapPrefixf(err, "failed to parse rendered patch template into a resource:\n%s\n", s) + } + nodes = append(nodes, newNodes...) + } + + // apply the patches to the matching resources + var err error + for j := range matches { + for i := range nodes { + matches[j], err = merge2.Merge(nodes[i], p.Selector.matches[j], yaml.MergeOptions{}) + if err != nil { + return errors.WrapPrefixf(err, "failed to merge templated patch") + } + } + } + return nil +} + +// Selector matches resources. A resource matches if and only if ALL of the Selector fields +// match the resource. An empty Selector matches all resources. +type Selector struct { + // Names is a list of metadata.names to match. If empty match all names. + // e.g. Names: ["foo", "bar"] matches if `metadata.name` is either "foo" or "bar". + Names []string `json:"names" yaml:"names"` + + namesSet sets.String + + // Namespaces is a list of metadata.namespaces to match. If empty match all namespaces. + // e.g. Namespaces: ["foo", "bar"] matches if `metadata.namespace` is either "foo" or "bar". + Namespaces []string `json:"namespaces" yaml:"namespaces"` + + namespaceSet sets.String + + // Kinds is a list of kinds to match. If empty match all kinds. + // e.g. Kinds: ["foo", "bar"] matches if `kind` is either "foo" or "bar". + Kinds []string `json:"kinds" yaml:"kinds"` + + kindsSet sets.String + + // APIVersions is a list of apiVersions to match. If empty apply match all apiVersions. + // e.g. APIVersions: ["foo/v1", "bar/v1"] matches if `apiVersion` is either "foo/v1" or "bar/v1". + APIVersions []string `json:"apiVersions" yaml:"apiVersions"` + + apiVersionsSet sets.String + + // Labels is a collection of labels to match. All labels must match exactly. + // e.g. Labels: {"foo": "bar", "baz": "buz"] matches if BOTH "foo" and "baz" labels match. + Labels map[string]string `json:"labels" yaml:"labels"` + + // Annotations is a collection of annotations to match. All annotations must match exactly. + // e.g. Annotations: {"foo": "bar", "baz": "buz"] matches if BOTH "foo" and "baz" annotations match. + Annotations map[string]string `json:"annotations" yaml:"annotations"` + + // Filter is an arbitrary filter function to match a resource. + // Selector matches if the function returns true. + Filter func(*yaml.RNode) bool + + // matches contains a list of matching reosurces. + matches []*yaml.RNode +} + +// GetMatches returns them matching resources from rl +func (s *Selector) GetMatches(rl *ResourceList) ([]*yaml.RNode, error) { + if err := s.init(rl); err != nil { + return nil, err + } + return s.matches, nil +} + +func (s *Selector) init(rl *ResourceList) error { + // index the selectors + s.matches = nil + s.kindsSet = sets.String{} + s.kindsSet.Insert(s.Kinds...) + s.apiVersionsSet = sets.String{} + s.apiVersionsSet.Insert(s.APIVersions...) + s.namesSet = sets.String{} + s.namesSet.Insert(s.Names...) + s.namespaceSet = sets.String{} + s.namespaceSet.Insert(s.Namespaces...) + + //check each resource that matches the patch selector + for i := range rl.Items { + if match, err := s.isMatch(rl.Items[i]); err != nil { + return err + } else if !match { + continue + } + s.matches = append(s.matches, rl.Items[i]) + } + return nil +} + +// isMatch returns true if r matches the patch selector +func (s *Selector) isMatch(r *yaml.RNode) (bool, error) { + m, err := r.GetMeta() + if err != nil { + return false, errors.Wrap(err) + } + if s.kindsSet.Len() > 0 && !s.kindsSet.Has(m.Kind) { + return false, nil + } + if s.apiVersionsSet.Len() > 0 && !s.apiVersionsSet.Has(m.APIVersion) { + return false, nil + } + if s.namesSet.Len() > 0 && !s.namesSet.Has(m.Name) { + return false, nil + } + if s.namespaceSet.Len() > 0 && !s.namespaceSet.Has(m.Namespace) { + return false, nil + } + for k := range s.Labels { + if m.Labels == nil || m.Labels[k] != s.Labels[k] { + return false, nil + } + } + for k := range s.Annotations { + if m.Annotations == nil || m.Annotations[k] != s.Annotations[k] { + return false, nil + } + } + if s.Filter != nil { + if match := s.Filter(r); !match { + return false, nil + } + } + return true, nil +} diff --git a/kyaml/fn/framework/patch_test.go b/kyaml/fn/framework/patch_test.go new file mode 100644 index 000000000..467ee52b6 --- /dev/null +++ b/kyaml/fn/framework/patch_test.go @@ -0,0 +1,81 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package framework_test + +import ( + "testing" + "text/template" + + "github.com/spf13/cobra" + "sigs.k8s.io/kustomize/kyaml/fn/framework" + "sigs.k8s.io/kustomize/kyaml/fn/framework/frameworktestutil" + "sigs.k8s.io/kustomize/kyaml/testutil" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +func TestPatchTemplate(t *testing.T) { + // TODO: make this test pass on windows -- current failure seems spurious + testutil.SkipWindows(t) + + cmdFn := func() cobra.Command { + type api struct { + Selector framework.Selector `json:"selector" yaml:"selector"` + A string `json:"a" yaml:"a"` + B string `json:"b" yaml:"b"` + Special string `json:"special" yaml:"special"` + LongList bool + } + var config api + filter := framework.Selector{ + // this is a special manual filter for the Selector for when the built-in matchers + // are insufficient + Filter: func(rn *yaml.RNode) bool { + m, _ := rn.GetMeta() + return config.Special != "" && m.Annotations["foo"] == config.Special + }, + } + return framework.TemplateCommand{ + API: &config, + PreProcess: func(rl *framework.ResourceList) error { + // do some extra processing based on the inputs + config.LongList = len(rl.Items) > 2 + return nil + }, + PatchTemplates: []framework.PatchTemplate{ + { + // Apply these rendered patches + Template: template.Must(template.New("test").Parse(` +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:{{ .B }} +--- +metadata: + annotations: + patched: '{{ .A }}' +{{- if .LongList }} + long: 'true' +{{- end }} +`)), + // Use the selector from the input + Selector: &config.Selector, + }, + { + // Apply these rendered patches + Template: template.Must(template.New("test").Parse(` +metadata: + annotations: + filterPatched: '{{ .A }}' +`)), + // Use an explicit selector + Selector: &filter, + }, + }, + }.GetCommand() + } + + frameworktestutil.ResultsChecker{Command: cmdFn, TestDataDirectory: "patchtestdata"}.Assert(t) +} diff --git a/kyaml/fn/framework/patchtestdata/annotationselector/config.yaml b/kyaml/fn/framework/patchtestdata/annotationselector/config.yaml new file mode 100644 index 000000000..0b800704e --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/annotationselector/config.yaml @@ -0,0 +1,10 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + annotations: + foo: bar +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/annotationselector/expected.yaml b/kyaml/fn/framework/patchtestdata/annotationselector/expected.yaml new file mode 100644 index 000000000..820220ae1 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/annotationselector/expected.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/annotationselector/input.yaml b/kyaml/fn/framework/patchtestdata/annotationselector/input.yaml new file mode 100644 index 000000000..83e896dc4 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/annotationselector/input.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/apiversionselector/config.yaml b/kyaml/fn/framework/patchtestdata/apiversionselector/config.yaml new file mode 100644 index 000000000..4639f3c13 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/apiversionselector/config.yaml @@ -0,0 +1,9 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + apiVersions: ["apps/v1alpha1"] +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/apiversionselector/expected.yaml b/kyaml/fn/framework/patchtestdata/apiversionselector/expected.yaml new file mode 100644 index 000000000..2b87f041c --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/apiversionselector/expected.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1alpha1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/apiversionselector/input.yaml b/kyaml/fn/framework/patchtestdata/apiversionselector/input.yaml new file mode 100644 index 000000000..934468e94 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/apiversionselector/input.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1alpha1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/filterselector/config.yaml b/kyaml/fn/framework/patchtestdata/filterselector/config.yaml new file mode 100644 index 000000000..70ae89b79 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/filterselector/config.yaml @@ -0,0 +1,8 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +a: a +b: b +special: bar \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/filterselector/expected.yaml b/kyaml/fn/framework/patchtestdata/filterselector/expected.yaml new file mode 100644 index 000000000..fa6066a32 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/filterselector/expected.yaml @@ -0,0 +1,32 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + namespace: test + annotations: + foo: bar + patched: 'a' + filterPatched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/filterselector/input.yaml b/kyaml/fn/framework/patchtestdata/filterselector/input.yaml new file mode 100644 index 000000000..c48080aa9 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/filterselector/input.yaml @@ -0,0 +1,17 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + namespace: test + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/kindselector/config.yaml b/kyaml/fn/framework/patchtestdata/kindselector/config.yaml new file mode 100644 index 000000000..6ec10f8ed --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/kindselector/config.yaml @@ -0,0 +1,9 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + kinds: ["Deployment"] +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/kindselector/expected.yaml b/kyaml/fn/framework/patchtestdata/kindselector/expected.yaml new file mode 100644 index 000000000..4bc25c387 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/kindselector/expected.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/kindselector/input.yaml b/kyaml/fn/framework/patchtestdata/kindselector/input.yaml new file mode 100644 index 000000000..04c97d7a5 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/kindselector/input.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/labelselector/config.yaml b/kyaml/fn/framework/patchtestdata/labelselector/config.yaml new file mode 100644 index 000000000..fb885f2ad --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/labelselector/config.yaml @@ -0,0 +1,10 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + labels: + foo: bar +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/labelselector/expected.yaml b/kyaml/fn/framework/patchtestdata/labelselector/expected.yaml new file mode 100644 index 000000000..5b08fc4ab --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/labelselector/expected.yaml @@ -0,0 +1,24 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + labels: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + labels: + foo: bar + annotations: + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/labelselector/input.yaml b/kyaml/fn/framework/patchtestdata/labelselector/input.yaml new file mode 100644 index 000000000..117a25c8d --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/labelselector/input.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + labels: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + labels: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/longlistpreprocess/config.yaml b/kyaml/fn/framework/patchtestdata/longlistpreprocess/config.yaml new file mode 100644 index 000000000..6ec10f8ed --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/longlistpreprocess/config.yaml @@ -0,0 +1,9 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + kinds: ["Deployment"] +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/longlistpreprocess/expected.yaml b/kyaml/fn/framework/patchtestdata/longlistpreprocess/expected.yaml new file mode 100644 index 000000000..9d820acb0 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/longlistpreprocess/expected.yaml @@ -0,0 +1,39 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo + long: 'true' + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: test-2 + annotations: + foo: bar +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-3 + annotations: + foo: bar + long: 'true' + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/longlistpreprocess/input.yaml b/kyaml/fn/framework/patchtestdata/longlistpreprocess/input.yaml new file mode 100644 index 000000000..d22cff50d --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/longlistpreprocess/input.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: test-2 + annotations: + foo: bar +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-3 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/nameselector/config.yaml b/kyaml/fn/framework/patchtestdata/nameselector/config.yaml new file mode 100644 index 000000000..3242579b9 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/nameselector/config.yaml @@ -0,0 +1,9 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + names: ["test-2"] +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/nameselector/expected.yaml b/kyaml/fn/framework/patchtestdata/nameselector/expected.yaml new file mode 100644 index 000000000..820220ae1 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/nameselector/expected.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/nameselector/input.yaml b/kyaml/fn/framework/patchtestdata/nameselector/input.yaml new file mode 100644 index 000000000..83e896dc4 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/nameselector/input.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + annotations: + foo: bar diff --git a/kyaml/fn/framework/patchtestdata/namespaceselector/config.yaml b/kyaml/fn/framework/patchtestdata/namespaceselector/config.yaml new file mode 100644 index 000000000..82912baa4 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/namespaceselector/config.yaml @@ -0,0 +1,9 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: example.com/v1alpha1 +kind: patcher +selector: + namespaces: ["test"] +a: a +b: b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/namespaceselector/expected.yaml b/kyaml/fn/framework/patchtestdata/namespaceselector/expected.yaml new file mode 100644 index 000000000..1e7b5e42b --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/namespaceselector/expected.yaml @@ -0,0 +1,24 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + namespace: test + annotations: + foo: bar + patched: 'a' +spec: + template: + spec: + containers: + - name: foo + image: example/sidecar:b \ No newline at end of file diff --git a/kyaml/fn/framework/patchtestdata/namespaceselector/input.yaml b/kyaml/fn/framework/patchtestdata/namespaceselector/input.yaml new file mode 100644 index 000000000..c48080aa9 --- /dev/null +++ b/kyaml/fn/framework/patchtestdata/namespaceselector/input.yaml @@ -0,0 +1,17 @@ +# Copyright 2019 The Kubernetes Authors. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-1 + annotations: + baz: foo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-2 + namespace: test + annotations: + foo: bar