Retire mount.Exec for k8s.io/utils/exec

This patch removes mount.Exec entirely and instead uses the common
utility from k8s.io/utils/exec.

The fake exec implementation found in k8s.io/utils/exec differs a bit
than mount.Exec, with the ability to pre-script expected calls to
Command.CombinedOutput(), so tests that previously relied on a callback
mechanism to produce specific output have been updated to use that
mechanism.
This commit is contained in:
Travis Rhoden
2019-10-10 11:27:54 -06:00
parent e7ce8d8a6f
commit 367f879131
53 changed files with 449 additions and 324 deletions

View File

@@ -20,7 +20,6 @@ import (
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
@@ -41,6 +40,9 @@ import (
"k8s.io/client-go/tools/record"
utiltesting "k8s.io/client-go/util/testing"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/utils/exec"
"k8s.io/utils/exec/testing"
"k8s.io/kubernetes/pkg/util/mount"
. "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
@@ -73,7 +75,7 @@ type fakeVolumeHost struct {
cloud cloudprovider.Interface
mounter mount.Interface
hostUtil hostutil.HostUtils
exec mount.Exec
exec *testingexec.FakeExec
nodeLabels map[string]string
nodeName string
subpather subpath.Interface
@@ -111,7 +113,7 @@ func newFakeVolumeHost(rootDir string, kubeClient clientset.Interface, plugins [
host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: cloud}
host.mounter = mount.NewFakeMounter(nil)
host.hostUtil = hostutil.NewFakeHostUtil(pathToTypeMap)
host.exec = mount.NewFakeExec(nil)
host.exec = &testingexec.FakeExec{DisableScripts: true}
host.pluginMgr.InitPlugins(plugins, nil /* prober */, host)
host.subpather = &subpath.FakeSubpath{}
host.informerFactory = informers.NewSharedInformerFactory(kubeClient, time.Minute)
@@ -213,7 +215,7 @@ func (f *fakeVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secre
}
}
func (f *fakeVolumeHost) GetExec(pluginName string) mount.Exec {
func (f *fakeVolumeHost) GetExec(pluginName string) exec.Interface {
return f.exec
}
@@ -248,6 +250,64 @@ func (f *fakeVolumeHost) GetEventRecorder() record.EventRecorder {
return nil
}
func (f *fakeVolumeHost) ScriptCommands(scripts []CommandScript) {
ScriptCommands(f.exec, scripts)
}
// CommandScript is used to pre-configure a command that will be executed and
// optionally set it's output (stdout and stderr combined) and return code.
type CommandScript struct {
// Cmd is the command to execute, e.g. "ls"
Cmd string
// Args is a slice of arguments to pass to the command, e.g. "-a"
Args []string
// Output is the combined stdout and stderr of the command to return
Output string
// ReturnCode is the exit code for the command. Setting this to non-zero will
// cause the command to return an error with this exit code set.
ReturnCode int
}
// ScriptCommands configures fe, the FakeExec, to have a pre-configured list of
// commands to expect. Calling more commands using fe than those scripted will
// result in a panic. By default, the fe does not enforce command argument checking
// or order -- if you have given an Output to the command, the first command scripted
// will return its output on the first command call, even if the command called is
// different than the one scripted. This is mostly useful to make sure that the
// right number of commands were called. If you want to check the exact commands
// and arguments were called, set fe.ExectOrder to true.
func ScriptCommands(fe *testingexec.FakeExec, scripts []CommandScript) {
fe.DisableScripts = false
for _, script := range scripts {
fakeCmd := &testingexec.FakeCmd{}
cmdAction := makeFakeCmd(fakeCmd, script.Cmd, script.Args...)
outputAction := makeFakeOutput(script.Output, script.ReturnCode)
fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
fe.CommandScript = append(fe.CommandScript, cmdAction)
}
}
func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
fc := fakeCmd
c := cmd
a := args
return func(cmd string, args ...string) exec.Cmd {
command := testingexec.InitFakeCmd(fc, c, a...)
return command
}
}
func makeFakeOutput(output string, rc int) testingexec.FakeCombinedOutputAction {
o := output
var e error
if rc != 0 {
e = testingexec.FakeExitError{Status: rc}
}
return func() ([]byte, error) {
return []byte(o), e
}
}
func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
if _, ok := config.OtherAttributes["fake-property"]; ok {
return []VolumePlugin{
@@ -1131,7 +1191,7 @@ func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
return nil, err
}
defer os.RemoveAll(tmpDir)
out, err := exec.Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
out, err := exec.New().Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
if err != nil {
return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
}