diff --git a/kyaml/fn/framework/doc.go b/kyaml/fn/framework/doc.go index 9691e10d3..adf83047f 100644 --- a/kyaml/fn/framework/doc.go +++ b/kyaml/fn/framework/doc.go @@ -31,7 +31,7 @@ // // Validator Functions // -// Functions may validate resources, returning Results as go errors. Results may contain +// Functions may validate resources, returning results as go errors. results may contain // different items for different validation failures. // // Configuring Functions diff --git a/kyaml/fn/framework/example_test.go b/kyaml/fn/framework/example_test.go index e54bf3538..10f96e1d7 100644 --- a/kyaml/fn/framework/example_test.go +++ b/kyaml/fn/framework/example_test.go @@ -281,7 +281,7 @@ functionConfig: } // ExampleCommand_validate validates that all Deployment resources have the replicas field set. -// If any Deployments do not contain spec.replicas, then the function will return Results +// If any Deployments do not contain spec.replicas, then the function will return results // which will be set on ResourceList.results func ExampleCommand_validate() { cmd := framework.Command(nil, func(nodes []*yaml.RNode) ([]*yaml.RNode, error) { @@ -320,7 +320,7 @@ func ExampleCommand_validate() { }) } - // framework will only consider Results an error if it has at least 1 item + // framework will only consider results an error if it has at least 1 item return nodes, framework.Result{ Name: "replicas-validator", Items: validationResults, diff --git a/kyaml/fn/runtime/exec/doc.go b/kyaml/fn/runtime/exec/doc.go new file mode 100644 index 000000000..2747a96fb --- /dev/null +++ b/kyaml/fn/runtime/exec/doc.go @@ -0,0 +1,5 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +// Package exec contains the exec function implementation. +package exec diff --git a/kyaml/fn/runtime/exec/exec.go b/kyaml/fn/runtime/exec/exec.go new file mode 100644 index 000000000..cf8edeaa5 --- /dev/null +++ b/kyaml/fn/runtime/exec/exec.go @@ -0,0 +1,34 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package exec + +import ( + "io" + "os/exec" + + "sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +type Filter struct { + // Path is the path to the executable to run + Path string `yaml:"path,omitempty"` + + // Args are the arguments to the executable + Args []string `yaml:"args,omitempty"` + + runtimeutil.FunctionFilter +} + +func (c *Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { + c.FunctionFilter.Run = c.Run + return c.FunctionFilter.Filter(nodes) +} + +func (c *Filter) Run(reader io.Reader, writer io.Writer) error { + cmd := exec.Command(c.Path, c.Args...) + cmd.Stdin = reader + cmd.Stdout = writer + return cmd.Run() +} diff --git a/kyaml/fn/runtime/exec/exec_test.go b/kyaml/fn/runtime/exec/exec_test.go new file mode 100644 index 000000000..c878ed993 --- /dev/null +++ b/kyaml/fn/runtime/exec/exec_test.go @@ -0,0 +1,112 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package exec_test + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/fn/runtime/exec" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +func TestFunctionFilter_Filter(t *testing.T) { + var tests = []struct { + name string + input []string + functionConfig string + expectedOutput []string + expectedError string + instance exec.Filter + }{ + { + name: "exec_sed", + input: []string{ + `apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-foo`, + `apiVersion: v1 +kind: Service +metadata: + name: service-foo`, + }, + expectedOutput: []string{ + `apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: deployment-foo + annotations: + config.kubernetes.io/path: 'statefulset_deployment-foo.yaml' +`, + `apiVersion: v1 +kind: Service +metadata: + name: service-foo + annotations: + config.kubernetes.io/path: 'service_service-foo.yaml' +`, + }, + expectedError: "", + instance: exec.Filter{ + Path: "sed", + Args: []string{"s/Deployment/StatefulSet/g"}, + }, + }, + } + + for i := range tests { + tt := tests[i] + t.Run(tt.name, func(t *testing.T) { + // initialize the inputs for the FunctionFilter + var inputs []*yaml.RNode + for i := range tt.input { + node, err := yaml.Parse(tt.input[i]) + if !assert.NoError(t, err) { + t.FailNow() + } + inputs = append(inputs, node) + } + if tt.functionConfig != "" { + fc, err := yaml.Parse(tt.functionConfig) + if !assert.NoError(t, err) { + t.FailNow() + } + tt.instance.FunctionConfig = fc + } + + // run the function + output, err := tt.instance.Filter(inputs) + + // check for errors + if tt.expectedError != "" { + if !assert.EqualError(t, err, tt.expectedError) { + t.FailNow() + } + return + } + if !assert.NoError(t, err) { + t.FailNow() + } + + // verify the output + var actual []string + for i := range output { + s, err := output[i].String() + if !assert.NoError(t, err) { + t.FailNow() + } + actual = append(actual, strings.TrimSpace(s)) + } + var expected []string + for i := range tt.expectedOutput { + expected = append(expected, strings.TrimSpace(tt.expectedOutput[i])) + } + if !assert.Equal(t, expected, actual) { + t.FailNow() + } + }) + } +} diff --git a/kyaml/fn/runtime/runtimeutil/example_test.go b/kyaml/fn/runtime/runtimeutil/example_test.go deleted file mode 100644 index 7b7fa960b..000000000 --- a/kyaml/fn/runtime/runtimeutil/example_test.go +++ /dev/null @@ -1 +0,0 @@ -package runtimeutil diff --git a/kyaml/fn/runtime/runtimeutil/types.go b/kyaml/fn/runtime/runtimeutil/types.go index fbbb7ad59..5edc4ebc3 100644 --- a/kyaml/fn/runtime/runtimeutil/types.go +++ b/kyaml/fn/runtime/runtimeutil/types.go @@ -1,3 +1,6 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + package runtimeutil type DeferFailureFunction interface {