summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md2
-rw-r--r--RELEASE_NOTES.md2
-rw-r--r--changelog.txt8
-rw-r--r--cmd/podman/run.go1
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--libpod/runtime.go56
-rw-r--r--pkg/adapter/containers.go4
-rw-r--r--pkg/adapter/containers_remote.go9
-rw-r--r--pkg/rootless/rootless_linux.go118
-rw-r--r--pkg/rootless/rootless_unsupported.go6
-rw-r--r--pkg/util/utils.go2
-rw-r--r--pkg/varlinkapi/attach.go1
-rw-r--r--pkg/varlinkapi/virtwriter/virtwriter.go24
-rw-r--r--test/e2e/checkpoint_test.go4
-rw-r--r--test/e2e/cp_test.go4
-rw-r--r--test/e2e/create_staticip_test.go8
-rw-r--r--test/e2e/create_test.go2
-rw-r--r--test/e2e/exec_test.go4
-rw-r--r--test/e2e/export_test.go2
-rw-r--r--test/e2e/generate_kube_test.go4
-rw-r--r--test/e2e/generate_systemd_test.go6
-rw-r--r--test/e2e/healthcheck_run_test.go2
-rw-r--r--test/e2e/inspect_test.go2
-rw-r--r--test/e2e/kill_test.go2
-rw-r--r--test/e2e/load_test.go2
-rw-r--r--test/e2e/login_logout_test.go10
-rw-r--r--test/e2e/logs_test.go2
-rw-r--r--test/e2e/negative_test.go2
-rw-r--r--test/e2e/network_create_test.go10
-rw-r--r--test/e2e/pause_test.go6
-rw-r--r--test/e2e/play_kube_test.go209
-rw-r--r--test/e2e/pod_infra_container_test.go6
-rw-r--r--test/e2e/pod_inspect_test.go2
-rw-r--r--test/e2e/pod_kill_test.go2
-rw-r--r--test/e2e/pod_pause_test.go4
-rw-r--r--test/e2e/pod_ps_test.go2
-rw-r--r--test/e2e/pod_rm_test.go2
-rw-r--r--test/e2e/pod_stats_test.go2
-rw-r--r--test/e2e/port_test.go4
-rw-r--r--test/e2e/ps_test.go4
-rw-r--r--test/e2e/pull_test.go4
-rw-r--r--test/e2e/push_test.go6
-rw-r--r--test/e2e/rmi_test.go2
-rw-r--r--test/e2e/run_cpu_test.go4
-rw-r--r--test/e2e/run_device_test.go4
-rw-r--r--test/e2e/run_dns_test.go10
-rw-r--r--test/e2e/run_networking_test.go4
-rw-r--r--test/e2e/run_ns_test.go4
-rw-r--r--test/e2e/run_staticip_test.go8
-rw-r--r--test/e2e/run_test.go20
-rw-r--r--test/e2e/run_volume_test.go4
-rw-r--r--test/e2e/runlabel_test.go4
-rw-r--r--test/e2e/save_test.go4
-rw-r--r--test/e2e/start_test.go4
-rw-r--r--test/e2e/volume_create_test.go2
-rw-r--r--test/e2e/volume_rm_test.go4
-rw-r--r--test/system/075-exec.bats20
-rw-r--r--test/system/helpers.bash14
-rw-r--r--test/utils/matchers.go61
-rw-r--r--test/utils/utils.go12
-rw-r--r--troubleshooting.md19
-rw-r--r--vendor/modules.txt2
-rw-r--r--version/version.go2
64 files changed, 426 insertions, 338 deletions
diff --git a/Makefile b/Makefile
index 413b46fb8..a19d4848f 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ export GOPROXY=https://proxy.golang.org
GO ?= go
DESTDIR ?=
-EPOCH_TEST_COMMIT ?= dc1f8b62b168e0815ed5e7eb7c61a26ec3a0c88c
+EPOCH_TEST_COMMIT ?= 2b0892e757c878cdb087dd22b8986bccef0276ed
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
diff --git a/README.md b/README.md
index 485ca7b6f..166a4bebe 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.6.0](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.6.2](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
* [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod)
* Automated continuous release downloads (including remote-client):
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 0f2e748fa..235871273 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -22,9 +22,11 @@
- Fixed a bug where `podman stats` was broken on systems running CGroups V2 when run rootless ([#4268](https://github.com/containers/libpod/issues/4268))
- Fixed a bug where the `podman start` command would print the short container ID, instead of the full ID
- Fixed a bug where containers created with an OCI runtime that is no longer available (uninstalled or removed from the config file) would not appear in `podman ps` and could not be removed via `podman rm`
+- Fixed a bug where containers restored via `podman container restore --import` would retain the CGroup path of the original container, even if their container ID changed; thus, multiple containers created from the same checkpoint would all share the same CGroup
### Misc
- The default PID limit for containers is now set to 4096. It can be adjusted back to the old default (unlimited) by passing `--pids-limit 0` to `podman create` and `podman run`
+- The `podman start --attach` command now automatically attaches `STDIN` if the container was created with `-i`
- The `podman network create` command now validates network names using the same regular expression as container and pod names
- The `--systemd` flag to `podman run` and `podman create` will now only enable systemd mode when the binary being run inside the container is `/sbin/init`, `/usr/sbin/init`, or ends in `systemd` (previously detected any path ending in `init` or `systemd`)
- Updated vendored Buildah to 1.11.3
diff --git a/changelog.txt b/changelog.txt
index dd3fcec82..615e2a135 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,11 @@
+- Changelog for v1.6.2 (2019-10-17)
+ * Finalize release notes for v1.6.2
+ * rootless: drop dependency on docker
+ * Bump gitvalidation epoch
+ * Bump to v1.6.2-dev
+ * Refactor tests when checking for error exit codes
+ * Attach stdin to container at start if it was created with --interactive
+
- Changelog for v1.6.2-rc1 (2019-10-16)
* Add release notes for Podman 1.6.2
* start: print full container ID
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index 4836c99dc..7aa4cb3c4 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -45,7 +45,6 @@ func runCmd(c *cliconfig.RunValues) error {
span, _ := opentracing.StartSpanFromContext(Ctx, "runCmd")
defer span.Finish()
}
-
if err := createInit(&c.PodmanCommand); err != nil {
return err
}
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index bd2cff3f6..d5247f689 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -39,7 +39,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.6.2
+Version: 1.6.3
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/libpod/runtime.go b/libpod/runtime.go
index a0cf0ad7c..8f145a809 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -14,7 +14,6 @@ import (
"strings"
"sync"
"syscall"
- "time"
"github.com/BurntSushi/toml"
is "github.com/containers/image/v4/storage"
@@ -353,10 +352,6 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
// SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set.
// containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is
// use for the libpod.conf configuration file.
-// SetXdgDirs internally calls EnableLinger() so that the user's processes are not
-// killed once the session is terminated. EnableLinger() also attempts to
-// get the runtime directory when XDG_RUNTIME_DIR is not specified.
-// This function should only be called when running rootless.
func SetXdgDirs() error {
if !rootless.IsRootless() {
return nil
@@ -365,21 +360,6 @@ func SetXdgDirs() error {
// Setup XDG_RUNTIME_DIR
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
- runtimeDirLinger, err := rootless.EnableLinger()
- if err != nil {
- return errors.Wrapf(err, "error enabling user session")
- }
- if runtimeDir == "" && runtimeDirLinger != "" {
- if _, err := os.Stat(runtimeDirLinger); err != nil && os.IsNotExist(err) {
- chWait := make(chan error)
- defer close(chWait)
- if _, err := WaitForFile(runtimeDirLinger, chWait, time.Second*10); err != nil {
- return errors.Wrapf(err, "waiting for directory '%s'", runtimeDirLinger)
- }
- }
- runtimeDir = runtimeDirLinger
- }
-
if runtimeDir == "" {
var err error
runtimeDir, err = util.GetRuntimeDir()
@@ -400,10 +380,11 @@ func SetXdgDirs() error {
// Setup XDG_CONFIG_HOME
if cfgHomeDir := os.Getenv("XDG_CONFIG_HOME"); cfgHomeDir == "" {
- if cfgHomeDir, err = util.GetRootlessConfigHomeDir(); err != nil {
+ cfgHomeDir, err := util.GetRootlessConfigHomeDir()
+ if err != nil {
return err
}
- if err = os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil {
+ if err := os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil {
return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME")
}
}
@@ -528,6 +509,17 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
return nil, err
}
+ // storage.conf
+ storageConfFile, err := storage.DefaultConfigFile(rootless.IsRootless())
+ if err != nil {
+ return nil, err
+ }
+
+ createStorageConfFile := false
+ if _, err := os.Stat(storageConfFile); os.IsNotExist(err) {
+ createStorageConfFile = true
+ }
+
defRunConf, err := defaultRuntimeConfig()
if err != nil {
return nil, err
@@ -702,27 +694,21 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
}
if rootless.IsRootless() && configPath == "" {
- configPath, err := getRootlessConfigPath()
- if err != nil {
- return nil, err
- }
-
- // storage.conf
- storageConfFile, err := storage.DefaultConfigFile(rootless.IsRootless())
- if err != nil {
- return nil, err
- }
- if _, err := os.Stat(storageConfFile); os.IsNotExist(err) {
+ if createStorageConfFile {
if err := util.WriteStorageConfigFile(&runtime.config.StorageConfig, storageConfFile); err != nil {
return nil, errors.Wrapf(err, "cannot write config file %s", storageConfFile)
}
}
+ configPath, err := getRootlessConfigPath()
+ if err != nil {
+ return nil, err
+ }
if configPath != "" {
- if err := os.MkdirAll(filepath.Dir(configPath), 0755); err != nil {
+ if err := os.MkdirAll(filepath.Dir(configPath), 0711); err != nil {
return nil, err
}
- file, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ file, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if err != nil && !os.IsExist(err) {
return nil, errors.Wrapf(err, "cannot open file %s", configPath)
}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 12fd98486..5c33467a7 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -612,7 +612,9 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP
if c.Attach {
inputStream := os.Stdin
if !c.Interactive {
- inputStream = nil
+ if !ctr.Stdin() {
+ inputStream = nil
+ }
}
// attach to the container and also start it not already running
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index f7cb28b0c..f4e83a975 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -1092,6 +1092,7 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
// These are the special writers that encode input from the client.
varlinkStdinWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdin)
varlinkResizeWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.TerminalResize)
+ varlinkHangupWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.HangUpFromClient)
go func() {
// Read from the wire and direct to stdout or stderr
@@ -1117,7 +1118,6 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
}
}
}()
-
if stdin != nil {
// Takes stdinput and sends it over the wire after being encoded
go func() {
@@ -1126,7 +1126,12 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
sendGenericError(ecChan)
errChan <- err
}
-
+ _, err := varlinkHangupWriter.Write([]byte("EOF"))
+ if err != nil {
+ logrus.Errorf("unable to notify server to hangup: %q", err)
+ }
+ err = varlinkStdinWriter.Close()
+ errChan <- err
}()
}
return errChan
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 99307e8c4..94c42f7d0 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -11,20 +11,16 @@ import (
"os/exec"
gosignal "os/signal"
"os/user"
- "path/filepath"
"runtime"
"strconv"
- "strings"
"sync"
- "syscall"
"unsafe"
"github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/storage/pkg/idtools"
- "github.com/docker/docker/pkg/signal"
- "github.com/godbus/dbus"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
)
/*
@@ -130,7 +126,7 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
func readUserNs(path string) (string, error) {
b := make([]byte, 256)
- _, err := syscall.Readlink(path, b)
+ _, err := unix.Readlink(path, b)
if err != nil {
return "", err
}
@@ -143,7 +139,7 @@ func readUserNsFd(fd uintptr) (string, error) {
func getParentUserNs(fd uintptr) (uintptr, error) {
const nsGetParent = 0xb702
- ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(nsGetParent), 0)
+ ret, _, errno := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(nsGetParent), 0)
if errno != 0 {
return 0, errno
}
@@ -179,7 +175,7 @@ func getUserNSFirstChild(fd uintptr) (*os.File, error) {
for {
nextFd, err := getParentUserNs(fd)
if err != nil {
- if err == syscall.ENOTTY {
+ if err == unix.ENOTTY {
return os.NewFile(fd, "userns child"), nil
}
return nil, errors.Wrapf(err, "cannot get parent user namespace")
@@ -191,14 +187,14 @@ func getUserNSFirstChild(fd uintptr) (*os.File, error) {
}
if ns == currentNS {
- if err := syscall.Close(int(nextFd)); err != nil {
+ if err := unix.Close(int(nextFd)); err != nil {
return nil, err
}
// Drop O_CLOEXEC for the fd.
- _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, fd, syscall.F_SETFD, 0)
+ _, _, errno := unix.Syscall(unix.SYS_FCNTL, fd, unix.F_SETFD, 0)
if errno != 0 {
- if err := syscall.Close(int(fd)); err != nil {
+ if err := unix.Close(int(fd)); err != nil {
logrus.Errorf("failed to close file descriptor %d", fd)
}
return nil, errno
@@ -206,99 +202,13 @@ func getUserNSFirstChild(fd uintptr) (*os.File, error) {
return os.NewFile(fd, "userns child"), nil
}
- if err := syscall.Close(int(fd)); err != nil {
+ if err := unix.Close(int(fd)); err != nil {
return nil, err
}
fd = nextFd
}
}
-// EnableLinger configures the system to not kill the user processes once the session
-// terminates
-func EnableLinger() (string, error) {
- uid := fmt.Sprintf("%d", GetRootlessUID())
-
- conn, err := dbus.SystemBus()
- if err == nil {
- defer func() {
- if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close dbus connection: %q", err)
- }
- }()
- }
-
- lingerEnabled := false
-
- // If we have a D-BUS connection, attempt to read the LINGER property from it.
- if conn != nil {
- path := dbus.ObjectPath(fmt.Sprintf("/org/freedesktop/login1/user/_%s", uid))
- ret, err := conn.Object("org.freedesktop.login1", path).GetProperty("org.freedesktop.login1.User.Linger")
- if err == nil && ret.Value().(bool) {
- lingerEnabled = true
- }
- }
-
- xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR")
- lingerFile := ""
- if xdgRuntimeDir != "" && !lingerEnabled {
- lingerFile = filepath.Join(xdgRuntimeDir, "libpod/linger")
- _, err := os.Stat(lingerFile)
- if err == nil {
- lingerEnabled = true
- }
- }
-
- if !lingerEnabled {
- // First attempt with D-BUS, if it fails, then attempt with "loginctl enable-linger"
- if conn != nil {
- o := conn.Object("org.freedesktop.login1", "/org/freedesktop/login1")
- ret := o.Call("org.freedesktop.login1.Manager.SetUserLinger", 0, uint32(GetRootlessUID()), true, true)
- if ret.Err == nil {
- lingerEnabled = true
- }
- }
- if !lingerEnabled {
- err := exec.Command("loginctl", "enable-linger", uid).Run()
- if err == nil {
- lingerEnabled = true
- } else {
- logrus.Debugf("cannot run `loginctl enable-linger` for the current user: %v", err)
- }
- }
- if lingerEnabled && lingerFile != "" {
- f, err := os.Create(lingerFile)
- if err == nil {
- if err := f.Close(); err != nil {
- logrus.Errorf("failed to close %s", f.Name())
- }
- } else {
- logrus.Debugf("could not create linger file: %v", err)
- }
- }
- }
-
- if !lingerEnabled {
- return "", nil
- }
-
- // If we have a D-BUS connection, attempt to read the RUNTIME PATH from it.
- if conn != nil {
- path := dbus.ObjectPath(fmt.Sprintf("/org/freedesktop/login1/user/_%s", uid))
- ret, err := conn.Object("org.freedesktop.login1", path).GetProperty("org.freedesktop.login1.User.RuntimePath")
- if err == nil {
- return strings.Trim(ret.String(), "\"\n"), nil
- }
- }
-
- // If XDG_RUNTIME_DIR is not set and the D-BUS call didn't work, try to get the runtime path with "loginctl"
- output, err := exec.Command("loginctl", "-pRuntimePath", "show-user", uid).Output()
- if err != nil {
- logrus.Debugf("could not get RuntimePath using loginctl: %v", err)
- return "", nil
- }
- return strings.Trim(strings.Replace(string(output), "RuntimePath=", "", -1), "\"\n"), nil
-}
-
// joinUserAndMountNS re-exec podman in a new userNS and join the user and mount
// namespace of the specified PID without looking up its parent. Useful to join directly
// the conmon process.
@@ -394,7 +304,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
if err != nil {
return false, -1, err
}
@@ -491,21 +401,21 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
signals := []os.Signal{}
for sig := 0; sig < numSig; sig++ {
- if sig == int(syscall.SIGTSTP) {
+ if sig == int(unix.SIGTSTP) {
continue
}
- signals = append(signals, syscall.Signal(sig))
+ signals = append(signals, unix.Signal(sig))
}
gosignal.Notify(c, signals...)
defer gosignal.Reset()
go func() {
for s := range c {
- if s == signal.SIGCHLD || s == signal.SIGPIPE {
+ if s == unix.SIGCHLD || s == unix.SIGPIPE {
continue
}
- if err := syscall.Kill(int(pidC), s.(syscall.Signal)); err != nil {
+ if err := unix.Kill(int(pidC), s.(unix.Signal)); err != nil {
logrus.Errorf("failed to kill %d", int(pidC))
}
}
@@ -560,7 +470,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st
lastErr = nil
break
} else {
- fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
if err != nil {
lastErr = err
continue
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index ce488f364..1499b737f 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -37,12 +37,6 @@ func GetRootlessGID() int {
return -1
}
-// EnableLinger configures the system to not kill the user processes once the session
-// terminates
-func EnableLinger() (string, error) {
- return "", nil
-}
-
// TryJoinFromFilePaths attempts to join the namespaces of the pid files in paths.
// This is useful when there are already running containers and we
// don't have a pause process yet. We can use the paths to the conmon
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 0190b106d..d9a84e4e5 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -318,7 +318,7 @@ func WriteStorageConfigFile(storageOpts *storage.StoreOptions, storageConf strin
if err := os.MkdirAll(filepath.Dir(storageConf), 0755); err != nil {
return err
}
- storageFile, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ storageFile, err := os.OpenFile(storageConf, os.O_RDWR|os.O_TRUNC, 0600)
if err != nil {
return errors.Wrapf(err, "cannot open %s", storageConf)
}
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index f8557ae0c..37adbbf55 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -70,7 +70,6 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
}
reader, writer, _, pw, streams := setupStreams(call)
-
go func() {
if err := virtwriter.Reader(reader, nil, nil, pw, resize, nil); err != nil {
errChan <- err
diff --git a/pkg/varlinkapi/virtwriter/virtwriter.go b/pkg/varlinkapi/virtwriter/virtwriter.go
index 27ecd1f52..dd171943f 100644
--- a/pkg/varlinkapi/virtwriter/virtwriter.go
+++ b/pkg/varlinkapi/virtwriter/virtwriter.go
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/json"
"io"
+ "time"
"github.com/pkg/errors"
"k8s.io/client-go/tools/remotecommand"
@@ -26,8 +27,14 @@ const (
TerminalResize SocketDest = iota
// Quit and detach
Quit SocketDest = iota
+ // Quit from the client
+ HangUpFromClient SocketDest = iota
)
+// ClientHangup signifies that the client wants to drop its
+// connection from the server
+var ClientHangup = errors.New("client hangup")
+
// IntToSocketDest returns a socketdest based on integer input
func IntToSocketDest(i int) SocketDest {
switch i {
@@ -41,6 +48,8 @@ func IntToSocketDest(i int) SocketDest {
return TerminalResize
case Quit.Int():
return Quit
+ case HangUpFromClient.Int():
+ return HangUpFromClient
default:
return ToStderr
}
@@ -65,7 +74,7 @@ func NewVirtWriteCloser(w *bufio.Writer, dest SocketDest) VirtWriteCloser {
// Close is a required method for a writecloser
func (v VirtWriteCloser) Close() error {
- return nil
+ return v.writer.Flush()
}
// Write prepends a header to the input message. The header is
@@ -96,7 +105,6 @@ func Reader(r *bufio.Reader, output, errput, input io.Writer, resize chan remote
if r == nil {
return errors.Errorf("Reader must not be nil")
}
-
for {
n, err := io.ReadFull(r, headerBytes)
if err != nil {
@@ -107,7 +115,6 @@ func Reader(r *bufio.Reader, output, errput, input io.Writer, resize chan remote
}
messageSize = int64(binary.BigEndian.Uint32(headerBytes[4:8]))
-
switch IntToSocketDest(int(headerBytes[0])) {
case ToStdout:
if output != nil {
@@ -161,7 +168,16 @@ func Reader(r *bufio.Reader, output, errput, input io.Writer, resize chan remote
execEcChan <- int(ecInt)
}
return nil
-
+ case HangUpFromClient:
+ // This sleep allows the pipes to flush themselves before tearing everything down.
+ // It makes me sick to do it but after a full day I cannot put my finger on the race
+ // that occurs when closing things up. It would require a significant rewrite of code
+ // to make the pipes close down properly. Given that we are currently discussing a
+ // rewrite of all things remote, this hardly seems worth resolving.
+ //
+ // reproducer: echo hello | (podman-remote run -i alpine cat)
+ time.Sleep(1 * time.Second)
+ return ClientHangup
default:
// Something really went wrong
return errors.New("unknown multiplex destination")
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 1caefd299..4b43ceb30 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -67,13 +67,13 @@ var _ = Describe("Podman checkpoint", func() {
It("podman checkpoint bogus container", func() {
session := podmanTest.Podman([]string{"container", "checkpoint", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman restore bogus container", func() {
session := podmanTest.Podman([]string{"container", "restore", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman checkpoint a running container by id", func() {
diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go
index 3317683de..8d4c3dee7 100644
--- a/test/e2e/cp_test.go
+++ b/test/e2e/cp_test.go
@@ -53,7 +53,7 @@ var _ = Describe("Podman cp", func() {
session = podmanTest.Podman([]string{"cp", srcPath, name + ":foo/"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"cp", srcPath, name + ":foo"})
session.WaitWithDefaultTimeout()
@@ -205,7 +205,7 @@ var _ = Describe("Podman cp", func() {
session = podmanTest.Podman([]string{"cp", "--pause=false", srcPath, name + ":/test1/"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman cp volume", func() {
diff --git a/test/e2e/create_staticip_test.go b/test/e2e/create_staticip_test.go
index 709e56665..72a0638f9 100644
--- a/test/e2e/create_staticip_test.go
+++ b/test/e2e/create_staticip_test.go
@@ -40,13 +40,13 @@ var _ = Describe("Podman create with --ip flag", func() {
It("Podman create --ip with garbage address", func() {
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "114232346", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman create --ip with v6 address", func() {
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "2001:db8:bad:beef::1", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman create --ip with non-allocatable IP", func() {
@@ -56,7 +56,7 @@ var _ = Describe("Podman create with --ip flag", func() {
result = podmanTest.Podman([]string{"start", "test"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman create with specified static IP has correct IP", func() {
@@ -88,6 +88,6 @@ var _ = Describe("Podman create with --ip flag", func() {
Expect(result.ExitCode()).To(Equal(0))
result = podmanTest.Podman([]string{"start", "test2"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
})
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 2918cce78..65b747880 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -235,7 +235,7 @@ var _ = Describe("Podman create", func() {
It("podman create --pull", func() {
session := podmanTest.PodmanNoCache([]string{"create", "--pull", "never", "--name=foo", "nginx"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.PodmanNoCache([]string{"create", "--pull", "always", "--name=foo", "nginx"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 13fdabb81..1c4a9adb9 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -203,11 +203,11 @@ var _ = Describe("Podman exec", func() {
session := podmanTest.Podman([]string{"exec", "--workdir", "/missing", "test1", "pwd"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"exec", "-w", "/missing", "test1", "pwd"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman exec cannot be invoked", func() {
diff --git a/test/e2e/export_test.go b/test/e2e/export_test.go
index 8406b0e73..1c84c6f4d 100644
--- a/test/e2e/export_test.go
+++ b/test/e2e/export_test.go
@@ -72,6 +72,6 @@ var _ = Describe("Podman export", func() {
outfile := filepath.Join(podmanTest.TempDir, "container:with:colon.tar")
result := podmanTest.Podman([]string{"export", "-o", outfile, cid})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(0)))
+ Expect(result).To(ExitWithError())
})
})
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 49d2c12a8..5d3b1238a 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -40,13 +40,13 @@ var _ = Describe("Podman generate kube", func() {
It("podman generate pod kube on bogus object", func() {
session := podmanTest.Podman([]string{"generate", "kube", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman generate service kube on bogus object", func() {
session := podmanTest.Podman([]string{"generate", "kube", "-s", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman generate kube on container", func() {
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 314743a92..91072b023 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -37,19 +37,19 @@ var _ = Describe("Podman generate systemd", func() {
It("podman generate systemd on bogus container/pod", func() {
session := podmanTest.Podman([]string{"generate", "systemd", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman generate systemd bad restart policy", func() {
session := podmanTest.Podman([]string{"generate", "systemd", "--restart-policy", "never", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman generate systemd bad timeout value", func() {
session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "-1", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman generate systemd good timeout value", func() {
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index e10aef427..4acea06eb 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -38,7 +38,7 @@ var _ = Describe("Podman healthcheck run", func() {
It("podman healthcheck run bogus container", func() {
session := podmanTest.Podman([]string{"healthcheck", "run", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman healthcheck on valid container", func() {
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index ca1e9d384..7d029c52f 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -46,7 +46,7 @@ var _ = Describe("Podman inspect", func() {
SkipIfRemote()
session := podmanTest.Podman([]string{"inspect", "foobar4321"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman inspect with GO format", func() {
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index 017fe4a3f..834f86b77 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -35,7 +35,7 @@ var _ = Describe("Podman kill", func() {
It("podman kill bogus container", func() {
session := podmanTest.Podman([]string{"kill", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman container kill a running container by id", func() {
diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go
index 9209e1770..9ff358d26 100644
--- a/test/e2e/load_test.go
+++ b/test/e2e/load_test.go
@@ -143,7 +143,7 @@ var _ = Describe("Podman load", func() {
It("podman load bogus file", func() {
save := podmanTest.PodmanNoCache([]string{"load", "-i", "foobar.tar"})
save.WaitWithDefaultTimeout()
- Expect(save.ExitCode()).ToNot(Equal(0))
+ Expect(save).To(ExitWithError())
})
It("podman load multiple tags", func() {
diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go
index 4d476e05f..14cfed5db 100644
--- a/test/e2e/login_logout_test.go
+++ b/test/e2e/login_logout_test.go
@@ -109,7 +109,7 @@ var _ = Describe("Podman login and logout", func() {
session = podmanTest.Podman([]string{"push", ALPINE, testImg})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman login and logout with flag --authfile", func() {
@@ -198,7 +198,7 @@ var _ = Describe("Podman login and logout", func() {
session = podmanTest.Podman([]string{"push", ALPINE, "localhost:9001/test-alpine"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "localhost:9001"})
session.WaitWithDefaultTimeout()
@@ -218,7 +218,7 @@ var _ = Describe("Podman login and logout", func() {
session = podmanTest.Podman([]string{"push", ALPINE, testImg})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"push", ALPINE, "localhost:9001/test-alpine"})
session.WaitWithDefaultTimeout()
@@ -234,10 +234,10 @@ var _ = Describe("Podman login and logout", func() {
session = podmanTest.Podman([]string{"push", ALPINE, testImg})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"push", ALPINE, "localhost:9001/test-alpine"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
})
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index d17f60a5d..f34d85d76 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -108,7 +108,7 @@ var _ = Describe("Podman logs", func() {
It("podman logs latest and container name should fail", func() {
results := podmanTest.Podman([]string{"logs", "-l", "foobar"})
results.WaitWithDefaultTimeout()
- Expect(results.ExitCode()).ToNot(Equal(0))
+ Expect(results).To(ExitWithError())
})
It("podman logs two containers and should display short container IDs", func() {
diff --git a/test/e2e/negative_test.go b/test/e2e/negative_test.go
index 3cb54a20a..957609b7e 100644
--- a/test/e2e/negative_test.go
+++ b/test/e2e/negative_test.go
@@ -33,6 +33,6 @@ var _ = Describe("Podman negative command-line", func() {
It("podman snuffleupagus exits non-zero", func() {
session := podmanTest.Podman([]string{"snuffleupagus"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
})
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index 264219178..b83757cc0 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -182,19 +182,19 @@ var _ = Describe("Podman network create", func() {
It("podman network create with invalid subnet", func() {
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", "fail"})
nc.WaitWithDefaultTimeout()
- Expect(nc.ExitCode()).ToNot(BeZero())
+ Expect(nc).To(ExitWithError())
})
It("podman network create with invalid IP", func() {
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", "fail"})
nc.WaitWithDefaultTimeout()
- Expect(nc.ExitCode()).ToNot(BeZero())
+ Expect(nc).To(ExitWithError())
})
It("podman network create with invalid gateway for subnet", func() {
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", "fail"})
nc.WaitWithDefaultTimeout()
- Expect(nc.ExitCode()).ToNot(BeZero())
+ Expect(nc).To(ExitWithError())
})
It("podman network create two networks with same name should fail", func() {
@@ -205,13 +205,13 @@ var _ = Describe("Podman network create", func() {
ncFail := podmanTest.Podman([]string{"network", "create", "samename"})
ncFail.WaitWithDefaultTimeout()
- Expect(ncFail.ExitCode()).ToNot(BeZero())
+ Expect(ncFail).To(ExitWithError())
})
It("podman network create with invalid network name", func() {
nc := podmanTest.Podman([]string{"network", "create", "foo "})
nc.WaitWithDefaultTimeout()
- Expect(nc.ExitCode()).ToNot(BeZero())
+ Expect(nc).To(ExitWithError())
})
})
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index c61131078..39e08e2e8 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -52,13 +52,13 @@ var _ = Describe("Podman pause", func() {
It("podman pause bogus container", func() {
session := podmanTest.Podman([]string{"pause", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman unpause bogus container", func() {
session := podmanTest.Podman([]string{"unpause", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pause a created container by id", func() {
@@ -70,7 +70,7 @@ var _ = Describe("Podman pause", func() {
result := podmanTest.Podman([]string{"pause", cid})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(0)))
+ Expect(result).To(ExitWithError())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring(createdState))
})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 5d59f0eb0..7069e049d 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -23,7 +23,7 @@ metadata:
spec:
hostname: {{ .Hostname }}
containers:
-{{ with .Containers }}
+{{ with .Ctrs }}
{{ range . }}
- command:
{{ range .Cmd }}
@@ -67,47 +67,128 @@ spec:
status: {}
`
-type Pod struct {
- Name string
- Hostname string
- Containers []Container
-}
-
-type Container struct {
- Cmd []string
- Image string
- Name string
- SecurityContext bool
- Caps bool
- CapAdd []string
- CapDrop []string
-}
+var (
+ defaultCtrName = "testCtr"
+ defaultCtrCmd = []string{"top"}
+ defaultCtrImage = ALPINE
+ defaultPodName = "testPod"
+)
-func generateKubeYaml(name string, hostname string, ctrs []Container, fileName string) error {
+func generateKubeYaml(pod *Pod, fileName string) error {
f, err := os.Create(fileName)
if err != nil {
return err
}
defer f.Close()
- testPod := Pod{name, hostname, ctrs}
t, err := template.New("pod").Parse(yamlTemplate)
if err != nil {
return err
}
- if err := t.Execute(f, testPod); err != nil {
+ if err := t.Execute(f, pod); err != nil {
return err
}
return nil
}
+// Pod describes the options a kube yaml can be configured at pod level
+type Pod struct {
+ Name string
+ Hostname string
+ Ctrs []*Ctr
+}
+
+// getPod takes a list of podOptions and returns a pod with sane defaults
+// and the configured options
+// if no containers are added, it will add the default container
+func getPod(options ...podOption) *Pod {
+ p := Pod{defaultPodName, "", make([]*Ctr, 0)}
+ for _, option := range options {
+ option(&p)
+ }
+ if len(p.Ctrs) == 0 {
+ p.Ctrs = []*Ctr{getCtr()}
+ }
+ return &p
+}
+
+type podOption func(*Pod)
+
+func withHostname(h string) podOption {
+ return func(pod *Pod) {
+ pod.Hostname = h
+ }
+}
+
+func withCtr(c *Ctr) podOption {
+ return func(pod *Pod) {
+ pod.Ctrs = append(pod.Ctrs, c)
+ }
+}
+
+// Ctr describes the options a kube yaml can be configured at container level
+type Ctr struct {
+ Name string
+ Image string
+ Cmd []string
+ SecurityContext bool
+ Caps bool
+ CapAdd []string
+ CapDrop []string
+}
+
+// getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
+// and the configured options
+func getCtr(options ...ctrOption) *Ctr {
+ c := Ctr{defaultCtrName, defaultCtrImage, defaultCtrCmd, true, false, nil, nil}
+ for _, option := range options {
+ option(&c)
+ }
+ return &c
+}
+
+type ctrOption func(*Ctr)
+
+func withCmd(cmd []string) ctrOption {
+ return func(c *Ctr) {
+ c.Cmd = cmd
+ }
+}
+
+func withImage(img string) ctrOption {
+ return func(c *Ctr) {
+ c.Image = img
+ }
+}
+
+func withSecurityContext(sc bool) ctrOption {
+ return func(c *Ctr) {
+ c.SecurityContext = sc
+ }
+}
+
+func withCapAdd(caps []string) ctrOption {
+ return func(c *Ctr) {
+ c.CapAdd = caps
+ c.Caps = true
+ }
+}
+
+func withCapDrop(caps []string) ctrOption {
+ return func(c *Ctr) {
+ c.CapDrop = caps
+ c.Caps = true
+ }
+}
+
var _ = Describe("Podman generate kube", func() {
var (
tempdir string
err error
podmanTest *PodmanTestIntegration
+ kubeYaml string
)
BeforeEach(func() {
@@ -118,6 +199,8 @@ var _ = Describe("Podman generate kube", func() {
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
podmanTest.SeedImages()
+
+ kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml")
})
AfterEach(func() {
@@ -127,123 +210,98 @@ var _ = Describe("Podman generate kube", func() {
})
It("podman play kube test correct command", func() {
- ctrName := "testCtr"
- ctrCmd := []string{"top"}
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, false, nil, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
-
- err := generateKubeYaml("test", "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
- Expect(inspect.OutputToString()).To(ContainSubstring(ctrCmd[0]))
+ Expect(inspect.OutputToString()).To(ContainSubstring(defaultCtrCmd[0]))
})
It("podman play kube test correct output", func() {
- ctrName := "testCtr"
- ctrCmd := []string{"echo", "hello"}
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, false, nil, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
+ p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}))))
- err := generateKubeYaml("test", "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(p, kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- logs := podmanTest.Podman([]string{"logs", ctrName})
+ logs := podmanTest.Podman([]string{"logs", defaultCtrName})
logs.WaitWithDefaultTimeout()
Expect(logs.ExitCode()).To(Equal(0))
Expect(logs.OutputToString()).To(ContainSubstring("hello"))
- inspect := podmanTest.Podman([]string{"inspect", ctrName, "--format", "'{{ .Config.Cmd }}'"})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName, "--format", "'{{ .Config.Cmd }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(ContainSubstring("hello"))
})
It("podman play kube test hostname", func() {
- podName := "test"
- ctrName := "testCtr"
- ctrCmd := []string{"top"}
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, false, nil, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
-
- err := generateKubeYaml(podName, "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName, "--format", "{{ .Config.Hostname }}"})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName, "--format", "{{ .Config.Hostname }}"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
- Expect(inspect.OutputToString()).To(Equal(podName))
+ Expect(inspect.OutputToString()).To(Equal(defaultPodName))
})
It("podman play kube test with customized hostname", func() {
hostname := "myhostname"
- ctrName := "testCtr"
- ctrCmd := []string{"top"}
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, false, nil, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
-
- err := generateKubeYaml("test", hostname, []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(withHostname(hostname)), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName, "--format", "{{ .Config.Hostname }}"})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName, "--format", "{{ .Config.Hostname }}"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(Equal(hostname))
})
It("podman play kube cap add", func() {
- ctrName := "testCtr"
- ctrCmd := []string{"cat", "/proc/self/status"}
capAdd := "CAP_SYS_ADMIN"
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, true, []string{capAdd}, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
+ ctr := getCtr(withCapAdd([]string{capAdd}), withCmd([]string{"cat", "/proc/self/status"}))
- err := generateKubeYaml("test", "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(withCtr(ctr)), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(ContainSubstring(capAdd))
})
- It("podman play kube cap add", func() {
- ctrName := "testCtr"
- ctrCmd := []string{"cat", "/proc/self/status"}
- capDrop := "CAP_SYS_ADMIN"
- testContainer := Container{ctrCmd, ALPINE, ctrName, true, true, []string{capDrop}, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
+ It("podman play kube cap drop", func() {
+ capDrop := "CAP_CHOWN"
+ ctr := getCtr(withCapDrop([]string{capDrop}))
- err := generateKubeYaml("test", "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(withCtr(ctr)), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(ContainSubstring(capDrop))
@@ -251,19 +309,14 @@ var _ = Describe("Podman generate kube", func() {
It("podman play kube no security context", func() {
// expect play kube to not fail if no security context is specified
- ctrName := "testCtr"
- ctrCmd := "ls"
- testContainer := Container{[]string{ctrCmd}, ALPINE, ctrName, false, false, nil, nil}
- tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml")
-
- err := generateKubeYaml("test", "", []Container{testContainer}, tempFile)
+ err := generateKubeYaml(getPod(withCtr(getCtr(withSecurityContext(false)))), kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", tempFile})
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect := podmanTest.Podman([]string{"inspect", defaultCtrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go
index 3897aa851..c8072f308 100644
--- a/test/e2e/pod_infra_container_test.go
+++ b/test/e2e/pod_infra_container_test.go
@@ -122,7 +122,7 @@ var _ = Describe("Podman pod create", func() {
session = podmanTest.Podman([]string{"run", fedoraMinimal, "curl", "localhost"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pod correctly sets up IPCNS", func() {
@@ -218,7 +218,7 @@ var _ = Describe("Podman pod create", func() {
session = podmanTest.Podman([]string{"run", "--pod", podID, "--network", "bridge", nginx, "curl", "localhost"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pod container can override pod pid NS", func() {
@@ -309,7 +309,7 @@ var _ = Describe("Podman pod create", func() {
session = podmanTest.Podman([]string{"rm", infraID})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"pod", "rm", podID})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 488dd1685..49c647528 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -35,7 +35,7 @@ var _ = Describe("Podman pod inspect", func() {
It("podman inspect bogus pod", func() {
session := podmanTest.Podman([]string{"pod", "inspect", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).Should(ExitWithError())
})
It("podman inspect a pod", func() {
diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go
index 7cf67bbfc..a3efec46c 100644
--- a/test/e2e/pod_kill_test.go
+++ b/test/e2e/pod_kill_test.go
@@ -36,7 +36,7 @@ var _ = Describe("Podman pod kill", func() {
It("podman pod kill bogus", func() {
session := podmanTest.Podman([]string{"pod", "kill", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pod kill a pod by id", func() {
diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go
index 619ee6f12..73707926d 100644
--- a/test/e2e/pod_pause_test.go
+++ b/test/e2e/pod_pause_test.go
@@ -38,13 +38,13 @@ var _ = Describe("Podman pod pause", func() {
It("podman pod pause bogus pod", func() {
session := podmanTest.Podman([]string{"pod", "pause", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman unpause bogus pod", func() {
session := podmanTest.Podman([]string{"pod", "unpause", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pod pause a created pod by id", func() {
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 6d5873caa..aa07be55c 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -107,7 +107,7 @@ var _ = Describe("Podman ps", func() {
It("podman pod ps mutually exclusive flags", func() {
session := podmanTest.Podman([]string{"pod", "ps", "-q", "--format", "{{.ID}}"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index f0689f152..de68e885a 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -135,7 +135,7 @@ var _ = Describe("Podman pod rm", func() {
fmt.Printf("Removing all empty pods\n")
result := podmanTest.Podman([]string{"pod", "rm", "-a"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(0)))
+ Expect(result).To(ExitWithError())
foundExpectedError, _ := result.ErrorGrepString("contains containers and cannot be removed")
Expect(foundExpectedError).To(Equal(true))
diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go
index 01176f97c..4d573a2c7 100644
--- a/test/e2e/pod_stats_test.go
+++ b/test/e2e/pod_stats_test.go
@@ -169,7 +169,7 @@ var _ = Describe("Podman pod stats", func() {
Expect(session.ExitCode()).To(Equal(0))
stats := podmanTest.Podman([]string{"pod", "stats", "-a", "--no-reset", "--no-stream", "--format", "\"table {{.ID}} \""})
stats.WaitWithDefaultTimeout()
- Expect(stats.ExitCode()).ToNot(Equal(0))
+ Expect(stats).To(ExitWithError())
})
})
diff --git a/test/e2e/port_test.go b/test/e2e/port_test.go
index 53fc33a01..5bb86d558 100644
--- a/test/e2e/port_test.go
+++ b/test/e2e/port_test.go
@@ -39,13 +39,13 @@ var _ = Describe("Podman port", func() {
It("podman port all and latest", func() {
result := podmanTest.Podman([]string{"port", "-a", "-l"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("podman port all and extra", func() {
result := podmanTest.Podman([]string{"port", "-a", "foobar"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("podman port -l nginx", func() {
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 4130f409e..a436d4f09 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -230,11 +230,11 @@ var _ = Describe("Podman ps", func() {
It("podman ps mutually exclusive flags", func() {
session := podmanTest.Podman([]string{"ps", "-aqs"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"ps", "-a", "--ns", "-s"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman --sort by size", func() {
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index 68fcaf133..537084220 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -40,7 +40,7 @@ var _ = Describe("Podman pull", func() {
It("podman pull from docker a not existing image", func() {
session := podmanTest.PodmanNoCache([]string{"pull", "ibetthisdoesntexistthere:foo"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pull from docker with tag", func() {
@@ -96,7 +96,7 @@ var _ = Describe("Podman pull", func() {
It("podman pull bogus image", func() {
session := podmanTest.PodmanNoCache([]string{"pull", "umohnani/get-started"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman pull from docker-archive", func() {
diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go
index 4360eeece..50f0ca6d9 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -140,7 +140,7 @@ var _ = Describe("Podman push", func() {
push := podmanTest.PodmanNoCache([]string{"push", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"})
push.WaitWithDefaultTimeout()
- Expect(push.ExitCode()).To(Not(Equal(0)))
+ Expect(push).To(ExitWithError())
push = podmanTest.PodmanNoCache([]string{"push", "--creds=podmantest:test", "--tls-verify=false", ALPINE, "localhost:5000/tlstest"})
push.WaitWithDefaultTimeout()
@@ -151,11 +151,11 @@ var _ = Describe("Podman push", func() {
push = podmanTest.PodmanNoCache([]string{"push", "--creds=podmantest:wrongpasswd", ALPINE, "localhost:5000/credstest"})
push.WaitWithDefaultTimeout()
- Expect(push.ExitCode()).To(Not(Equal(0)))
+ Expect(push).To(ExitWithError())
push = podmanTest.PodmanNoCache([]string{"push", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"})
push.WaitWithDefaultTimeout()
- Expect(push.ExitCode()).To(Not(Equal(0)))
+ Expect(push).To(ExitWithError())
push = podmanTest.PodmanNoCache([]string{"push", "--creds=podmantest:test", ALPINE, "localhost:5000/defaultflags"})
push.WaitWithDefaultTimeout()
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 506adee7e..80e877de1 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -102,7 +102,7 @@ var _ = Describe("Podman rmi", func() {
// Trying without --force should fail
result := podmanTest.PodmanNoCache([]string{"rmi", alpineId})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
// With --force it should work
resultForce := podmanTest.PodmanNoCache([]string{"rmi", "-f", alpineId})
diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go
index 42f17985c..29ceb4e67 100644
--- a/test/e2e/run_cpu_test.go
+++ b/test/e2e/run_cpu_test.go
@@ -164,12 +164,12 @@ var _ = Describe("Podman run cpu", func() {
It("podman run cpus and cpu-period", func() {
result := podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", "--cpus=0.5", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(0)))
+ Expect(result).To(ExitWithError())
})
It("podman run cpus and cpu-quota", func() {
result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", "--cpus=0.5", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(0)))
+ Expect(result).To(ExitWithError())
})
})
diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go
index d3b4b0e32..eae3f574c 100644
--- a/test/e2e/run_device_test.go
+++ b/test/e2e/run_device_test.go
@@ -37,7 +37,7 @@ var _ = Describe("Podman run device", func() {
It("podman run bad device test", func() {
session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/baddevice", ALPINE, "true"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run device test", func() {
@@ -70,7 +70,7 @@ var _ = Describe("Podman run device", func() {
It("podman run device rename and bad permission test", func() {
session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:rd", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run device host device and container device parameter are directories", func() {
diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go
index dc0f4a8fb..02b9ff8d1 100644
--- a/test/e2e/run_dns_test.go
+++ b/test/e2e/run_dns_test.go
@@ -51,7 +51,7 @@ var _ = Describe("Podman run dns", func() {
It("podman run add bad dns server", func() {
session := podmanTest.Podman([]string{"run", "--dns=foobar", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run add dns server", func() {
@@ -71,7 +71,7 @@ var _ = Describe("Podman run dns", func() {
It("podman run add bad host", func() {
session := podmanTest.Podman([]string{"run", "--add-host=foo:1.2", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run add host", func() {
@@ -105,15 +105,15 @@ var _ = Describe("Podman run dns", func() {
It("podman run mutually excludes --dns* and --network", func() {
session := podmanTest.Podman([]string{"run", "--dns=1.2.3.4", "--network", "container:ALPINE", ALPINE})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"run", "--dns-opt=1.2.3.4", "--network", "container:ALPINE", ALPINE})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"run", "--dns-search=foobar.com", "--network", "none", ALPINE})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"run", "--dns=1.2.3.4", "--network", "host", ALPINE})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 31291d373..ec12f709a 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -74,7 +74,7 @@ var _ = Describe("Podman run networking", func() {
Expect(results.OutputToString()).To(ContainSubstring("8000"))
ncBusy := SystemExec("nc", []string{"-l", "-p", "80"})
- Expect(ncBusy.ExitCode()).ToNot(Equal(0))
+ Expect(ncBusy).To(ExitWithError())
})
It("podman run network expose ports in image metadata", func() {
@@ -229,7 +229,7 @@ var _ = Describe("Podman run networking", func() {
It("podman run network in bogus user created network namespace", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxy", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("stat /run/netns/xxy: no such file or directory"))
})
})
diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go
index e3e86fc66..c8ba68efc 100644
--- a/test/e2e/run_ns_test.go
+++ b/test/e2e/run_ns_test.go
@@ -48,7 +48,7 @@ var _ = Describe("Podman run ns", func() {
session = podmanTest.Podman([]string{"run", "--pid=badpid", fedoraMinimal, "bash", "-c", "echo $$"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run --cgroup private test", func() {
@@ -102,6 +102,6 @@ var _ = Describe("Podman run ns", func() {
It("podman run bad ipc pid test", func() {
session := podmanTest.Podman([]string{"run", "--ipc=badpid", fedoraMinimal, "bash", "-c", "echo $$"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
})
})
diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go
index 7a877ebdc..5b4842fea 100644
--- a/test/e2e/run_staticip_test.go
+++ b/test/e2e/run_staticip_test.go
@@ -40,19 +40,19 @@ var _ = Describe("Podman run with --ip flag", func() {
It("Podman run --ip with garbage address", func() {
result := podmanTest.Podman([]string{"run", "-ti", "--ip", "114232346", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman run --ip with v6 address", func() {
result := podmanTest.Podman([]string{"run", "-ti", "--ip", "2001:db8:bad:beef::1", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman run --ip with non-allocatable IP", func() {
result := podmanTest.Podman([]string{"run", "-ti", "--ip", "203.0.113.124", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("Podman run with specified static IP has correct IP", func() {
@@ -70,6 +70,6 @@ var _ = Describe("Podman run with --ip flag", func() {
Expect(result.ExitCode()).To(Equal(0))
result = podmanTest.Podman([]string{"run", "-ti", "--ip", ip, ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 1e6f1d97d..874aa498e 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -170,7 +170,7 @@ var _ = Describe("Podman run", func() {
session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", jsonFile}, ""), ALPINE, "pwd"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
match, _ := session.GrepString("Operation not permitted")
Expect(match).Should(BeTrue())
})
@@ -730,11 +730,11 @@ USER mail`
session := podmanTest.Podman([]string{"run", "--volume", ":/myvol1:z", ALPINE, "touch", "/myvol2/foo.txt"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
session = podmanTest.Podman([]string{"run", "--volume", vol1 + ":", ALPINE, "touch", "/myvol2/foo.txt"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
})
@@ -815,7 +815,7 @@ USER mail`
It("podman run --rm failed container should delete itself", func() {
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "foo"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
numContainers := podmanTest.NumberOfContainers()
Expect(numContainers).To(Equal(0))
@@ -824,7 +824,7 @@ USER mail`
It("podman run failed container should NOT delete itself", func() {
session := podmanTest.Podman([]string{"run", ALPINE, "foo"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
numContainers := podmanTest.NumberOfContainers()
Expect(numContainers).To(Equal(1))
@@ -840,28 +840,28 @@ USER mail`
It("podman run with bad healthcheck retries", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-retries", "0", ALPINE, "top"})
session.Wait()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-retries must be greater than 0"))
})
It("podman run with bad healthcheck timeout", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-timeout", "0s", ALPINE, "top"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-timeout must be at least 1 second"))
})
It("podman run with bad healthcheck start-period", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-start-period", "-1s", ALPINE, "top"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-start-period must be 0 seconds or greater"))
})
It("podman run with --add-host and --no-hosts fails", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session).To(ExitWithError())
})
It("podman run --http-proxy test", func() {
@@ -990,6 +990,6 @@ USER mail`
It("podman run with cgroups=garbage errors", func() {
session := podmanTest.Podman([]string{"run", "-d", "--cgroups=garbage", ALPINE, "top"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index bc3a14b66..94bfebab7 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -155,7 +155,7 @@ var _ = Describe("Podman run with volumes", func() {
session = podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,ro=true,rw=false", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run with volume flag and multiple named volumes", func() {
@@ -191,7 +191,7 @@ var _ = Describe("Podman run with volumes", func() {
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
It("podman run with tmpfs named volume mounts and unmounts", func() {
diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go
index 4e2cb501e..52a011efb 100644
--- a/test/e2e/runlabel_test.go
+++ b/test/e2e/runlabel_test.go
@@ -75,12 +75,12 @@ var _ = Describe("podman container runlabel", func() {
It("podman container runlabel bogus label should result in non-zero exit code", func() {
result := podmanTest.Podman([]string{"container", "runlabel", "RUN", ALPINE})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
It("podman container runlabel bogus label in remote image should result in non-zero exit", func() {
result := podmanTest.Podman([]string{"container", "runlabel", "RUN", "docker.io/library/ubuntu:latest"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).ToNot(Equal(0))
+ Expect(result).To(ExitWithError())
})
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index be1ede962..52dab923b 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -72,7 +72,7 @@ var _ = Describe("Podman save", func() {
save := podmanTest.PodmanNoCache([]string{"save", "-o", outfile, "FOOBAR"})
save.WaitWithDefaultTimeout()
- Expect(save.ExitCode()).To(Not(Equal(0)))
+ Expect(save).To(ExitWithError())
})
It("podman save to directory with oci format", func() {
@@ -113,7 +113,7 @@ var _ = Describe("Podman save", func() {
save := podmanTest.PodmanNoCache([]string{"save", "--compress", "--format", "docker-dir", "-o", outdir, ALPINE})
save.WaitWithDefaultTimeout()
- Expect(save.ExitCode()).To(Not(Equal(0)))
+ Expect(save).To(ExitWithError())
})
})
diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go
index 13f14183b..da581f158 100644
--- a/test/e2e/start_test.go
+++ b/test/e2e/start_test.go
@@ -108,7 +108,7 @@ var _ = Describe("Podman start", func() {
start := podmanTest.Podman([]string{"start", "-l"})
start.WaitWithDefaultTimeout()
- Expect(start.ExitCode()).Should(BeNumerically(">", 0))
+ Expect(start).To(ExitWithError())
Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout, 3.0).Should(BeZero())
})
@@ -120,7 +120,7 @@ var _ = Describe("Podman start", func() {
start := podmanTest.Podman([]string{"start", "-l"})
start.WaitWithDefaultTimeout()
- Expect(start.ExitCode()).Should(BeNumerically(">", 0))
+ Expect(start).To(ExitWithError())
Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout, 3.0).Should(Equal(1))
})
diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go
index 77e8abbd4..41107b5ba 100644
--- a/test/e2e/volume_create_test.go
+++ b/test/e2e/volume_create_test.go
@@ -61,6 +61,6 @@ var _ = Describe("Podman volume create", func() {
It("podman create volume with bad volume option", func() {
session := podmanTest.Podman([]string{"volume", "create", "--opt", "badOpt=bad"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
})
diff --git a/test/e2e/volume_rm_test.go b/test/e2e/volume_rm_test.go
index 61cf9b893..6f2020828 100644
--- a/test/e2e/volume_rm_test.go
+++ b/test/e2e/volume_rm_test.go
@@ -56,7 +56,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "rm", "myvol"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring(cid))
session = podmanTest.Podman([]string{"volume", "rm", "-f", "myvol"})
@@ -116,7 +116,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "rm", "myv"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index 11cb98269..472fdd1ab 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -29,4 +29,24 @@ load helpers
run_podman rm $cid
}
+@test "podman exec - leak check" {
+ skip_if_remote
+
+ # Start a container in the background then run exec command
+ # three times and make sure no any exec pid hash file leak
+ run_podman run -td $IMAGE /bin/sh
+ cid="$output"
+
+ is "$(check_exec_pid)" "" "exec pid hash file indeed doesn't exist"
+
+ for i in {1..3}; do
+ run_podman exec $cid /bin/true
+ done
+
+ is "$(check_exec_pid)" "" "there isn't any exec pid hash file leak"
+
+ run_podman stop --time 1 $cid
+ run_podman rm -f $cid
+}
+
# vim: filetype=sh
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 3d607f4bd..8c061d2c9 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -373,5 +373,19 @@ function random_string() {
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length
}
+
+#########################
+# find_exec_pid_files # Returns nothing or exec_pid hash files
+#########################
+#
+# Return exec_pid hash files if exists, otherwise, return nothing
+#
+function find_exec_pid_files() {
+ run_podman info --format '{{.store.RunRoot}}'
+ local storage_path="$output"
+ if [ -d $storage_path ]; then
+ find $storage_path -type f -iname 'exec_pid_*'
+ fi
+}
# END miscellaneous tools
###############################################################################
diff --git a/test/utils/matchers.go b/test/utils/matchers.go
new file mode 100644
index 000000000..07c1232e7
--- /dev/null
+++ b/test/utils/matchers.go
@@ -0,0 +1,61 @@
+package utils
+
+import (
+ "fmt"
+
+ "github.com/onsi/gomega/format"
+ "github.com/onsi/gomega/gexec"
+)
+
+// ExitWithError matches when assertion is > argument. Default 0
+// Modeled after the gomega Exit() matcher
+func ExitWithError(optionalExitCode ...int) *exitMatcher {
+ exitCode := 0
+ if len(optionalExitCode) > 0 {
+ exitCode = optionalExitCode[0]
+ }
+ return &exitMatcher{exitCode: exitCode}
+}
+
+type exitMatcher struct {
+ exitCode int
+ actualExitCode int
+}
+
+func (m *exitMatcher) Match(actual interface{}) (success bool, err error) {
+ exiter, ok := actual.(gexec.Exiter)
+ if !ok {
+ return false, fmt.Errorf("ExitWithError must be passed a gexec.Exiter (Missing method ExitCode() int) Got:\n#{format.Object(actual, 1)}")
+ }
+
+ m.actualExitCode = exiter.ExitCode()
+ if m.actualExitCode == -1 {
+ return false, nil
+ }
+ return m.actualExitCode > m.exitCode, nil
+}
+
+func (m *exitMatcher) FailureMessage(actual interface{}) (message string) {
+ if m.actualExitCode == -1 {
+ return "Expected process to exit. It did not."
+ }
+ return format.Message(m.actualExitCode, "to be greater than exit code:", m.exitCode)
+}
+
+func (m *exitMatcher) NegatedFailureMessage(actual interface{}) (message string) {
+ if m.actualExitCode == -1 {
+ return "you really shouldn't be able to see this!"
+ } else {
+ if m.exitCode == -1 {
+ return "Expected process not to exit. It did."
+ }
+ return format.Message(m.actualExitCode, "is less than or equal to exit code:", m.exitCode)
+ }
+}
+func (m *exitMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
+ session, ok := actual.(*gexec.Session)
+ if ok {
+ return session.ExitCode() == -1
+ }
+ return true
+}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 7d373bd56..ad78d9792 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -268,7 +268,7 @@ func (s *PodmanSession) ErrorGrepString(term string) (bool, []string) {
return matches, greps
}
-//LineInOutputStartsWith returns true if a line in a
+// LineInOutputStartsWith returns true if a line in a
// session output starts with the supplied string
func (s *PodmanSession) LineInOuputStartsWith(term string) bool {
for _, i := range s.OutputToStringArray() {
@@ -279,7 +279,7 @@ func (s *PodmanSession) LineInOuputStartsWith(term string) bool {
return false
}
-//LineInOutputContains returns true if a line in a
+// LineInOutputContains returns true if a line in a
// session output contains the supplied string
func (s *PodmanSession) LineInOutputContains(term string) bool {
for _, i := range s.OutputToStringArray() {
@@ -290,7 +290,7 @@ func (s *PodmanSession) LineInOutputContains(term string) bool {
return false
}
-//LineInOutputContainsTag returns true if a line in the
+// LineInOutputContainsTag returns true if a line in the
// session's output contains the repo-tag pair as returned
// by podman-images(1).
func (s *PodmanSession) LineInOutputContainsTag(repo, tag string) bool {
@@ -348,7 +348,7 @@ func StringInSlice(s string, sl []string) bool {
return false
}
-//tagOutPutToMap parses each string in imagesOutput and returns
+// tagOutPutToMap parses each string in imagesOutput and returns
// a map of repo:tag pairs. Notice, the first array item will
// be skipped as it's considered to be the header.
func tagOutputToMap(imagesOutput []string) map[string]string {
@@ -371,7 +371,7 @@ func tagOutputToMap(imagesOutput []string) map[string]string {
return m
}
-//GetHostDistributionInfo returns a struct with its distribution name and version
+// GetHostDistributionInfo returns a struct with its distribution name and version
func GetHostDistributionInfo() HostOS {
f, err := os.Open(OSReleasePath)
defer f.Close()
@@ -415,7 +415,7 @@ func IsKernelNewerThan(version string) (bool, error) {
}
-//IsCommandAvaible check if command exist
+// IsCommandAvaible check if command exist
func IsCommandAvailable(command string) bool {
check := exec.Command("bash", "-c", strings.Join([]string{"command -v", command}, " "))
err := check.Run()
diff --git a/troubleshooting.md b/troubleshooting.md
index 6fed719f7..c4e577645 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -410,3 +410,22 @@ You'll need to either:
* configure the host to use cgroups v1
* update the image to use an updated version of systemd.
+
+### 17) rootless containers exit once the user session exits
+
+
+You need to set lingering mode through loginctl to prevent user processes to be killed once
+the user session completed.
+
+#### Symptom
+
+Once the user logs out all the containers exit.
+
+#### Solution
+You'll need to either:
+
+* loginctl enable-linger $UID
+
+or as root if your user has not enough privileges.
+
+* sudo loginctl enable-linger $UID
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 712bfb69a..65a99869e 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -346,12 +346,12 @@ github.com/onsi/ginkgo/internal/specrunner
# github.com/onsi/gomega v1.7.0
github.com/onsi/gomega
github.com/onsi/gomega/gexec
+github.com/onsi/gomega/format
github.com/onsi/gomega/internal/assertion
github.com/onsi/gomega/internal/asyncassertion
github.com/onsi/gomega/internal/testingtsupport
github.com/onsi/gomega/matchers
github.com/onsi/gomega/types
-github.com/onsi/gomega/format
github.com/onsi/gomega/gbytes
github.com/onsi/gomega/internal/oraclematcher
github.com/onsi/gomega/matchers/support/goraph/bipartitegraph
diff --git a/version/version.go b/version/version.go
index 2c4d69b78..c0dbeadfe 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.6.2-dev"
+const Version = "1.6.3-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility