diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/runlabel.go | 5 | ||||
-rw-r--r-- | cmd/podman/shared/funcs.go | 41 | ||||
-rw-r--r-- | cmd/podman/shared/funcs_test.go | 87 |
3 files changed, 122 insertions, 11 deletions
diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go index aa7411a5f..e1dee1fb2 100644 --- a/cmd/podman/runlabel.go +++ b/cmd/podman/runlabel.go @@ -196,7 +196,10 @@ func runlabelCmd(c *cli.Context) error { runLabel = fmt.Sprintf("%s %s", runLabel, strings.Join(args[2:], " ")) } - cmd := shared.GenerateCommand(runLabel, imageName, c.String("name")) + cmd, err := shared.GenerateCommand(runLabel, imageName, c.String("name")) + if err != nil { + return errors.Wrapf(err, "unable to generate command") + } env := shared.GenerateRunEnvironment(c.String("name"), imageName, opts) env = append(env, "PODMAN_RUNLABEL_NESTED=1") diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go index 485944f29..a92e0d547 100644 --- a/cmd/podman/shared/funcs.go +++ b/cmd/podman/shared/funcs.go @@ -3,11 +3,39 @@ package shared import ( "fmt" "os" + "path/filepath" "strings" ) +func substituteCommand(cmd string) (string, error) { + // If cmd is an absolute or relative path, check if the file exists. + // Throw an error if it doesn't exist. + if strings.Contains(cmd, "/") || strings.HasPrefix(cmd, ".") { + res, err := filepath.Abs(cmd) + if err != nil { + return "", err + } + if _, err := os.Stat(res); !os.IsNotExist(err) { + return res, nil + } else if err != nil { + return "", err + } + } + + // Replace cmd with "/proc/self/exe" if "podman" or "docker" is being + // used. Otherwise, leave the command unchanged. + switch cmd { + case "podman": + fallthrough + case "docker": + return "/proc/self/exe", nil + default: + return cmd, nil + } +} + // GenerateCommand takes a label (string) and converts it to an executable command -func GenerateCommand(command, imageName, name string) []string { +func GenerateCommand(command, imageName, name string) ([]string, error) { var ( newCommand []string ) @@ -15,8 +43,13 @@ func GenerateCommand(command, imageName, name string) []string { name = imageName } cmd := strings.Split(command, " ") - // Replace the first element of cmd with "/proc/self/exe" - newCommand = append(newCommand, "/proc/self/exe") + + prog, err := substituteCommand(cmd[0]) + if err != nil { + return nil, err + } + newCommand = append(newCommand, prog) + for _, arg := range cmd[1:] { var newArg string switch arg { @@ -37,7 +70,7 @@ func GenerateCommand(command, imageName, name string) []string { } newCommand = append(newCommand, newArg) } - return newCommand + return newCommand, nil } // GenerateRunEnvironment merges the current environment variables with optional diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go index 612be480b..596df84e8 100644 --- a/cmd/podman/shared/funcs_test.go +++ b/cmd/podman/shared/funcs_test.go @@ -1,6 +1,10 @@ package shared import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" "strings" "testing" @@ -16,35 +20,106 @@ var ( func TestGenerateCommand(t *testing.T) { inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" - newCommand := GenerateCommand(inputCommand, "foo", "bar") + newCommand, err := GenerateCommand(inputCommand, "foo", "bar") + assert.Nil(t, err) assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) } +func TestGenerateCommandCheckSubstitution(t *testing.T) { + type subsTest struct { + input string + expected string + shouldFail bool + } + + absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath") + assert.Nil(t, err, "error creating tempfile") + defer os.Remove(absTmpFile.Name()) + + relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath") + assert.Nil(t, err, "error creating tempfile") + defer os.Remove(relTmpFile.Name()) + relTmpCmd, err := filepath.Abs(relTmpFile.Name()) + assert.Nil(t, err, "error getting absolute path for relative tmpfile") + + // this has a (low) potential of race conditions but no other way + removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove") + assert.Nil(t, err, "error creating tempfile") + os.Remove(removedTmpFile.Name()) + + absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name()) + tests := []subsTest{ + { + input: "docker run -it alpine:latest", + expected: "/proc/self/exe run -it alpine:latest", + shouldFail: false, + }, + { + input: "podman run -it alpine:latest", + expected: "/proc/self/exe run -it alpine:latest", + shouldFail: false, + }, + { + input: absTmpCmd, + expected: absTmpCmd, + shouldFail: false, + }, + { + input: "./" + relTmpFile.Name(), + expected: relTmpCmd, + shouldFail: false, + }, + { + input: "ls -la", + expected: "ls -la", + shouldFail: false, + }, + { + input: removedTmpFile.Name(), + expected: "", + shouldFail: true, + }, + } + + for _, test := range tests { + newCommand, err := GenerateCommand(test.input, "foo", "bar") + if test.shouldFail { + assert.NotNil(t, err) + } else { + assert.Nil(t, err) + } + assert.Equal(t, test.expected, strings.Join(newCommand, " ")) + } +} + func TestGenerateCommandPath(t *testing.T) { - inputCommand := "/usr/bin/docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" + inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" - newCommand := GenerateCommand(inputCommand, "foo", "bar") + newCommand, _ := GenerateCommand(inputCommand, "foo", "bar") assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) } func TestGenerateCommandNoSetName(t *testing.T) { inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install" - newCommand := GenerateCommand(inputCommand, "foo", "") + newCommand, err := GenerateCommand(inputCommand, "foo", "") + assert.Nil(t, err) assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) } func TestGenerateCommandNoName(t *testing.T) { inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install" correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install" - newCommand := GenerateCommand(inputCommand, "foo", "") + newCommand, err := GenerateCommand(inputCommand, "foo", "") + assert.Nil(t, err) assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) } func TestGenerateCommandAlreadyPodman(t *testing.T) { inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" - newCommand := GenerateCommand(inputCommand, "foo", "bar") + newCommand, err := GenerateCommand(inputCommand, "foo", "bar") + assert.Nil(t, err) assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) } |