diff options
-rw-r--r-- | .cirrus.yml | 22 | ||||
-rw-r--r-- | cmd/podman/cleanup.go | 39 | ||||
-rw-r--r-- | cmd/podman/commands.go | 3 | ||||
-rw-r--r-- | cmd/podman/container.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers_prune.go | 56 | ||||
-rw-r--r-- | cmd/podman/system.go | 1 | ||||
-rw-r--r-- | cmd/podman/system_prune.go | 5 | ||||
-rw-r--r-- | docs/podman-run.1.md | 60 | ||||
-rw-r--r-- | docs/tutorials/podman_tutorial.md | 2 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 90 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 38 | ||||
-rw-r--r-- | pkg/varlinkapi/attach.go | 14 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 1 | ||||
-rw-r--r-- | test/e2e/prune_test.go | 3 |
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)) |