diff options
-rw-r--r-- | cmd/podman/main.go | 5 | ||||
-rw-r--r-- | cmd/podman/ps.go | 13 | ||||
-rw-r--r-- | cmd/podman/rm.go | 23 | ||||
-rw-r--r-- | cmd/podman/runlabel.go | 5 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 4 | ||||
-rw-r--r-- | cmd/podman/shared/funcs.go | 41 | ||||
-rw-r--r-- | cmd/podman/shared/funcs_test.go | 87 | ||||
-rw-r--r-- | cmd/podman/shared/parallel.go | 91 | ||||
-rw-r--r-- | cmd/podman/stop.go | 20 | ||||
-rw-r--r-- | cmd/podman/utils.go | 66 | ||||
-rw-r--r-- | contrib/python/podman/test/test_images.py | 8 | ||||
-rwxr-xr-x | contrib/python/podman/test/test_runner.sh | 4 | ||||
-rw-r--r-- | test/e2e/run_selinux_test.go | 64 | ||||
-rw-r--r-- | test/e2e/runlabel_test.go | 68 |
14 files changed, 400 insertions, 99 deletions
diff --git a/cmd/podman/main.go b/cmd/podman/main.go index d4c8454a8..38eac4504 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -211,6 +211,11 @@ func main() { Value: hooks.DefaultDir, Hidden: true, }, + cli.IntFlag{ + Name: "max-workers", + Usage: "the maximum number of workers for parallel operations", + Hidden: true, + }, cli.StringFlag{ Name: "log-level", Usage: "log messages above specified level: debug, info, warn, error (default), fatal or panic", diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index a468f6121..d63618e58 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -20,6 +20,7 @@ import ( "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-units" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/urfave/cli" "k8s.io/apimachinery/pkg/fields" ) @@ -300,7 +301,13 @@ func psCmd(c *cli.Context) error { outputContainers = []*libpod.Container{latestCtr} } - pss := shared.PBatch(outputContainers, 8, opts) + maxWorkers := shared.Parallelize("ps") + if c.GlobalIsSet("max-workers") { + maxWorkers = c.GlobalInt("max-workers") + } + logrus.Debugf("Setting maximum workers to %d", maxWorkers) + + pss := shared.PBatch(outputContainers, maxWorkers, opts) if opts.Sort != "" { pss, err = sortPsOutput(opts.Sort, pss) if err != nil { @@ -344,7 +351,9 @@ func psCmd(c *cli.Context) error { // Output Namespace headers fmt.Fprintf(w, "\n%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", hid, hnames, nspid, nscgroup, nsipc, nsmnt, nsnet, nspidns, nsuserns, nsuts) } - + if len(pss) == 0 { + fmt.Fprint(w, "\n") + } // Now iterate each container and output its information for _, container := range pss { diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go index c6641e879..0fb5345ee 100644 --- a/cmd/podman/rm.go +++ b/cmd/podman/rm.go @@ -2,11 +2,11 @@ package main import ( "fmt" - rt "runtime" - "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -48,14 +48,13 @@ func rmCmd(c *cli.Context) error { var ( delContainers []*libpod.Container lastError error - deleteFuncs []workerInput + deleteFuncs []shared.ParallelWorkerInput ) ctx := getContext() if err := validateFlags(c, rmFlags); err != nil { return err } - runtime, err := libpodruntime.GetRuntime(c) if err != nil { return errors.Wrapf(err, "could not get runtime") @@ -69,17 +68,23 @@ func rmCmd(c *cli.Context) error { delContainers, lastError = getAllOrLatestContainers(c, runtime, -1, "all") for _, container := range delContainers { + con := container f := func() error { - return runtime.RemoveContainer(ctx, container, c.Bool("force")) + return runtime.RemoveContainer(ctx, con, c.Bool("force")) } - deleteFuncs = append(deleteFuncs, workerInput{ - containerID: container.ID(), - parallelFunc: f, + deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{ + ContainerID: con.ID(), + ParallelFunc: f, }) } + maxWorkers := shared.Parallelize("rm") + if c.GlobalIsSet("max-workers") { + maxWorkers = c.GlobalInt("max-workers") + } + logrus.Debugf("Setting maximum workers to %d", maxWorkers) - deleteErrors := parallelExecuteWorkerPool(rt.NumCPU()*3, deleteFuncs) + deleteErrors := shared.ParallelExecuteWorkerPool(maxWorkers, deleteFuncs) for cid, result := range deleteErrors { if result != nil { fmt.Println(result.Error()) 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/container.go b/cmd/podman/shared/container.go index 4af737e0a..b847314a4 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -226,10 +226,10 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput return pso, nil } -type pFunc func() (PsContainerOutput, error) +type batchFunc func() (PsContainerOutput, error) type workerInput struct { - parallelFunc pFunc + parallelFunc batchFunc opts PsOptions cid string job int 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/cmd/podman/shared/parallel.go b/cmd/podman/shared/parallel.go new file mode 100644 index 000000000..03eba2f0b --- /dev/null +++ b/cmd/podman/shared/parallel.go @@ -0,0 +1,91 @@ +package shared + +import ( + "runtime" + "sync" +) + +type pFunc func() error + +// ParallelWorkerInput is a struct used to pass in a slice of parallel funcs to be +// performed on a container ID +type ParallelWorkerInput struct { + ContainerID string + ParallelFunc pFunc +} + +type containerError struct { + ContainerID string + Err error +} + +// ParallelWorker is a "threaded" worker that takes jobs from the channel "queue" +func ParallelWorker(wg *sync.WaitGroup, jobs <-chan ParallelWorkerInput, results chan<- containerError) { + for j := range jobs { + err := j.ParallelFunc() + results <- containerError{ContainerID: j.ContainerID, Err: err} + wg.Done() + } +} + +// ParallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker +// int determines how many workers/threads should be premade. +func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) map[string]error { + var ( + wg sync.WaitGroup + ) + + resultChan := make(chan containerError, len(functions)) + results := make(map[string]error) + paraJobs := make(chan ParallelWorkerInput, len(functions)) + + // If we have more workers than functions, match up the number of workers and functions + if workers > len(functions) { + workers = len(functions) + } + + // Create the workers + for w := 1; w <= workers; w++ { + go ParallelWorker(&wg, paraJobs, resultChan) + } + + // Add jobs to the workers + for _, j := range functions { + j := j + wg.Add(1) + paraJobs <- j + } + + close(paraJobs) + wg.Wait() + + close(resultChan) + for ctrError := range resultChan { + results[ctrError.ContainerID] = ctrError.Err + } + + return results +} + +// Parallelize provides the maximum number of parallel workers (int) as calculated by a basic +// heuristic. This can be overriden by the --max-workers primary switch to podman. +func Parallelize(job string) int { + numCpus := runtime.NumCPU() + switch job { + case "stop": + if numCpus <= 2 { + return 4 + } else { + return numCpus * 3 + } + case "rm": + if numCpus <= 3 { + return numCpus * 3 + } else { + return numCpus * 4 + } + case "ps": + return 8 + } + return 3 +} diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index edadbda89..afeb49f76 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -2,12 +2,12 @@ package main import ( "fmt" - rt "runtime" - "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -61,7 +61,7 @@ func stopCmd(c *cli.Context) error { containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running") - var stopFuncs []workerInput + var stopFuncs []shared.ParallelWorkerInput for _, ctr := range containers { con := ctr var stopTimeout uint @@ -73,13 +73,19 @@ func stopCmd(c *cli.Context) error { f := func() error { return con.StopWithTimeout(stopTimeout) } - stopFuncs = append(stopFuncs, workerInput{ - containerID: con.ID(), - parallelFunc: f, + stopFuncs = append(stopFuncs, shared.ParallelWorkerInput{ + ContainerID: con.ID(), + ParallelFunc: f, }) } - stopErrors := parallelExecuteWorkerPool(rt.NumCPU()*3, stopFuncs) + maxWorkers := shared.Parallelize("stop") + if c.GlobalIsSet("max-workers") { + maxWorkers = c.GlobalInt("max-workers") + } + logrus.Debugf("Setting maximum workers to %d", maxWorkers) + + stopErrors := shared.ParallelExecuteWorkerPool(maxWorkers, stopFuncs) for cid, result := range stopErrors { if result != nil && result != libpod.ErrCtrStopped { diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go index f9971fd88..afeccb668 100644 --- a/cmd/podman/utils.go +++ b/cmd/podman/utils.go @@ -3,10 +3,6 @@ package main import ( "context" "fmt" - "os" - gosignal "os/signal" - "sync" - "github.com/containers/libpod/libpod" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/term" @@ -15,6 +11,8 @@ import ( "github.com/urfave/cli" "golang.org/x/crypto/ssh/terminal" "k8s.io/client-go/tools/remotecommand" + "os" + gosignal "os/signal" ) type RawTtyFormatter struct { @@ -209,63 +207,3 @@ func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error } return pods, lastError } - -type pFunc func() error - -type workerInput struct { - containerID string - parallelFunc pFunc -} - -type containerError struct { - containerID string - err error -} - -// worker is a "threaded" worker that takes jobs from the channel "queue" -func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results chan<- containerError) { - for j := range jobs { - err := j.parallelFunc() - results <- containerError{containerID: j.containerID, err: err} - wg.Done() - } -} - -// parallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker -// int is determines how many workers/threads should be premade. -func parallelExecuteWorkerPool(workers int, functions []workerInput) map[string]error { - var ( - wg sync.WaitGroup - ) - - resultChan := make(chan containerError, len(functions)) - results := make(map[string]error) - paraJobs := make(chan workerInput, len(functions)) - - // If we have more workers than functions, match up the number of workers and functions - if workers > len(functions) { - workers = len(functions) - } - - // Create the workers - for w := 1; w <= workers; w++ { - go worker(&wg, paraJobs, resultChan) - } - - // Add jobs to the workers - for _, j := range functions { - j := j - wg.Add(1) - paraJobs <- j - } - - close(paraJobs) - wg.Wait() - - close(resultChan) - for ctrError := range resultChan { - results[ctrError.containerID] = ctrError.err - } - - return results -} diff --git a/contrib/python/podman/test/test_images.py b/contrib/python/podman/test/test_images.py index f6b95f98a..f97e13b4c 100644 --- a/contrib/python/podman/test/test_images.py +++ b/contrib/python/podman/test/test_images.py @@ -6,6 +6,7 @@ from datetime import datetime, timezone from test.podman_testcase import PodmanTestCase import podman +from podman import FoldedString class TestImages(PodmanTestCase): @@ -44,6 +45,7 @@ class TestImages(PodmanTestCase): self.assertGreaterEqual(len(actual), 2) self.assertIsNotNone(self.alpine_image) + @unittest.skip('TODO: missing buildah json file') def test_build(self): path = os.path.join(self.tmpdir, 'ctnr', 'Dockerfile') img, logs = self.pclient.images.build( @@ -59,12 +61,12 @@ class TestImages(PodmanTestCase): def test_create(self): img_details = self.alpine_image.inspect() - actual = self.alpine_image.container() + actual = self.alpine_image.container(command=['sleep', '1h']) self.assertIsNotNone(actual) - self.assertEqual(actual.status, 'configured') + self.assertEqual(FoldedString(actual.status), 'configured') ctnr = actual.start() - self.assertIn(ctnr.status, ['running', 'stopped', 'exited']) + self.assertEqual(FoldedString(ctnr.status), 'running') ctnr_details = ctnr.inspect() for e in img_details.containerconfig['env']: diff --git a/contrib/python/podman/test/test_runner.sh b/contrib/python/podman/test/test_runner.sh index 65cbd1e9c..bf097e2b2 100755 --- a/contrib/python/podman/test/test_runner.sh +++ b/contrib/python/podman/test/test_runner.sh @@ -31,7 +31,9 @@ function cleanup { # aggressive cleanup as tests may crash leaving crap around umount '^(shm|nsfs)' umount '\/run\/netns' - rm -r "$1" + if [[ $RETURNCODE -eq 0 ]]; then + rm -r "$1" + fi } # Create temporary directory for storage diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go index ebe6604cc..a1a18c780 100644 --- a/test/e2e/run_selinux_test.go +++ b/test/e2e/run_selinux_test.go @@ -84,4 +84,68 @@ var _ = Describe("Podman run", func() { Expect(match).Should(BeTrue()) }) + It("podman test selinux label resolv.conf", func() { + session := podmanTest.Podman([]string{"run", fedoraMinimal, "ls", "-Z", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux label hosts", func() { + session := podmanTest.Podman([]string{"run", fedoraMinimal, "ls", "-Z", "/etc/hosts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux label hostname", func() { + session := podmanTest.Podman([]string{"run", fedoraMinimal, "ls", "-Z", "/etc/hostname"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux label /run/secrets", func() { + session := podmanTest.Podman([]string{"run", fedoraMinimal, "ls", "-dZ", "/run/secrets"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux --privileged label resolv.conf", func() { + session := podmanTest.Podman([]string{"run", "--privileged", fedoraMinimal, "ls", "-Z", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux --privileged label hosts", func() { + session := podmanTest.Podman([]string{"run", "--privileged", fedoraMinimal, "ls", "-Z", "/etc/hosts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux --privileged label hostname", func() { + session := podmanTest.Podman([]string{"run", "--privileged", fedoraMinimal, "ls", "-Z", "/etc/hostname"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + + It("podman test selinux --privileged label /run/secrets", func() { + session := podmanTest.Podman([]string{"run", "--privileged", fedoraMinimal, "ls", "-dZ", "/run/secrets"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_file_t") + Expect(match).Should(BeTrue()) + }) + }) 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)) + }) +}) |