summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/main.go5
-rw-r--r--cmd/podman/ps.go13
-rw-r--r--cmd/podman/rm.go23
-rw-r--r--cmd/podman/runlabel.go5
-rw-r--r--cmd/podman/shared/container.go4
-rw-r--r--cmd/podman/shared/funcs.go41
-rw-r--r--cmd/podman/shared/funcs_test.go87
-rw-r--r--cmd/podman/shared/parallel.go91
-rw-r--r--cmd/podman/stop.go20
-rw-r--r--cmd/podman/utils.go66
-rw-r--r--contrib/python/podman/test/test_images.py8
-rwxr-xr-xcontrib/python/podman/test/test_runner.sh4
-rw-r--r--test/e2e/run_selinux_test.go64
-rw-r--r--test/e2e/runlabel_test.go68
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))
+ })
+})