mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
test without system call
This commit is contained in:
@@ -5,7 +5,6 @@ package container
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/user"
|
|
||||||
|
|
||||||
runtimeexec "sigs.k8s.io/kustomize/kyaml/fn/runtime/exec"
|
runtimeexec "sigs.k8s.io/kustomize/kyaml/fn/runtime/exec"
|
||||||
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
|
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
|
||||||
@@ -185,28 +184,9 @@ func (c *Filter) getCommand() (string, []string) {
|
|||||||
return "docker", a
|
return "docker", a
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUIDGID will return "nobody" if asCurrentUser is false. Otherwise
|
|
||||||
// return "uid:gid" according to current user who runs the command.
|
|
||||||
func getUIDGID(asCurrentUser bool) (string, error) {
|
|
||||||
if !asCurrentUser {
|
|
||||||
return "nobody", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s:%s", u.Uid, u.Gid), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContainer returns a new container filter
|
// NewContainer returns a new container filter
|
||||||
func NewContainer(spec runtimeutil.ContainerSpec, asCurrentUser bool) (Filter, error) {
|
func NewContainer(spec runtimeutil.ContainerSpec, uidgid string) (Filter, error) {
|
||||||
f := Filter{ContainerSpec: spec}
|
f := Filter{ContainerSpec: spec, UIDGID: uidgid}
|
||||||
u, err := getUIDGID(asCurrentUser)
|
|
||||||
if err != nil {
|
|
||||||
return f, err
|
|
||||||
}
|
|
||||||
f.UIDGID = u
|
|
||||||
|
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package container
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/user"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -16,16 +15,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestFilter_setupExec(t *testing.T) {
|
func TestFilter_setupExec(t *testing.T) {
|
||||||
u, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
functionConfig string
|
functionConfig string
|
||||||
expectedArgs []string
|
expectedArgs []string
|
||||||
containerSpec runtimeutil.ContainerSpec
|
containerSpec runtimeutil.ContainerSpec
|
||||||
asCurrentUser bool
|
UIDGID string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "command",
|
name: "command",
|
||||||
@@ -45,6 +40,7 @@ metadata:
|
|||||||
containerSpec: runtimeutil.ContainerSpec{
|
containerSpec: runtimeutil.ContainerSpec{
|
||||||
Image: "example.com:version",
|
Image: "example.com:version",
|
||||||
},
|
},
|
||||||
|
UIDGID: "nobody",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -62,12 +58,11 @@ metadata:
|
|||||||
"--user", "nobody",
|
"--user", "nobody",
|
||||||
"--security-opt=no-new-privileges",
|
"--security-opt=no-new-privileges",
|
||||||
},
|
},
|
||||||
instance: NewContainer(
|
containerSpec: runtimeutil.ContainerSpec{
|
||||||
runtimeutil.ContainerSpec{
|
Image: "example.com:version",
|
||||||
Image: "example.com:version",
|
Network: true,
|
||||||
Network: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
UIDGID: "nobody",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -98,6 +93,7 @@ metadata:
|
|||||||
{MountType: "tmpfs", Src: "", DstPath: "/local/"},
|
{MountType: "tmpfs", Src: "", DstPath: "/local/"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
UIDGID: "nobody",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "as current user",
|
name: "as current user",
|
||||||
@@ -111,13 +107,13 @@ metadata:
|
|||||||
"--rm",
|
"--rm",
|
||||||
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
|
"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR",
|
||||||
"--network", "none",
|
"--network", "none",
|
||||||
"--user", fmt.Sprintf("%s:%s", u.Uid, u.Gid),
|
"--user", "1:2",
|
||||||
"--security-opt=no-new-privileges",
|
"--security-opt=no-new-privileges",
|
||||||
},
|
},
|
||||||
containerSpec: runtimeutil.ContainerSpec{
|
containerSpec: runtimeutil.ContainerSpec{
|
||||||
Image: "example.com:version",
|
Image: "example.com:version",
|
||||||
},
|
},
|
||||||
asCurrentUser: true,
|
UIDGID: "1:2",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +125,7 @@ metadata:
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
instance, err := NewContainer(tt.containerSpec, tt.asCurrentUser)
|
instance, err := NewContainer(tt.containerSpec, tt.UIDGID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -83,7 +84,7 @@ type RunFns struct {
|
|||||||
// functionFilterProvider provides a filter to perform the function.
|
// functionFilterProvider provides a filter to perform the function.
|
||||||
// this is a variable so it can be mocked in tests
|
// this is a variable so it can be mocked in tests
|
||||||
functionFilterProvider func(
|
functionFilterProvider func(
|
||||||
filter runtimeutil.FunctionSpec, api *yaml.RNode) (kio.Filter, error)
|
filter runtimeutil.FunctionSpec, api *yaml.RNode, currentUser currentUserFunc) (kio.Filter, error)
|
||||||
|
|
||||||
// AsCurrentUser is a boolean to indicate whether docker container should use
|
// AsCurrentUser is a boolean to indicate whether docker container should use
|
||||||
// the uid and gid that run the command
|
// the uid and gid that run the command
|
||||||
@@ -303,7 +304,7 @@ func (r RunFns) getFunctionFilters(global bool, fns ...*yaml.RNode) (
|
|||||||
// merge envs from imperative and declarative
|
// merge envs from imperative and declarative
|
||||||
spec.Container.Env = r.mergeContainerEnv(spec.Container.Env)
|
spec.Container.Env = r.mergeContainerEnv(spec.Container.Env)
|
||||||
|
|
||||||
c, err := r.functionFilterProvider(*spec, api)
|
c, err := r.functionFilterProvider(*spec, api, user.Current)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -395,8 +396,24 @@ func (r *RunFns) init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type currentUserFunc func() (*user.User, error)
|
||||||
|
|
||||||
|
// getUIDGID will return "nobody" if asCurrentUser is false. Otherwise
|
||||||
|
// return "uid:gid" according to the return from currentUser function.
|
||||||
|
func getUIDGID(asCurrentUser bool, currentUser currentUserFunc) (string, error) {
|
||||||
|
if !asCurrentUser {
|
||||||
|
return "nobody", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := currentUser()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%s", u.Uid, u.Gid), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ffp provides function filters
|
// ffp provides function filters
|
||||||
func (r *RunFns) ffp(spec runtimeutil.FunctionSpec, api *yaml.RNode) (kio.Filter, error) {
|
func (r *RunFns) ffp(spec runtimeutil.FunctionSpec, api *yaml.RNode, currentUser currentUserFunc) (kio.Filter, error) {
|
||||||
var resultsFile string
|
var resultsFile string
|
||||||
if r.ResultsDir != "" {
|
if r.ResultsDir != "" {
|
||||||
resultsFile = filepath.Join(r.ResultsDir, fmt.Sprintf(
|
resultsFile = filepath.Join(r.ResultsDir, fmt.Sprintf(
|
||||||
@@ -405,6 +422,10 @@ func (r *RunFns) ffp(spec runtimeutil.FunctionSpec, api *yaml.RNode) (kio.Filter
|
|||||||
}
|
}
|
||||||
if !r.DisableContainers && spec.Container.Image != "" {
|
if !r.DisableContainers && spec.Container.Image != "" {
|
||||||
// TODO: Add a test for this behavior
|
// TODO: Add a test for this behavior
|
||||||
|
uidgid, err := getUIDGID(r.AsCurrentUser, currentUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
c, err := container.NewContainer(
|
c, err := container.NewContainer(
|
||||||
runtimeutil.ContainerSpec{
|
runtimeutil.ContainerSpec{
|
||||||
Image: spec.Container.Image,
|
Image: spec.Container.Image,
|
||||||
@@ -412,7 +433,7 @@ func (r *RunFns) ffp(spec runtimeutil.FunctionSpec, api *yaml.RNode) (kio.Filter
|
|||||||
StorageMounts: r.StorageMounts,
|
StorageMounts: r.StorageMounts,
|
||||||
Env: spec.Container.Env,
|
Env: spec.Container.Env,
|
||||||
},
|
},
|
||||||
r.AsCurrentUser,
|
uidgid,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -38,6 +39,13 @@ replace: StatefulSet
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func currentUser() (*user.User, error) {
|
||||||
|
return &user.User{
|
||||||
|
Uid: "1",
|
||||||
|
Gid: "2",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestRunFns_init(t *testing.T) {
|
func TestRunFns_init(t *testing.T) {
|
||||||
instance := RunFns{}
|
instance := RunFns{}
|
||||||
instance.init()
|
instance.init()
|
||||||
@@ -59,8 +67,41 @@ kind:
|
|||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter, _ := instance.functionFilterProvider(spec, api)
|
filter, _ := instance.functionFilterProvider(spec, api, currentUser)
|
||||||
c, err := container.NewContainer(runtimeutil.ContainerSpec{Image: "example.com:version"}, false)
|
c, err := container.NewContainer(runtimeutil.ContainerSpec{Image: "example.com:version"}, "nobody")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cf := &c
|
||||||
|
cf.Exec.FunctionConfig = api
|
||||||
|
assert.Equal(t, cf, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunFns_initAsCurrentUser(t *testing.T) {
|
||||||
|
instance := RunFns{
|
||||||
|
AsCurrentUser: true,
|
||||||
|
}
|
||||||
|
instance.init()
|
||||||
|
if !assert.Equal(t, instance.Input, os.Stdin) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, instance.Output, os.Stdout) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := yaml.Parse(`apiVersion: apps/v1
|
||||||
|
kind:
|
||||||
|
`)
|
||||||
|
spec := runtimeutil.FunctionSpec{
|
||||||
|
Container: runtimeutil.ContainerSpec{
|
||||||
|
Image: "example.com:version",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filter, _ := instance.functionFilterProvider(spec, api, currentUser)
|
||||||
|
c, err := container.NewContainer(runtimeutil.ContainerSpec{Image: "example.com:version"}, "1:2")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -93,8 +134,8 @@ kind:
|
|||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter, _ := instance.functionFilterProvider(spec, api)
|
filter, _ := instance.functionFilterProvider(spec, api, currentUser)
|
||||||
c, err := container.NewContainer(runtimeutil.ContainerSpec{Image: "example.com:version"}, false)
|
c, err := container.NewContainer(runtimeutil.ContainerSpec{Image: "example.com:version"}, "nobody")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -869,7 +910,7 @@ replace: StatefulSet
|
|||||||
var fltrs []*TestFilter
|
var fltrs []*TestFilter
|
||||||
instance := RunFns{
|
instance := RunFns{
|
||||||
Path: dir,
|
Path: dir,
|
||||||
functionFilterProvider: func(f runtimeutil.FunctionSpec, node *yaml.RNode) (kio.Filter, error) {
|
functionFilterProvider: func(f runtimeutil.FunctionSpec, node *yaml.RNode, currentUser currentUserFunc) (kio.Filter, error) {
|
||||||
tf := &TestFilter{
|
tf := &TestFilter{
|
||||||
Exit: errors.Errorf("message: %s", f.Container.Image),
|
Exit: errors.Errorf("message: %s", f.Container.Image),
|
||||||
}
|
}
|
||||||
@@ -1075,8 +1116,8 @@ func setupTest(t *testing.T) string {
|
|||||||
// getFilterProvider fakes the creation of a filter, replacing the ContainerFiler with
|
// getFilterProvider fakes the creation of a filter, replacing the ContainerFiler with
|
||||||
// a filter to s/kind: Deployment/kind: StatefulSet/g.
|
// a filter to s/kind: Deployment/kind: StatefulSet/g.
|
||||||
// this can be used to simulate running a filter.
|
// this can be used to simulate running a filter.
|
||||||
func getFilterProvider(t *testing.T) func(runtimeutil.FunctionSpec, *yaml.RNode) (kio.Filter, error) {
|
func getFilterProvider(t *testing.T) func(runtimeutil.FunctionSpec, *yaml.RNode, currentUserFunc) (kio.Filter, error) {
|
||||||
return func(f runtimeutil.FunctionSpec, node *yaml.RNode) (kio.Filter, error) {
|
return func(f runtimeutil.FunctionSpec, node *yaml.RNode, currentUser currentUserFunc) (kio.Filter, error) {
|
||||||
// parse the filter from the input
|
// parse the filter from the input
|
||||||
filter := yaml.YFilter{}
|
filter := yaml.YFilter{}
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
|
|||||||
Reference in New Issue
Block a user