aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml22
-rw-r--r--cmd/podman/cleanup.go39
-rw-r--r--cmd/podman/commands.go3
-rw-r--r--cmd/podman/container.go2
-rw-r--r--cmd/podman/containers_prune.go56
-rw-r--r--cmd/podman/system.go1
-rw-r--r--cmd/podman/system_prune.go5
-rw-r--r--docs/podman-run.1.md60
-rw-r--r--docs/tutorials/podman_tutorial.md2
-rw-r--r--pkg/adapter/containers.go90
-rw-r--r--pkg/adapter/containers_remote.go38
-rw-r--r--pkg/varlinkapi/attach.go14
-rw-r--r--test/e2e/libpod_suite_test.go1
-rw-r--r--test/e2e/prune_test.go3
14 files changed, 213 insertions, 123 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 0102dcb1a..392d7b72d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -137,7 +137,7 @@ gating_task:
- '/usr/local/bin/entrypoint.sh podman-remote-darwin'
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
# This task runs `make vendor` followed by ./hack/tree_status.sh to check
@@ -166,7 +166,7 @@ vendor_task:
- 'cd /go/src/github.com/containers/libpod && ./hack/tree_status.sh'
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
build_each_commit_task:
@@ -193,7 +193,7 @@ build_each_commit_task:
- 'env GOPATH=/var/tmp/go/ make build-all-new-commits GIT_BASE_BRANCH=origin/$CIRRUS_BASE_BRANCH'
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
# Update metadata on VM images referenced by this repository state
@@ -253,9 +253,14 @@ testing_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh'
unit_test_script: '$SCRIPT_BASE/unit_test.sh'
integration_test_script: '$SCRIPT_BASE/integration_test.sh'
+ audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
+ journalctl_b_script: 'journalctl -b'
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ # Job has already failed, don't fail again and miss collecting data
+ failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
+ failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
# This task executes tests under unique environments/conditions
@@ -283,9 +288,14 @@ special_testing_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh'
integration_test_script: '$SCRIPT_BASE/integration_test.sh'
+ audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
+ journalctl_b_script: 'journalctl -b'
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ # Job has already failed, don't fail again and miss collecting data
+ failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
+ failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
# Because system tests are stored within the repository, it is sometimes
@@ -361,7 +371,7 @@ cache_images_task:
# - commit_and_create_upstream_pr.sh
on_failure:
- master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
# Post message to IRC if everything passed
diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go
index 9434c68ba..4ff744ae5 100644
--- a/cmd/podman/cleanup.go
+++ b/cmd/podman/cleanup.go
@@ -1,11 +1,8 @@
package main
import (
- "fmt"
- "os"
-
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -49,38 +46,16 @@ func init() {
}
func cleanupCmd(c *cliconfig.CleanupValues) error {
- runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
- cleanupContainers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
-
- ctx := getContext()
-
- for _, ctr := range cleanupContainers {
- hadError := false
- if c.Remove {
- if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
- hadError = true
- }
- } else {
- if err := ctr.Cleanup(ctx); err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
- hadError = true
- }
- }
- if !hadError {
- fmt.Println(ctr.ID())
- }
+ ok, failures, err := runtime.CleanupContainers(getContext(), c)
+ if err != nil {
+ return err
}
- return lastError
+
+ return printCmdResults(ok, failures)
}
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 36c28696f..4b0641d82 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -46,12 +46,10 @@ func getContainerSubCommands() []*cobra.Command {
_execCommand,
_mountCommand,
_portCommand,
- _pruneContainersCommand,
_refreshCommand,
_restoreCommand,
_runlabelCommand,
_statsCommand,
- _stopCommand,
_umountCommand,
}
}
@@ -74,7 +72,6 @@ func getTrustSubCommands() []*cobra.Command {
// Commands that the local client implements
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{
- _pruneSystemCommand,
_renumberCommand,
_dfSystemCommand,
_migrateCommand,
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index 52152d50e..b3058bf12 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -61,9 +61,11 @@ var (
_logsCommand,
_pauseCommand,
_restartCommand,
+ _pruneContainersCommand,
_runCommand,
_rmCommand,
_startCommand,
+ _stopCommand,
_topCommand,
_unpauseCommand,
_waitCommand,
diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go
index 8270669c9..b052bda36 100644
--- a/cmd/podman/containers_prune.go
+++ b/cmd/podman/containers_prune.go
@@ -1,14 +1,11 @@
package main
import (
- "context"
-
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -41,39 +38,6 @@ func init() {
flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
}
-func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force, volumes bool) error {
- var deleteFuncs []shared.ParallelWorkerInput
-
- filter := func(c *libpod.Container) bool {
- state, err := c.State()
- if state == libpod.ContainerStateStopped || (state == libpod.ContainerStateExited && err == nil && c.PodID() == "") {
- return true
- }
- return false
- }
- delContainers, err := runtime.GetContainers(filter)
- if err != nil {
- return err
- }
- if len(delContainers) < 1 {
- return nil
- }
- for _, container := range delContainers {
- con := container
- f := func() error {
- return runtime.RemoveContainer(ctx, con, force, volumes)
- }
-
- deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
- ContainerID: con.ID(),
- ParallelFunc: f,
- })
- }
- // Run the parallel funcs
- deleteErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, deleteFuncs)
- return printParallelOutput(deleteErrors, errCount)
-}
-
func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
@@ -81,11 +45,23 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
}
defer runtime.Shutdown(false)
- maxWorkers := shared.Parallelize("rm")
+ maxWorkers := shared.DefaultPoolSize("prune")
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks
}
- logrus.Debugf("Setting maximum workers to %d", maxWorkers)
-
- return pruneContainers(runtime, getContext(), maxWorkers, c.Bool("force"), c.Bool("volumes"))
+ ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force)
+ if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ if len(c.InputArgs) > 1 {
+ exitCode = 125
+ } else {
+ exitCode = 1
+ }
+ }
+ return err
+ }
+ if len(failures) > 0 {
+ exitCode = 125
+ }
+ return printCmdResults(ok, failures)
}
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index 528a594de..80080bf44 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -20,6 +20,7 @@ var (
var systemCommands = []*cobra.Command{
_infoCommand,
+ _pruneSystemCommand,
}
func init() {
diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go
index 8a648b603..d5b218cd8 100644
--- a/cmd/podman/system_prune.go
+++ b/cmd/podman/system_prune.go
@@ -81,14 +81,15 @@ Are you sure you want to continue? [y/N] `, volumeString)
rmWorkers := shared.Parallelize("rm")
ctx := getContext()
fmt.Println("Deleted Containers")
- lasterr := pruneContainers(runtime, ctx, rmWorkers, false, false)
+ ok, failures, lasterr := runtime.Prune(ctx, rmWorkers, false)
+ printCmdResults(ok, failures)
fmt.Println("Deleted Pods")
pruneValues := cliconfig.PodPruneValues{
PodmanCommand: c.PodmanCommand,
Force: c.Force,
}
- ok, failures, err := runtime.PrunePods(ctx, &pruneValues)
+ ok, failures, err = runtime.PrunePods(ctx, &pruneValues)
if err != nil {
if lasterr != nil {
logrus.Errorf("%q", lasterr)
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index e54e5e691..4411aca9e 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -415,6 +415,36 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
+**--mount**=*type=TYPE,TYPE-SPECIFIC-OPTION[,...]*
+
+Attach a filesystem mount to the container
+
+Current supported mount TYPES are bind, and tmpfs.
+
+ e.g.
+
+ type=bind,source=/path/on/host,destination=/path/in/container
+
+ type=tmpfs,tmpfs-size=512M,destination=/path/in/container
+
+ Common Options:
+
+ · src, source: mount source spec for bind and volume. Mandatory for bind.
+
+ · dst, destination, target: mount destination spec.
+
+ · ro, read-only: true or false (default).
+
+ Options specific to bind:
+
+ · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+
+ Options specific to tmpfs:
+
+ · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
+
+ · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux.
+
**--name**=""
Assign a name to the container
@@ -711,36 +741,6 @@ Set the UTS mode for the container
**NOTE**: the host mode gives the container access to changing the host's hostname and is therefore considered insecure.
-**--mount**=*type=TYPE,TYPE-SPECIFIC-OPTION[,...]*
-
-Attach a filesystem mount to the container
-
-Current supported mount TYPES are bind, and tmpfs.
-
- e.g.
-
- type=bind,source=/path/on/host,destination=/path/in/container
-
- type=tmpfs,tmpfs-size=512M,destination=/path/in/container
-
- Common Options:
-
- · src, source: mount source spec for bind and volume. Mandatory for bind.
-
- · dst, destination, target: mount destination spec.
-
- · ro, read-only: true or false (default).
-
- Options specific to bind:
-
- · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
-
- Options specific to tmpfs:
-
- · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
-
- · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux.
-
**--userns**=""
Set the user namespace mode for the container. The use of userns is disabled by default.
diff --git a/docs/tutorials/podman_tutorial.md b/docs/tutorials/podman_tutorial.md
index 2abd9c50f..f972853e6 100644
--- a/docs/tutorials/podman_tutorial.md
+++ b/docs/tutorials/podman_tutorial.md
@@ -99,7 +99,7 @@ sudo cp bin/* /usr/libexec/cni
Add a most basic network config
```console
mkdir -p /etc/cni/net.d
-curl -qsSL https://raw.githubusercontent.com/containers/libpod/master/cni/87-podman-bridge.conflist | tee /etc/cni/net.d/99-loopback.conf
+curl -qsSL https://raw.githubusercontent.com/containers/libpod/master/cni/87-podman-bridge.conflist | sudo tee /etc/cni/net.d/99-loopback.conf
```
#### Installing runc
```console
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 9f5fc7e65..9ec897a60 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -786,3 +786,93 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
}
return container.Top(descriptors)
}
+
+// Prune removes stopped containers
+func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ err error
+ )
+
+ logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
+
+ filter := func(c *libpod.Container) bool {
+ state, err := c.State()
+ if err != nil {
+ logrus.Error(err)
+ return false
+ }
+ if c.PodID() != "" {
+ return false
+ }
+ if state == libpod.ContainerStateStopped || state == libpod.ContainerStateExited {
+ return true
+ }
+ return false
+ }
+ delContainers, err := r.Runtime.GetContainers(filter)
+ if err != nil {
+ return ok, failures, err
+ }
+ if len(delContainers) < 1 {
+ return ok, failures, err
+ }
+ pool := shared.NewPool("prune", maxWorkers, len(delContainers))
+ for _, c := range delContainers {
+ ctr := c
+ pool.Add(shared.Job{
+ ID: ctr.ID(),
+ Fn: func() error {
+ err := r.Runtime.RemoveContainer(ctx, ctr, force, false)
+ if err != nil {
+ logrus.Debugf("Failed to prune container %s: %s", ctr.ID(), err.Error())
+ }
+ return err
+ },
+ })
+ }
+ return pool.Run()
+}
+
+// CleanupContainers any leftovers bits of stopped containers
+func (r *LocalRuntime) CleanupContainers(ctx context.Context, cli *cliconfig.CleanupValues) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, ctr := range ctrs {
+ if cli.Remove {
+ err = removeContainer(ctx, ctr, r)
+ } else {
+ err = cleanupContainer(ctx, ctr, r)
+ }
+
+ if err == nil {
+ ok = append(ok, ctr.ID())
+ } else {
+ failures[ctr.ID()] = err
+ }
+ }
+ return ok, failures, nil
+}
+
+func removeContainer(ctx context.Context, ctr *libpod.Container, runtime *LocalRuntime) error {
+ if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil {
+ return errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
+ }
+ return nil
+}
+
+func cleanupContainer(ctx context.Context, ctr *libpod.Container, runtime *LocalRuntime) error {
+ if err := ctr.Cleanup(ctx); err != nil {
+ return errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
+ }
+ return nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index ef6d0efe1..a3a48a564 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -584,7 +584,10 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
}
inputStream := os.Stdin
if c.NoStdin {
- inputStream = nil
+ inputStream, err = os.Open(os.DevNull)
+ if err != nil {
+ return err
+ }
}
errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0], false, c.DetachKeys)
if err != nil {
@@ -852,3 +855,36 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
}
return iopodman.Top().Call(r.Conn, ctr.ID(), descriptors)
}
+
+// Prune removes stopped containers
+func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
+
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ ctrs []*Container
+ err error
+ )
+ logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
+
+ filters := []string{libpod.ContainerStateExited.String()}
+ ctrs, err = r.LookupContainersWithStatus(filters)
+ if err != nil {
+ return ok, failures, err
+ }
+ for _, c := range ctrs {
+ c := c
+ _, err := iopodman.RemoveContainer().Call(r.Conn, c.ID(), false, false)
+ if err != nil {
+ failures[c.ID()] = err
+ } else {
+ ok = append(ok, c.ID())
+ }
+ }
+ return ok, failures, nil
+}
+
+// Cleanup any leftovers bits of stopped containers
+func (r *LocalRuntime) CleanupContainers(ctx context.Context, cli *cliconfig.CleanupValues) ([]string, map[string]error, error) {
+ return nil, nil, errors.New("container cleanup not supported for remote clients")
+}
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index 9e2a265be..6c62d3514 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -53,7 +53,13 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
-
+ state, err := ctr.State()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if !start && state != libpod.ContainerStateRunning {
+ return call.ReplyErrorOccurred("container must be running to attach")
+ }
reader, writer, _, pw, streams := setupStreams(call)
go func() {
@@ -62,10 +68,10 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
}
}()
- if start {
- finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan)
- } else {
+ if state == libpod.ContainerStateRunning {
finalErr = attach(ctr, streams, detachKeys, resize, errChan)
+ } else {
+ finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan)
}
if finalErr != libpod.ErrDetach && finalErr != nil {
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 867844c32..10ca9ac47 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -13,7 +13,6 @@ import (
)
func SkipIfRemote() {
- ginkgo.Skip("This function is not enabled for remote podman")
}
func SkipIfRootless() {
diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go
index 544d54b50..377c9f5e1 100644
--- a/test/e2e/prune_test.go
+++ b/test/e2e/prune_test.go
@@ -39,7 +39,6 @@ var _ = Describe("Podman prune", func() {
})
It("podman container prune containers", func() {
- SkipIfRemote()
top := podmanTest.RunTopContainer("")
top.WaitWithDefaultTimeout()
Expect(top.ExitCode()).To(Equal(0))
@@ -102,8 +101,6 @@ var _ = Describe("Podman prune", func() {
})
It("podman system prune pods", func() {
- SkipIfRemote()
-
session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))