summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/checkpoint.go22
-rw-r--r--cmd/podman/pull.go9
-rw-r--r--cmd/podman/restore.go23
-rw-r--r--pkg/adapter/containers.go69
-rw-r--r--pkg/adapter/containers_remote.go72
-rw-r--r--pkg/rootless/rootless_linux.c7
-rw-r--r--pkg/rootless/rootless_linux.go14
-rw-r--r--test/e2e/create_test.go11
-rw-r--r--test/e2e/pull_test.go6
9 files changed, 190 insertions, 43 deletions
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go
index dbf72c2cd..5b8d00ff9 100644
--- a/cmd/podman/checkpoint.go
+++ b/cmd/podman/checkpoint.go
@@ -1,13 +1,9 @@
package main
import (
- "context"
- "fmt"
- "os"
-
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -57,7 +53,7 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error {
return errors.New("checkpointing a container requires root")
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@@ -68,17 +64,5 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error {
KeepRunning: c.LeaveRunning,
TCPEstablished: c.TcpEstablished,
}
- containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
-
- for _, ctr := range containers {
- if err = ctr.Checkpoint(context.TODO(), options); err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID())
- } else {
- fmt.Println(ctr.ID())
- }
- }
- return lastError
+ return runtime.Checkpoint(c, options)
}
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 491d3a8c2..7cc7b65b3 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -61,7 +61,12 @@ func init() {
// pullCmd gets the data from the command line and calls pullImage
// to copy an image from a registry to a local machine
-func pullCmd(c *cliconfig.PullValues) error {
+func pullCmd(c *cliconfig.PullValues) (retError error) {
+ defer func() {
+ if retError != nil && exitCode == 0 {
+ exitCode = 1
+ }
+ }()
if c.Bool("trace") {
span, _ := opentracing.StartSpanFromContext(Ctx, "pullCmd")
defer span.Finish()
@@ -163,7 +168,7 @@ func pullCmd(c *cliconfig.PullValues) error {
for _, name := range names {
newImage, err := runtime.New(getContext(), name, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil)
if err != nil {
- println(errors.Wrapf(err, "error pulling image %q", name))
+ logrus.Errorf("error pulling image %q", name)
foundImage = false
continue
}
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index 0f6828432..0f0150644 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -1,13 +1,9 @@
package main
import (
- "context"
- "fmt"
- "os"
-
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -57,7 +53,7 @@ func restoreCmd(c *cliconfig.RestoreValues) error {
return errors.New("restoring a container requires root")
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@@ -67,18 +63,5 @@ func restoreCmd(c *cliconfig.RestoreValues) error {
Keep: c.Keep,
TCPEstablished: c.TcpEstablished,
}
-
- containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed")
-
- for _, ctr := range containers {
- if err = ctr.Restore(context.TODO(), options); err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID())
- } else {
- fmt.Println(ctr.ID())
- }
- }
- return lastError
+ return runtime.Restore(c, options)
}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index d4e8e30d9..931c55a57 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -257,7 +257,10 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
results := shared.NewIntermediateLayer(&c.PodmanCommand, false)
ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime)
- return ctr.ID(), err
+ if err != nil {
+ return "", err
+ }
+ return ctr.ID(), nil
}
// Run a libpod container
@@ -443,3 +446,67 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
}
return nil
}
+
+// Checkpoint one or more containers
+func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
+ var (
+ containers []*libpod.Container
+ err, lastError error
+ )
+
+ if c.All {
+ containers, err = r.Runtime.GetRunningContainers()
+ } else {
+ containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ }
+ if err != nil {
+ return err
+ }
+
+ for _, ctr := range containers {
+ if err = ctr.Checkpoint(context.TODO(), options); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID())
+ } else {
+ fmt.Println(ctr.ID())
+ }
+ }
+ return lastError
+}
+
+// Restore one or more containers
+func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
+ var (
+ containers []*libpod.Container
+ err, lastError error
+ filterFuncs []libpod.ContainerFilter
+ )
+
+ filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
+ state, _ := c.State()
+ return state == libpod.ContainerStateExited
+ })
+
+ if c.All {
+ containers, err = r.GetContainers(filterFuncs...)
+ } else {
+ containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ }
+ if err != nil {
+ return err
+ }
+
+ for _, ctr := range containers {
+ if err = ctr.Restore(context.TODO(), options); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID())
+ } else {
+ fmt.Println(ctr.ID())
+ }
+ }
+ return lastError
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 9ca823760..50cff9fa0 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -537,3 +537,75 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
}
return <-errChan
}
+
+// Checkpoint one or more containers
+func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
+ var lastError error
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ return err
+ }
+ if c.All {
+ // We dont have a great way to get all the running containers, so need to get all and then
+ // check status on them bc checkpoint considers checkpointing a stopped container an error
+ var runningIds []string
+ for _, id := range ids {
+ ctr, err := r.LookupContainer(id)
+ if err != nil {
+ return err
+ }
+ if ctr.state.State == libpod.ContainerStateRunning {
+ runningIds = append(runningIds, id)
+ }
+ }
+ ids = runningIds
+ }
+
+ for _, id := range ids {
+ if _, err := iopodman.ContainerCheckpoint().Call(r.Conn, id, options.Keep, options.KeepRunning, options.TCPEstablished); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to checkpoint container %v", id)
+ } else {
+ fmt.Println(id)
+ }
+ }
+ return lastError
+}
+
+// Restore one or more containers
+func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
+ var lastError error
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ return err
+ }
+ if c.All {
+ // We dont have a great way to get all the exited containers, so need to get all and then
+ // check status on them bc checkpoint considers restoring a running container an error
+ var exitedIDs []string
+ for _, id := range ids {
+ ctr, err := r.LookupContainer(id)
+ if err != nil {
+ return err
+ }
+ if ctr.state.State != libpod.ContainerStateRunning {
+ exitedIDs = append(exitedIDs, id)
+ }
+ }
+ ids = exitedIDs
+ }
+
+ for _, id := range ids {
+ if _, err := iopodman.ContainerRestore().Call(r.Conn, id, options.Keep, options.TCPEstablished); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to restore container %v", id)
+ } else {
+ fmt.Println(id)
+ }
+ }
+ return lastError
+}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 9cb79ed4d..d6a2793a7 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -16,6 +16,8 @@
#include <sys/types.h>
#include <sys/prctl.h>
#include <dirent.h>
+#include <termios.h>
+#include <sys/ioctl.h>
static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
@@ -178,6 +180,11 @@ reexec_userns_join (int userns, int mountns)
_exit (EXIT_FAILURE);
}
+ if (isatty (1) && ioctl (1, TIOCSCTTY, 0) == -1) {
+ fprintf (stderr, "cannot ioctl(TIOCSCTTY): %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+
if (setns (userns, 0) < 0)
{
fprintf (stderr, "cannot setns: %s\n", strerror (errno));
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 1d1b1713d..2c99f41a4 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -28,6 +28,10 @@ extern int reexec_userns_join(int userns, int mountns);
*/
import "C"
+const (
+ numSig = 65 // max number of signals
+)
+
func runInUser() error {
os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done")
return nil
@@ -283,7 +287,15 @@ func BecomeRootInUserNS() (bool, int, error) {
c := make(chan os.Signal, 1)
- gosignal.Notify(c)
+ signals := []os.Signal{}
+ for sig := 0; sig < numSig; sig++ {
+ if sig == int(syscall.SIGTSTP) {
+ continue
+ }
+ signals = append(signals, syscall.Signal(sig))
+ }
+
+ gosignal.Notify(c, signals...)
defer gosignal.Reset()
go func() {
for s := range c {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 6ed5ad2d8..105cba37c 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -70,6 +70,17 @@ var _ = Describe("Podman create", func() {
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
})
+ It("podman create using existing name", func() {
+ session := podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(1))
+
+ session = podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ })
+
It("podman create adds annotation", func() {
session := podmanTest.Podman([]string{"create", "--annotation", "HELLO=WORLD", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index de6d4ea09..4e4e80d56 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -38,6 +38,12 @@ var _ = Describe("Podman pull", func() {
})
+ It("podman pull from docker a not existing image", func() {
+ session := podmanTest.Podman([]string{"pull", "ibetthisdoesntexistthere:foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
It("podman pull from docker with tag", func() {
session := podmanTest.Podman([]string{"pull", "busybox:glibc"})
session.WaitWithDefaultTimeout()