summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--.papr.sh3
-rwxr-xr-xcontrib/cirrus/optional_system_test.sh24
-rw-r--r--contrib/python/podman/test/test_pods_ctnrs.py3
-rw-r--r--docs/podman-build.1.md2
-rw-r--r--docs/podman-create.1.md12
-rw-r--r--docs/podman-run.1.md13
-rw-r--r--libpod/container_api.go23
-rw-r--r--libpod/container_internal.go106
-rw-r--r--libpod/container_internal_linux.go41
-rw-r--r--libpod/oci.go61
-rw-r--r--libpod/runtime_ctr.go2
-rw-r--r--libpod/runtime_pod_linux.go19
-rw-r--r--pkg/lookup/lookup.go8
-rw-r--r--test/e2e/pause_test.go4
-rw-r--r--test/e2e/run_dns_test.go9
16 files changed, 241 insertions, 91 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index c5d35141e..f78205a49 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -63,6 +63,8 @@ full_vm_testing_task:
integration_test_script: $SCRIPT_BASE/integration_test.sh
+ optional_system_test_script: $SCRIPT_BASE/optional_system_test.sh
+
success_script: $SCRIPT_BASE/success.sh
diff --git a/.papr.sh b/.papr.sh
index 120b3d94b..284326709 100644
--- a/.papr.sh
+++ b/.papr.sh
@@ -139,6 +139,3 @@ if [ $integrationtest -eq 1 ]; then
fi
make ginkgo GOPATH=/go $INTEGRATION_TEST_ENVS
fi
-
-
-exit 0
diff --git a/contrib/cirrus/optional_system_test.sh b/contrib/cirrus/optional_system_test.sh
new file mode 100755
index 000000000..705dda5ad
--- /dev/null
+++ b/contrib/cirrus/optional_system_test.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+source $(dirname $0)/lib.sh
+
+MAGIC_RE='\*\*\*\s*CIRRUS:\s*SYSTEM\s*TEST\s*\*\*\*'
+if ! echo "$CIRRUS_CHANGE_MESSAGE" | egrep -q "$MAGIC_RE"
+then
+ echo "Skipping system-testing because PR title or description"
+ echo "does not match regular expression: $MAGIC_RE"
+ exit 0
+fi
+
+req_env_var "
+GOSRC $GOSRC
+OS_RELEASE_ID $OS_RELEASE_ID
+OS_RELEASE_VER $OS_RELEASE_VER
+"
+
+show_env_vars
+
+set -x
+cd "$GOSRC"
+make localsystem
diff --git a/contrib/python/podman/test/test_pods_ctnrs.py b/contrib/python/podman/test/test_pods_ctnrs.py
index 14ce95c8a..009e30720 100644
--- a/contrib/python/podman/test/test_pods_ctnrs.py
+++ b/contrib/python/podman/test/test_pods_ctnrs.py
@@ -52,7 +52,8 @@ class TestPodsCtnrs(PodmanTestCase):
status = FoldedString(pod.containersinfo[0]['status'])
self.assertIn(status, ('stopped', 'exited', 'running'))
- killed = pod.kill()
+ # Pod kill is broken, so use stop for now
+ killed = pod.stop()
self.assertEqual(pod, killed)
def test_999_remove(self):
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
index 0cbce15c0..f887d68cd 100644
--- a/docs/podman-build.1.md
+++ b/docs/podman-build.1.md
@@ -171,7 +171,7 @@ value can be entered. The password is entered without echo.
**--disable-content-trust**
This is a Docker specific option to disable image verification to a Docker
-registry and is not supported by Buildah. This flag is a NOOP and provided
+registry and is not supported by Podman. This flag is a NOOP and provided
soley for scripting compatibility.
**--file, -f** *Dockerfile*
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 5a4d7fb5a..68c00685b 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -66,7 +66,7 @@ Write the container ID to the file
**--conmon-pidfile**=""
-Write the pid of the `conmon` process to a file. `conmon` daemonizes separate from Podman, so this is necessary when using systemd to restart Podman containers.
+Write the pid of the `conmon` process to a file. `conmon` runs in a separate process than Podman, so this is necessary when using systemd to restart Podman containers.
**--cpu-count**=*0*
@@ -321,13 +321,13 @@ Not implemented
**--log-driver**="*json-file*"
-Logging driver for the container. Default is defined by daemon `--log-driver` flag.
-**Warning**: the `podman logs` command works only for the `json-file` and
-`journald` logging drivers.
+Logging driver for the container. Currently not supported. This flag is a NOOP provided soley for scripting compatibility.
**--log-opt**=[]
-Logging driver specific options.
+Logging driver specific options. Used to set the path to the container log file. For example:
+
+`--log-opt path=/var/log/container/mycontainer.json`
**--mac-address**=""
@@ -414,7 +414,7 @@ UUID short identifier (“f78375b1c487”)
Name (“jonah”)
podman generates a UUID for each container, and if a name is not assigned
-to the container with **--name** then the daemon will also generate a random
+to the container with **--name** then it will generate a random
string name. The name is useful any place you need to identify a container.
This works for both background and foreground containers.
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index b708e3407..912026a55 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -78,7 +78,7 @@ Write the container ID to the file
**--conmon-pidfile**=""
-Write the pid of the `conmon` process to a file. `conmon` daemonizes separate from Podman, so this is necessary when using systemd to restart Podman containers.
+Write the pid of the `conmon` process to a file. `conmon` runs in a separate process than Podman, so this is necessary when using systemd to restart Podman containers.
**--cpu-period**=*0*
@@ -333,16 +333,13 @@ Not implemented
**--log-driver**="*json-file*"
-Logging driver for the container. Default is defined by daemon `--log-driver` flag.
-
-**Warning**: the `podman logs` command works only for the `json-file` and
-`journald` logging drivers.
+Logging driver for the container. Currently not supported. This flag is a NOOP provided soley for scripting compatibility.
**--log-opt**=[]
-Logging driver specific options.
+Logging driver specific options. Used to set the path to the container log file. For example:
-`path=/var/log/container/mycontainer.json`: Set the path to the container log file.
+`--log-opt path=/var/log/container/mycontainer.json`
**--mac-address**=""
@@ -399,7 +396,7 @@ The operator can identify a container in three ways:
- Name (“jonah”)
podman generates a UUID for each container, and if a name is not assigned
-to the container with **--name** then the daemon will also generate a random
+to the container with **--name** then it will generate a random
string name. The name is useful any place you need to identify a container.
This works for both background and foreground containers.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 30c67eb2a..d99aec5b4 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -46,9 +46,6 @@ func (c *Container) Init(ctx context.Context) (err error) {
return errors.Wrapf(ErrCtrStateInvalid, "some dependencies of container %s are not started: %s", c.ID(), depString)
}
- if err := c.prepare(); err != nil {
- return err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -57,6 +54,10 @@ func (c *Container) Init(ctx context.Context) (err error) {
}
}()
+ if err := c.prepare(); err != nil {
+ return err
+ }
+
if c.state.State == ContainerStateStopped {
// Reinitialize the container
return c.reinit(ctx)
@@ -99,9 +100,6 @@ func (c *Container) Start(ctx context.Context) (err error) {
return errors.Wrapf(ErrCtrStateInvalid, "some dependencies of container %s are not started: %s", c.ID(), depString)
}
- if err := c.prepare(); err != nil {
- return err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -110,6 +108,10 @@ func (c *Container) Start(ctx context.Context) (err error) {
}
}()
+ if err := c.prepare(); err != nil {
+ return err
+ }
+
if c.state.State == ContainerStateStopped {
// Reinitialize the container if we need to
if err := c.reinit(ctx); err != nil {
@@ -164,9 +166,6 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams,
return nil, errors.Wrapf(ErrCtrStateInvalid, "some dependencies of container %s are not started: %s", c.ID(), depString)
}
- if err := c.prepare(); err != nil {
- return nil, err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -175,6 +174,10 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams,
}
}()
+ if err := c.prepare(); err != nil {
+ return nil, err
+ }
+
if c.state.State == ContainerStateStopped {
// Reinitialize the container if we need to
if err := c.reinit(ctx); err != nil {
@@ -685,7 +688,7 @@ func (c *Container) Sync() error {
(c.state.State != ContainerStateConfigured) {
oldState := c.state.State
// TODO: optionally replace this with a stat for the exit file
- if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil {
+ if err := c.runtime.ociRuntime.updateContainerStatus(c, true); err != nil {
return err
}
// Only save back to DB if state changed
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index d928c4aed..d2f48d661 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"fmt"
- "github.com/opencontainers/runc/libcontainer/user"
"io"
"io/ioutil"
"os"
@@ -13,8 +12,10 @@ import (
"strconv"
"strings"
"syscall"
+ "time"
"github.com/containers/buildah/imagebuildah"
+ "github.com/containers/libpod/pkg/ctime"
"github.com/containers/libpod/pkg/hooks"
"github.com/containers/libpod/pkg/hooks/exec"
"github.com/containers/libpod/pkg/lookup"
@@ -25,12 +26,14 @@ import (
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
"github.com/containers/storage/pkg/mount"
+ "github.com/opencontainers/runc/libcontainer/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/text/language"
+ kwait "k8s.io/apimachinery/pkg/util/wait"
)
const (
@@ -147,6 +150,77 @@ func (c *Container) execPidPath(sessionID string) string {
return filepath.Join(c.state.RunDir, "exec_pid_"+sessionID)
}
+// exitFilePath gets the path to the container's exit file
+func (c *Container) exitFilePath() string {
+ return filepath.Join(c.runtime.ociRuntime.exitsDir, c.ID())
+}
+
+// Wait for the container's exit file to appear.
+// When it does, update our state based on it.
+func (c *Container) waitForExitFileAndSync() error {
+ exitFile := c.exitFilePath()
+
+ err := kwait.ExponentialBackoff(
+ kwait.Backoff{
+ Duration: 500 * time.Millisecond,
+ Factor: 1.2,
+ Steps: 6,
+ },
+ func() (bool, error) {
+ _, err := os.Stat(exitFile)
+ if err != nil {
+ // wait longer
+ return false, nil
+ }
+ return true, nil
+ })
+ if err != nil {
+ // Exit file did not appear
+ // Reset our state
+ c.state.ExitCode = -1
+ c.state.FinishedTime = time.Now()
+ c.state.State = ContainerStateStopped
+
+ if err2 := c.save(); err2 != nil {
+ logrus.Errorf("Error saving container %s state: %v", c.ID(), err2)
+ }
+
+ return err
+ }
+
+ if err := c.runtime.ociRuntime.updateContainerStatus(c, false); err != nil {
+ return err
+ }
+
+ return c.save()
+}
+
+// Handle the container exit file.
+// The exit file is used to supply container exit time and exit code.
+// This assumes the exit file already exists.
+func (c *Container) handleExitFile(exitFile string, fi os.FileInfo) error {
+ c.state.FinishedTime = ctime.Created(fi)
+ statusCodeStr, err := ioutil.ReadFile(exitFile)
+ if err != nil {
+ return errors.Wrapf(err, "failed to read exit file for container %s", c.ID())
+ }
+ statusCode, err := strconv.Atoi(string(statusCodeStr))
+ if err != nil {
+ return errors.Wrapf(err, "error converting exit status code (%q) for container %s to int",
+ c.ID(), statusCodeStr)
+ }
+ c.state.ExitCode = int32(statusCode)
+
+ oomFilePath := filepath.Join(c.bundlePath(), "oom")
+ if _, err = os.Stat(oomFilePath); err == nil {
+ c.state.OOMKilled = true
+ }
+
+ c.state.Exited = true
+
+ return nil
+}
+
// Sync this container with on-disk state and runtime status
// Should only be called with container lock held
// This function should suffice to ensure a container's state is accurate and
@@ -162,7 +236,7 @@ func (c *Container) syncContainer() error {
(c.state.State != ContainerStateExited) {
oldState := c.state.State
// TODO: optionally replace this with a stat for the exit file
- if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil {
+ if err := c.runtime.ociRuntime.updateContainerStatus(c, false); err != nil {
return err
}
// Only save back to DB if state changed
@@ -623,9 +697,6 @@ func (c *Container) initAndStart(ctx context.Context) (err error) {
return errors.Wrapf(ErrCtrStateInvalid, "cannot start paused container %s", c.ID())
}
- if err := c.prepare(); err != nil {
- return err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -634,6 +705,10 @@ func (c *Container) initAndStart(ctx context.Context) (err error) {
}
}()
+ if err := c.prepare(); err != nil {
+ return err
+ }
+
// If we are ContainerStateStopped we need to remove from runtime
// And reset to ContainerStateConfigured
if c.state.State == ContainerStateStopped {
@@ -673,13 +748,8 @@ func (c *Container) stop(timeout uint) error {
return err
}
- // Sync the container's state to pick up return code
- if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil {
- return err
- }
-
- // Container should clean itself up
- return nil
+ // Wait until we have an exit file, and sync once we do
+ return c.waitForExitFileAndSync()
}
// Internal, non-locking function to pause a container
@@ -719,9 +789,6 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
return err
}
}
- if err := c.prepare(); err != nil {
- return err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -729,6 +796,9 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
}
}
}()
+ if err := c.prepare(); err != nil {
+ return err
+ }
if c.state.State == ContainerStateStopped {
// Reinitialize the container if we need to
@@ -1069,7 +1139,7 @@ func (c *Container) generatePasswd() (string, error) {
}
originPasswdFile := filepath.Join(c.state.Mountpoint, "/etc/passwd")
orig, err := ioutil.ReadFile(originPasswdFile)
- if err != nil {
+ if err != nil && !os.IsNotExist(err) {
return "", errors.Wrapf(err, "unable to read passwd file %s", originPasswdFile)
}
@@ -1157,6 +1227,10 @@ func (c *Container) generateHosts() (string, error) {
hosts += fmt.Sprintf("%s %s\n", fields[1], fields[0])
}
}
+ if len(c.state.NetworkStatus) > 0 && len(c.state.NetworkStatus[0].IPs) > 0 {
+ ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0]
+ hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname())
+ }
return c.writeStringToRundir("hosts", hosts)
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 7bf2c71ca..163cd75e7 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -360,19 +360,31 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
g.AddMount(tmpfsMnt)
}
- cgroupPath, err := c.CGroupPath()
- if err != nil {
- return err
- }
- sourcePath := filepath.Join("/sys/fs/cgroup/systemd", cgroupPath)
+ // rootless containers have no write access to /sys/fs/cgroup, so don't
+ // add any mount into the container.
+ if !rootless.IsRootless() {
+ cgroupPath, err := c.CGroupPath()
+ if err != nil {
+ return err
+ }
+ sourcePath := filepath.Join("/sys/fs/cgroup/systemd", cgroupPath)
- systemdMnt := spec.Mount{
- Destination: "/sys/fs/cgroup/systemd",
- Type: "bind",
- Source: sourcePath,
- Options: []string{"bind", "private"},
+ systemdMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup/systemd",
+ Type: "bind",
+ Source: sourcePath,
+ Options: []string{"bind", "private"},
+ }
+ g.AddMount(systemdMnt)
+ } else {
+ systemdMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup/systemd",
+ Type: "bind",
+ Source: "/sys/fs/cgroup/systemd",
+ Options: []string{"bind", "nodev", "noexec", "nosuid"},
+ }
+ g.AddMount(systemdMnt)
}
- g.AddMount(systemdMnt)
return nil
}
@@ -484,9 +496,6 @@ func (c *Container) restore(ctx context.Context, keep bool) (err error) {
}
}
- if err := c.prepare(); err != nil {
- return err
- }
defer func() {
if err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
@@ -495,6 +504,10 @@ func (c *Container) restore(ctx context.Context, keep bool) (err error) {
}
}()
+ if err := c.prepare(); err != nil {
+ return err
+ }
+
// TODO: use existing way to request static IPs, once it is merged in ocicni
// https://github.com/cri-o/ocicni/pull/23/
diff --git a/libpod/oci.go b/libpod/oci.go
index ca8f967c4..233bacfbb 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -11,12 +11,10 @@ import (
"os/exec"
"path/filepath"
"runtime"
- "strconv"
"strings"
"syscall"
"time"
- "github.com/containers/libpod/pkg/ctime"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/coreos/go-systemd/activation"
@@ -443,6 +441,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
}
return errors.Wrapf(ErrInternal, "container create failed")
}
+ ctr.state.PID = ss.si.Pid
case <-time.After(ContainerCreateTimeout):
return errors.Wrapf(ErrInternal, "container creation timeout")
}
@@ -451,17 +450,47 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
// updateContainerStatus retrieves the current status of the container from the
// runtime. It updates the container's state but does not save it.
-func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
- state := new(spec.State)
+// If useRunc is false, we will not directly hit runc to see the container's
+// status, but will instead only check for the existence of the conmon exit file
+// and update state to stopped if it exists.
+func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRunc bool) error {
+ exitFile := ctr.exitFilePath()
runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil {
return err
}
+ // If not using runc, we don't need to do most of this.
+ if !useRunc {
+ // If the container's not running, nothing to do.
+ if ctr.state.State != ContainerStateRunning {
+ return nil
+ }
+
+ // Check for the exit file conmon makes
+ info, err := os.Stat(exitFile)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // Container is still running, no error
+ return nil
+ }
+
+ return errors.Wrapf(err, "error running stat on container %s exit file", ctr.ID())
+ }
+
+ // Alright, it exists. Transition to Stopped state.
+ ctr.state.State = ContainerStateStopped
+
+ // Read the exit file to get our stopped time and exit code.
+ return ctr.handleExitFile(exitFile, info)
+ }
+
// Store old state so we know if we were already stopped
oldState := ctr.state.State
+ state := new(spec.State)
+
cmd := exec.Command(r.path, "state", ctr.ID())
cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
outPipe, err := cmd.StdoutPipe()
@@ -480,6 +509,8 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
}
if strings.Contains(string(out), "does not exist") {
ctr.removeConmonFiles()
+ ctr.state.ExitCode = -1
+ ctr.state.FinishedTime = time.Now()
ctr.state.State = ContainerStateExited
return nil
}
@@ -514,7 +545,6 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
// Only grab exit status if we were not already stopped
// If we were, it should already be in the database
if ctr.state.State == ContainerStateStopped && oldState != ContainerStateStopped {
- exitFile := filepath.Join(r.exitsDir, ctr.ID())
var fi os.FileInfo
err = kwait.ExponentialBackoff(
kwait.Backoff{
@@ -538,24 +568,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
return nil
}
- ctr.state.FinishedTime = ctime.Created(fi)
- statusCodeStr, err := ioutil.ReadFile(exitFile)
- if err != nil {
- return errors.Wrapf(err, "failed to read exit file for container %s", ctr.ID())
- }
- statusCode, err := strconv.Atoi(string(statusCodeStr))
- if err != nil {
- return errors.Wrapf(err, "error converting exit status code for container %s to int",
- ctr.ID())
- }
- ctr.state.ExitCode = int32(statusCode)
-
- oomFilePath := filepath.Join(ctr.bundlePath(), "oom")
- if _, err = os.Stat(oomFilePath); err == nil {
- ctr.state.OOMKilled = true
- }
-
- ctr.state.Exited = true
+ return ctr.handleExitFile(exitFile, fi)
}
return nil
@@ -601,6 +614,8 @@ func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error {
// Does not set finished time for container, assumes you will run updateStatus
// after to pull the exit code
func (r *OCIRuntime) stopContainer(ctr *Container, timeout uint) error {
+ logrus.Debugf("Stopping container %s (PID %d)", ctr.ID(), ctr.state.PID)
+
// Ping the container to see if it's alive
// If it's not, it's already stopped, return
err := unix.Kill(ctr.state.PID, 0)
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index b63726f29..09dc7c48b 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -256,7 +256,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool)
}
// Need to update container state to make sure we know it's stopped
- if err := c.syncContainer(); err != nil {
+ if err := c.waitForExitFileAndSync(); err != nil {
return err
}
} else if !(c.state.State == ContainerStateConfigured ||
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index eb3d471dd..3d6fad52f 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -265,15 +265,26 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
}
case CgroupfsCgroupsManager:
// Delete the cgroupfs cgroup
+ // Make sure the conmon cgroup is deleted first
+ // Since the pod is almost gone, don't bother failing
+ // hard - instead, just log errors.
v1CGroups := GetV1CGroups(getExcludedCGroups())
+ conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
+ conmonCgroup, err := cgroups.Load(v1CGroups, cgroups.StaticPath(conmonCgroupPath))
+ if err != nil && err != cgroups.ErrCgroupDeleted {
+ return err
+ }
+ if err == nil {
+ if err := conmonCgroup.Delete(); err != nil {
+ logrus.Errorf("Error deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ }
+ }
cgroup, err := cgroups.Load(v1CGroups, cgroups.StaticPath(p.state.CgroupPath))
if err != nil && err != cgroups.ErrCgroupDeleted {
return err
- } else if err == nil {
+ }
+ if err == nil {
if err := cgroup.Delete(); err != nil {
- // The pod is already almost gone.
- // No point in hard-failing if we fail
- // this bit of cleanup.
logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
}
}
diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go
index b27e2a724..a9d975b4b 100644
--- a/pkg/lookup/lookup.go
+++ b/pkg/lookup/lookup.go
@@ -1,10 +1,12 @@
package lookup
import (
+ "os"
+ "strconv"
+
"github.com/cyphar/filepath-securejoin"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/sirupsen/logrus"
- "strconv"
)
const (
@@ -116,7 +118,7 @@ func GetUser(containerMount, userIDorName string) (*user.User, error) {
}
return u.Uid == uid
})
- if err != nil {
+ if err != nil && !os.IsNotExist(err) {
return nil, err
}
if len(users) > 0 {
@@ -146,7 +148,7 @@ func GetGroup(containerMount, groupIDorName string) (*user.Group, error) {
}
return g.Gid == gid
})
- if err != nil {
+ if err != nil && !os.IsNotExist(err) {
return nil, err
}
if len(groups) > 0 {
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index 24876b6d6..1a2eb1a09 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -250,6 +250,10 @@ var _ = Describe("Podman pause", func() {
running.WaitWithDefaultTimeout()
Expect(running.ExitCode()).To(Equal(0))
Expect(len(running.OutputToStringArray())).To(Equal(0))
+
+ unpause := podmanTest.Podman([]string{"unpause", "--all"})
+ unpause.WaitWithDefaultTimeout()
+ Expect(unpause.ExitCode()).To(Equal(0))
})
It("Unpause a bunch of running containers", func() {
diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go
index c5a02c776..a617035a1 100644
--- a/test/e2e/run_dns_test.go
+++ b/test/e2e/run_dns_test.go
@@ -1,9 +1,9 @@
package integration
import (
+ "fmt"
"os"
- "fmt"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -83,4 +83,11 @@ var _ = Describe("Podman run dns", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("foobar"))
})
+
+ It("podman run add hostname sets /etc/hosts", func() {
+ session := podmanTest.Podman([]string{"run", "-t", "-i", "--hostname=foobar", ALPINE, "cat", "/etc/hosts"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("foobar")).To(BeTrue())
+ })
})