diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2018-10-26 04:33:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-26 04:33:12 -0700 |
commit | 6e1aeb06f86bfed7045be19c8e8b09c1bf5ba55f (patch) | |
tree | e05292388acb06c0c30d5031fc540fc629f6f6e5 | |
parent | a2dc29746f354382a90956fcc3b47abf8a986fd9 (diff) | |
parent | 606a5cec8fa177fe64cff4ccf7cac05900fbe86c (diff) | |
download | podman-6e1aeb06f86bfed7045be19c8e8b09c1bf5ba55f.tar.gz podman-6e1aeb06f86bfed7045be19c8e8b09c1bf5ba55f.tar.bz2 podman-6e1aeb06f86bfed7045be19c8e8b09c1bf5ba55f.zip |
Merge pull request #1637 from vrothberg/runlabel-execute-any-command
runlabel: run any command
-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 | ||||
-rw-r--r-- | test/e2e/runlabel_test.go | 68 |
4 files changed, 190 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, " ")) } diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go new file mode 100644 index 000000000..8d10d3c24 --- /dev/null +++ b/test/e2e/runlabel_test.go @@ -0,0 +1,68 @@ +package integration + +import ( + "fmt" + "os" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var PodmanDockerfile = ` +FROM alpine:latest +LABEL RUN podman --version` + +var LsDockerfile = ` +FROM alpine:latest +LABEL RUN ls -la` + +var _ = Describe("podman container runlabel", func() { + var ( + tempdir string + err error + podmanTest PodmanTest + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanCreate(tempdir) + podmanTest.RestoreAllArtifacts() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + + }) + + It("podman container runlabel (podman --version)", func() { + image := "podman-runlabel-test:podman" + podmanTest.BuildImage(PodmanDockerfile, image, "false") + + result := podmanTest.Podman([]string{"container", "runlabel", "RUN", image}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + + result = podmanTest.Podman([]string{"rmi", image}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) + + It("podman container runlabel (ls -la)", func() { + image := "podman-runlabel-test:ls" + podmanTest.BuildImage(LsDockerfile, image, "false") + + result := podmanTest.Podman([]string{"container", "runlabel", "RUN", image}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + + result = podmanTest.Podman([]string{"rmi", image}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) +}) |