Files
kustomize/kyaml/fn/runtime/container/container_test.go
Karl Isenberg 43868688d5 Use require for Error and NoError
Assert keeps going after failure, but require immediately fails
the tests, making it easier to find the output related to the test
failure, rather than having to comb through a bunch of subsequent
assertion failures. For equality tests, we may or may not want to
continue, but for error checks we almost always want to immediately
fail the test. Exceptions can be changed as-needed.
2024-03-20 13:19:18 -07:00

257 lines
6.4 KiB
Go

// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package container
import (
"bytes"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestFilter_setupExec(t *testing.T) {
var tests = []struct {
name string
functionConfig string
expectedArgs []string
containerSpec runtimeutil.ContainerSpec
UIDGID string
}{
{
name: "command",
functionConfig: `apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
expectedArgs: []string{
"run",
"--rm",
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
"--network", "none",
"--user", "nobody",
"--security-opt=no-new-privileges",
},
containerSpec: runtimeutil.ContainerSpec{
Image: "example.com:version",
},
UIDGID: "nobody",
},
{
name: "network",
functionConfig: `apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
expectedArgs: []string{
"run",
"--rm",
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
"--network", "host",
"--user", "nobody",
"--security-opt=no-new-privileges",
},
containerSpec: runtimeutil.ContainerSpec{
Image: "example.com:version",
Network: true,
},
UIDGID: "nobody",
},
{
name: "storage_mounts",
functionConfig: `apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
expectedArgs: []string{
"run",
"--rm",
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
"--network", "none",
"--user", "nobody",
"--security-opt=no-new-privileges",
// use filepath.Join for Windows filepath handling
"--mount", fmt.Sprintf("type=%s,source=%s,target=%s,readonly", "bind", getAbsFilePath(string(filepath.Separator), "mount", "path"), "/local/"),
"--mount", fmt.Sprintf("type=%s,source=%s,target=%s", "bind", getAbsFilePath(string(filepath.Separator), "mount", "pathrw"), "/localrw/"),
"--mount", fmt.Sprintf("type=%s,source=%s,target=%s,readonly", "volume", getAbsFilePath(string(filepath.Separator), "myvol"), "/local/"),
"--mount", fmt.Sprintf("type=%s,source=%s,target=%s,readonly", "tmpfs", getAbsFilePath(string(filepath.Separator)), "/local/"),
},
containerSpec: runtimeutil.ContainerSpec{
Image: "example.com:version",
StorageMounts: []runtimeutil.StorageMount{
{MountType: "bind", Src: getAbsFilePath(string(filepath.Separator), "mount", "path"), DstPath: "/local/"},
{MountType: "bind", Src: getAbsFilePath(string(filepath.Separator), "mount", "pathrw"), DstPath: "/localrw/", ReadWriteMode: true},
{MountType: "volume", Src: getAbsFilePath(string(filepath.Separator), "myvol"), DstPath: "/local/"},
{MountType: "tmpfs", Src: getAbsFilePath(string(filepath.Separator)), DstPath: "/local/"},
},
},
UIDGID: "nobody",
},
{
name: "as current user",
functionConfig: `apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
expectedArgs: []string{
"run",
"--rm",
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
"--network", "none",
"--user", "1:2",
"--security-opt=no-new-privileges",
},
containerSpec: runtimeutil.ContainerSpec{
Image: "example.com:version",
},
UIDGID: "1:2",
},
}
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
cfg, err := yaml.Parse(tt.functionConfig)
if !assert.NoError(t, err) {
t.FailNow()
}
instance := NewContainer(tt.containerSpec, tt.UIDGID)
instance.Exec.FunctionConfig = cfg
instance.Env = append(instance.Env, "KYAML_TEST=FOO")
require.NoError(t, instance.setupExec())
tt.expectedArgs = append(tt.expectedArgs,
runtimeutil.NewContainerEnvFromStringSlice(instance.Env).GetDockerFlags()...)
tt.expectedArgs = append(tt.expectedArgs, instance.Image)
if !assert.Equal(t, "docker", instance.Exec.Path) {
t.FailNow()
}
if !assert.Equal(t, tt.expectedArgs, instance.Exec.Args) {
t.FailNow()
}
})
}
}
func TestFilter_Filter(t *testing.T) {
cfg, err := yaml.Parse(`apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`)
if !assert.NoError(t, err) {
return
}
input, err := (&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-foo
---
apiVersion: v1
kind: Service
metadata:
name: service-foo
`)}).Read()
if !assert.NoError(t, err) {
return
}
instance := Filter{}
instance.Exec.FunctionConfig = cfg
instance.Exec.Path = "sed"
instance.Exec.Args = []string{"s/Deployment/StatefulSet/g"}
instance.Exec.WorkingDir = getWorkingDir(t)
output, err := instance.Filter(input)
if !assert.NoError(t, err) {
t.FailNow()
}
b := &bytes.Buffer{}
err = kio.ByteWriter{Writer: b, KeepReaderAnnotations: true}.Write(output)
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Equal(t, `apiVersion: apps/v1
kind: StatefulSet
metadata:
name: deployment-foo
annotations:
config.kubernetes.io/index: '0'
internal.config.kubernetes.io/index: '0'
internal.config.kubernetes.io/path: 'statefulset_deployment-foo.yaml'
config.kubernetes.io/path: 'statefulset_deployment-foo.yaml'
---
apiVersion: v1
kind: Service
metadata:
name: service-foo
annotations:
config.kubernetes.io/index: '1'
internal.config.kubernetes.io/index: '1'
internal.config.kubernetes.io/path: 'service_service-foo.yaml'
config.kubernetes.io/path: 'service_service-foo.yaml'
`, b.String()) {
t.FailNow()
}
}
func TestFilter_String(t *testing.T) {
instance := Filter{ContainerSpec: runtimeutil.ContainerSpec{Image: "foo"}}
if !assert.Equal(t, "foo", instance.String()) {
t.FailNow()
}
instance.Exec.DeferFailure = true
if !assert.Equal(t, "foo deferFailure: true", instance.String()) {
t.FailNow()
}
}
func TestFilter_ExitCode(t *testing.T) {
instance := Filter{}
instance.Exec.Path = "/not/real/command"
instance.Exec.DeferFailure = true
instance.Exec.WorkingDir = getWorkingDir(t)
_, err := instance.Filter(nil)
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Error(t, instance.GetExit()) {
t.FailNow()
}
if !assert.Contains(t, instance.GetExit().Error(), "/not/real/command") {
t.FailNow()
}
}
func getWorkingDir(t *testing.T) string {
t.Helper()
wd, err := os.Getwd()
require.NoError(t, err)
return wd
}
func getAbsFilePath(args ...string) string {
path, _ := filepath.Abs(filepath.Join(args...))
return path
}