mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
390 lines
8.9 KiB
Go
390 lines
8.9 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package commands
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/stretchr/testify/assert"
|
|
"sigs.k8s.io/kustomize/kyaml/runfn"
|
|
)
|
|
|
|
// TestRunFnCommand_preRunE verifies that preRunE correctly parses the commandline
|
|
// flags and arguments into the RunFns structure to be executed.
|
|
func TestRunFnCommand_preRunE(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
expectedStruct *runfn.RunFns
|
|
err string
|
|
path string
|
|
input io.Reader
|
|
output io.Writer
|
|
functionPaths []string
|
|
network bool
|
|
networkName string
|
|
mount []string
|
|
}{
|
|
{
|
|
name: "config map",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--", "a=b", "c=d", "e=f"},
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {a: b, c: d, e: f}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "config map stdin / stdout",
|
|
args: []string{"run", "--image", "foo:bar", "--", "a=b", "c=d", "e=f"},
|
|
input: os.Stdin,
|
|
output: os.Stdout,
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {a: b, c: d, e: f}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "config map dry-run",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--dry-run", "--", "a=b", "c=d", "e=f"},
|
|
output: os.Stdout,
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {a: b, c: d, e: f}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "config map no args",
|
|
args: []string{"run", "dir", "--image", "foo:bar"},
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "network enabled",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--network"},
|
|
path: "dir",
|
|
network: true,
|
|
networkName: "bridge",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar', network: {required: true}}
|
|
data: {}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "with network name",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--network", "--network-name", "foo"},
|
|
path: "dir",
|
|
network: true,
|
|
networkName: "foo",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar', network: {required: true}}
|
|
data: {}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "custom kind",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--", "Foo", "g=h"},
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {g: h}
|
|
kind: Foo
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "custom kind '=' in data",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--", "Foo", "g=h", "i=j=k"},
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {g: h, i: j=k}
|
|
kind: Foo
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "star",
|
|
args: []string{"run", "dir",
|
|
"--enable-star",
|
|
"--star-path", "a/b/c",
|
|
"--star-name", "foo",
|
|
"--", "Foo", "g=h"},
|
|
path: "dir",
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
starlark: {path: a/b/c, name: foo}
|
|
data: {g: h}
|
|
kind: Foo
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "star-not-enabled",
|
|
args: []string{"run", "dir",
|
|
"--star-path", "a/b/c",
|
|
"--star-name", "foo",
|
|
"--", "Foo", "g=h"},
|
|
path: "dir",
|
|
err: "must specify --enable-star with --star-path",
|
|
},
|
|
{
|
|
name: "image-star-not-enabled",
|
|
args: []string{"run", "dir",
|
|
"--image", "some_image",
|
|
"--star-path", "a/b/c",
|
|
"--star-name", "foo",
|
|
"--", "Foo", "g=h"},
|
|
path: "dir",
|
|
err: "must specify --enable-star with --star-path",
|
|
},
|
|
{
|
|
name: "star-enabled",
|
|
args: []string{"run", "dir", "--enable-star"},
|
|
path: "dir",
|
|
expectedStruct: &runfn.RunFns{
|
|
Path: "dir",
|
|
NetworkName: "bridge",
|
|
EnableStarlark: true,
|
|
},
|
|
},
|
|
{
|
|
name: "function paths",
|
|
args: []string{"run", "dir", "--fn-path", "path1", "--fn-path", "path2"},
|
|
path: "dir",
|
|
functionPaths: []string{"path1", "path2"},
|
|
},
|
|
{
|
|
name: "custom kind with function paths",
|
|
args: []string{
|
|
"run", "dir", "--fn-path", "path", "--image", "foo:bar", "--", "Foo", "g=h", "i=j=k"},
|
|
path: "dir",
|
|
functionPaths: []string{"path"},
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {g: h, i: j=k}
|
|
kind: Foo
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "custom kind with storage mounts",
|
|
args: []string{
|
|
"run", "dir", "--mount", "type=bind,src=/mount/path,dst=/local/",
|
|
"--mount", "type=volume,src=myvol,dst=/local/",
|
|
"--mount", "type=tmpfs,dst=/local/",
|
|
"--image", "foo:bar", "--", "Foo", "g=h", "i=j=k"},
|
|
path: "dir",
|
|
mount: []string{"type=bind,src=/mount/path,dst=/local/", "type=volume,src=myvol,dst=/local/", "type=tmpfs,dst=/local/"},
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {g: h, i: j=k}
|
|
kind: Foo
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "results_dir",
|
|
args: []string{"run", "dir", "--results-dir", "foo/", "--image", "foo:bar", "--", "a=b", "c=d", "e=f"},
|
|
path: "dir",
|
|
expectedStruct: &runfn.RunFns{
|
|
Path: "dir",
|
|
NetworkName: "bridge",
|
|
ResultsDir: "foo/",
|
|
},
|
|
expected: `
|
|
metadata:
|
|
name: function-input
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container: {image: 'foo:bar'}
|
|
data: {a: b, c: d, e: f}
|
|
kind: ConfigMap
|
|
apiVersion: v1
|
|
`,
|
|
},
|
|
{
|
|
name: "config map multi args",
|
|
args: []string{"run", "dir", "dir2", "--image", "foo:bar", "--", "a=b", "c=d", "e=f"},
|
|
err: "0 or 1 arguments supported",
|
|
},
|
|
{
|
|
name: "config map not image",
|
|
args: []string{"run", "dir", "--", "a=b", "c=d", "e=f"},
|
|
err: "must specify --image",
|
|
},
|
|
{
|
|
name: "config map bad data",
|
|
args: []string{"run", "dir", "--image", "foo:bar", "--", "a=b", "c", "e=f"},
|
|
err: "must have keys and values separated by",
|
|
},
|
|
}
|
|
|
|
for i := range tests {
|
|
tt := tests[i]
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
r := GetRunFnRunner("kustomize")
|
|
// Don't run the actual command
|
|
r.Command.Run = nil
|
|
r.Command.RunE = func(cmd *cobra.Command, args []string) error { return nil }
|
|
r.Command.SilenceErrors = true
|
|
r.Command.SilenceUsage = true
|
|
|
|
// hack due to https://github.com/spf13/cobra/issues/42
|
|
root := &cobra.Command{Use: "root"}
|
|
root.AddCommand(r.Command)
|
|
root.SetArgs(tt.args)
|
|
|
|
// error case
|
|
err := r.Command.Execute()
|
|
if tt.err != "" {
|
|
if !assert.Error(t, err) {
|
|
t.FailNow()
|
|
}
|
|
if !assert.Contains(t, err.Error(), tt.err) {
|
|
t.FailNow()
|
|
}
|
|
// don't check anything else in error case
|
|
return
|
|
}
|
|
|
|
// non-error case
|
|
if !assert.NoError(t, err) {
|
|
t.FailNow()
|
|
}
|
|
|
|
// check if Input was set
|
|
if !assert.Equal(t, tt.input, r.RunFns.Input) {
|
|
t.FailNow()
|
|
}
|
|
|
|
// check if Output was set
|
|
if !assert.Equal(t, tt.output, r.RunFns.Output) {
|
|
t.FailNow()
|
|
}
|
|
|
|
// check if Path was set
|
|
if !assert.Equal(t, tt.path, r.RunFns.Path) {
|
|
t.FailNow()
|
|
}
|
|
|
|
// check if Network was set
|
|
if tt.network {
|
|
if !assert.Equal(t, tt.network, r.RunFns.Network) {
|
|
t.FailNow()
|
|
}
|
|
if !assert.Equal(t, tt.networkName, r.RunFns.NetworkName) {
|
|
t.FailNow()
|
|
}
|
|
} else {
|
|
if !assert.Equal(t, false, r.RunFns.Network) {
|
|
t.FailNow()
|
|
}
|
|
}
|
|
|
|
// check if FunctionPaths were set
|
|
if tt.functionPaths == nil {
|
|
// make Equal work against flag default
|
|
tt.functionPaths = []string{}
|
|
}
|
|
if !assert.Equal(t, tt.functionPaths, r.RunFns.FunctionPaths) {
|
|
t.FailNow()
|
|
}
|
|
|
|
if !assert.Equal(t, r.RunFns, r.RunFns) {
|
|
t.FailNow()
|
|
}
|
|
|
|
if !assert.Equal(t, toStorageMounts(tt.mount), r.RunFns.StorageMounts) {
|
|
t.FailNow()
|
|
}
|
|
|
|
// check if Functions were set
|
|
if tt.expected != "" {
|
|
if !assert.Len(t, r.RunFns.Functions, 1) {
|
|
t.FailNow()
|
|
}
|
|
actual := strings.TrimSpace(r.RunFns.Functions[0].MustString())
|
|
if !assert.Equal(t, strings.TrimSpace(tt.expected), actual) {
|
|
t.FailNow()
|
|
}
|
|
}
|
|
|
|
if tt.expectedStruct != nil {
|
|
r.RunFns.Functions = nil
|
|
tt.expectedStruct.FunctionPaths = tt.functionPaths
|
|
if !assert.Equal(t, *tt.expectedStruct, r.RunFns) {
|
|
t.FailNow()
|
|
}
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
}
|