summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--RELEASE_NOTES.md11
-rw-r--r--changelog.txt17
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/create.go2
-rw-r--r--cmd/podman/exec.go30
-rw-r--r--cmd/podman/rm.go3
-rw-r--r--cmd/podman/top.go2
-rw-r--r--docs/podman-exec.1.md4
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/oci.go13
-rw-r--r--pkg/adapter/containers.go23
-rw-r--r--pkg/logs/logs.go5
-rw-r--r--pkg/rootless/rootless_linux.go9
-rw-r--r--test/e2e/stop_test.go28
15 files changed, 136 insertions, 18 deletions
diff --git a/Makefile b/Makefile
index faeeeff07..cb351f917 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= cabfc9b6fb16c5b55d70140182496bbe129f6a4b
+EPOCH_TEST_COMMIT ?= 4b80517b6a638ff06f8ad432f0f0f5839283d058
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 67975730e..65a3f5eea 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,16 @@
# Release Notes
+## 1.1.2
+### Bugfixes
+- Fixed a bug where the `podman image list`, `podman image rm`, and `podman container list` had broken global storage options
+- Fixed a bug where the `--label` option to `podman create` and `podman run` was missing the `-l` alias
+- Fixed a bug where running Podman with the `--config` flag would not set an appropriate default value for `tmp_dir` ([#2408](https://github.com/containers/libpod/issues/2408))
+- Fixed a bug where the `podman logs` command with the `--timestamps` flag produced unreadable output ([#2500](https://github.com/containers/libpod/issues/2500))
+- Fixed a bug where the `podman cp` command would automatically extract `.tar` files copied into the container ([#2509](https://github.com/containers/libpod/issues/2509))
+
+### Misc
+- The `podman container stop` command is now usable with the Podman remote client
+
## 1.1.1
### Bugfixes
- Fixed a bug where `podman container restore` was erroneously available as `podman restore` ([#2191](https://github.com/containers/libpod/issues/2191))
diff --git a/changelog.txt b/changelog.txt
index 9dd0ae2d1..7db579f3a 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,20 @@
+- Changelog for v1.1.2 (2019-03-04)
+ * Fix #2521
+ * Update release notes for v1.1.2
+ * Change timestamp format for podman logs
+ * Don't extract tar file in podman cp
+ * runtime: fill a proper default tmpdir when --config is used
+ * Add additional defense against 0-length log segfaults
+ * When logging with timestamps, append only until newline
+ * Ensure that each log line is newline-terminated
+ * A few more usage-message tweaks
+ * Add missing short flag -l for run/create
+ * Fix aliased commands to actually work
+ * Support podman-remote stop container(s)
+ * Add tests to make sure podman container and podman image commands work
+ * Bump gitvalidation epoch
+ * Bump to v1.2.0-dev
+
- Changelog for v1.1.1 (2019-03-01)
* Update release notes for v1.1.1
* Pull image for runlabel if not local
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 702e20040..ea99aafc2 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -100,6 +100,7 @@ type ExecValues struct {
User string
Latest bool
Workdir string
+ PreserveFDs int
}
type ImageExistsValues struct {
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 95cb732d9..129c886b2 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -869,7 +869,7 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l
}
return false, -1, errors.Errorf("dependency container %s is not running", ctr.ID())
}
- return rootless.JoinNS(uint(pid))
+ return rootless.JoinNS(uint(pid), 0)
}
}
return rootless.BecomeRootInUserNS()
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index 4917fb606..32a6e4bb5 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -4,7 +4,9 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
+ "io/ioutil"
"os"
+ "strconv"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
@@ -47,6 +49,7 @@ func init() {
flags.BoolVarP(&execCommand.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false")
flags.StringVarP(&execCommand.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command")
+ flags.IntVar(&execCommand.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container")
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -82,11 +85,34 @@ func execCmd(c *cliconfig.ExecValues) error {
return errors.Wrapf(err, "unable to exec into %s", args[0])
}
+ if c.PreserveFDs > 0 {
+ entries, err := ioutil.ReadDir("/proc/self/fd")
+ if err != nil {
+ return errors.Wrapf(err, "unable to read /proc/self/fd")
+ }
+ m := make(map[int]bool)
+ for _, e := range entries {
+ i, err := strconv.Atoi(e.Name())
+ if err != nil {
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name())
+ }
+ }
+ m[i] = true
+ }
+ for i := 3; i < 3+c.PreserveFDs; i++ {
+ if _, found := m[i]; !found {
+ return errors.New("invalid --preserve-fds=N specified. Not enough FDs available")
+ }
+ }
+
+ }
+
pid, err := ctr.PID()
if err != nil {
return err
}
- became, ret, err := rootless.JoinNS(uint(pid))
+ became, ret, err := rootless.JoinNS(uint(pid), c.PreserveFDs)
if err != nil {
return err
}
@@ -113,5 +139,5 @@ func execCmd(c *cliconfig.ExecValues) error {
streams.AttachError = true
streams.AttachInput = true
- return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams)
+ return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
}
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 61b049840..d23f8228c 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -80,6 +80,9 @@ func rmCmd(c *cliconfig.RmValues) error {
return err
}
if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ exitCode = 1
+ }
fmt.Println(err.Error())
}
}
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index cdf270fa7..d96402f1a 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -108,7 +108,7 @@ func topCmd(c *cliconfig.TopValues) error {
if err != nil {
return err
}
- became, ret, err := rootless.JoinNS(uint(pid))
+ became, ret, err := rootless.JoinNS(uint(pid), 0)
if err != nil {
return err
}
diff --git a/docs/podman-exec.1.md b/docs/podman-exec.1.md
index 14088b468..b74713b0b 100644
--- a/docs/podman-exec.1.md
+++ b/docs/podman-exec.1.md
@@ -26,6 +26,10 @@ to run containers such as CRI-O, the last started container could be from eithe
The latest option is not supported on the remote client.
+**--preserve-fds=N**
+
+Pass down to the process N additional file descriptors (in addition to 0, 1, 2). The total FDs will be 3+N.
+
**--privileged**
Give the process extended Linux capabilities when running the command in container.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 6bef3c47d..4a76e1434 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -204,7 +204,7 @@ func (c *Container) Kill(signal uint) error {
// Exec starts a new process inside the container
// TODO investigate allowing exec without attaching
-func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams) error {
+func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams, preserveFDs int) error {
var capList []string
locked := false
@@ -266,7 +266,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID)
- execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams)
+ execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams, preserveFDs)
if err != nil {
return errors.Wrapf(err, "error exec %s", c.ID())
}
diff --git a/libpod/oci.go b/libpod/oci.go
index 2b3cc5db5..2cbf25699 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -733,7 +733,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
// TODO: Add --detach support
// TODO: Convert to use conmon
// TODO: add --pid-file and use that to generate exec session tracking
-func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams) (*exec.Cmd, error) {
+func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams, preserveFDs int) (*exec.Cmd, error) {
if len(cmd) == 0 {
return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute")
}
@@ -770,6 +770,9 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
args = append(args, "--user", user)
}
+ if preserveFDs > 0 {
+ args = append(args, fmt.Sprintf("--preserve-fds=%d", preserveFDs))
+ }
if c.config.Spec.Process.NoNewPrivileges {
args = append(args, "--no-new-privs")
}
@@ -806,6 +809,14 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
return nil, errors.Wrapf(err, "cannot start container %s", c.ID())
}
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ // These fds were passed down to the runtime. Close them
+ // and not interfere
+ os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
+ }
+ }
+
return execCmd, nil
}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index b0c75cf49..7514f30d2 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// GetLatestContainer gets the latest Container and wraps it in an adapter Container
@@ -45,9 +46,10 @@ func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) {
// StopContainers stops container(s) based on CLI inputs.
// Returns list of successful id(s), map of failed id(s) + error, or error not from container
func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopValues) ([]string, map[string]error, error) {
- timeout := uint(0)
- if cli.Flags().Changed("timeout") {
- timeout = uint(cli.Timeout)
+ var timeout *uint
+ if cli.Flags().Changed("timeout") || cli.Flags().Changed("time") {
+ t := uint(cli.Timeout)
+ timeout = &t
}
var (
@@ -61,11 +63,18 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
}
for _, c := range ctrs {
- err := c.StopWithTimeout(timeout)
- if err != nil && errors.Cause(err) != libpod.ErrCtrStopped {
- failures[c.ID()] = err
- } else {
+ if timeout == nil {
+ t := c.StopTimeout()
+ timeout = &t
+ logrus.Debugf("Set timeout to container %s default (%d)", c.ID(), *timeout)
+ }
+ if err := c.StopWithTimeout(*timeout); err == nil {
ok = append(ok, c.ID())
+ } else if errors.Cause(err) == libpod.ErrCtrStopped {
+ ok = append(ok, c.ID())
+ logrus.Debugf("Container %s is already stopped", c.ID())
+ } else {
+ failures[c.ID()] = err
}
}
return ok, failures, nil
diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go
index bbd5509b1..7fb5c7ea8 100644
--- a/pkg/logs/logs.go
+++ b/pkg/logs/logs.go
@@ -35,7 +35,10 @@ import (
const (
// timeFormat is the time format used in the log.
- timeFormat = time.RFC3339Nano
+ // It is a modified version of RFC3339Nano that guarantees trailing
+ // zeroes are not trimmed, taken from
+ // https://github.com/golang/go/issues/19635
+ timeFormat = "2006-01-02T15:04:05.000000000Z07:00"
)
// LogStreamType is the type of the stream in CRI container log.
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 98692707f..55fba900e 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -102,7 +102,7 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
// PID.
-func JoinNS(pid uint) (bool, int, error) {
+func JoinNS(pid uint, preserveFDs int) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
@@ -117,6 +117,13 @@ func JoinNS(pid uint) (bool, int, error) {
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
}
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ // These fds were passed down to the runtime. Close them
+ // and not interfere
+ os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
+ }
+ }
ret := C.reexec_in_user_namespace_wait(pidC)
if ret < 0 {
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index eb680d2a1..cd0d804ee 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -82,7 +82,7 @@ var _ = Describe("Podman stop", func() {
Expect(session3.ExitCode()).To(Equal(0))
})
- It("podman stop all containers", func() {
+ It("podman stop all containers -t", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -107,6 +107,32 @@ var _ = Describe("Podman stop", func() {
Expect(output).To(ContainSubstring(cid3))
})
+ It("podman stop container --time", func() {
+ session := podmanTest.RunTopContainer("test4")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid1 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"stop", "--time", "1", "test4"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ output := session.OutputToString()
+ Expect(output).To(ContainSubstring(cid1))
+ })
+
+ It("podman stop container --timeout", func() {
+ session := podmanTest.RunTopContainer("test5")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid1 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"stop", "--timeout", "1", "test5"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ output := session.OutputToString()
+ Expect(output).To(ContainSubstring(cid1))
+ })
+
It("podman stop latest containers", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()