Skip to content

Commit

Permalink
Merge pull request #5782 from baude/v2containercleanup
Browse files Browse the repository at this point in the history
v2podman container cleanup
  • Loading branch information
openshift-merge-robot authored Apr 10, 2020
2 parents 838b5e1 + 7d0e0a7 commit 2a8db9d
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 15 deletions.
75 changes: 75 additions & 0 deletions cmd/podmanV2/containers/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package containers

import (
"fmt"

"github.com/containers/libpod/cmd/podmanV2/parse"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/cmd/podmanV2/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
)

var (
cleanupDescription = `
podman container cleanup
Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits.
`
cleanupCommand = &cobra.Command{
Use: "cleanup [flags] CONTAINER [CONTAINER...]",
Short: "Cleanup network and mountpoints of one or more containers",
Long: cleanupDescription,
RunE: cleanup,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman container cleanup --latest
podman container cleanup ctrID1 ctrID2 ctrID3
podman container cleanup --all`,
}
)

var (
cleanupOptions entities.ContainerCleanupOptions
)

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
Parent: containerCmd,
Command: cleanupCommand,
})
flags := cleanupCommand.Flags()
flags.BoolVarP(&cleanupOptions.All, "all", "a", false, "Cleans up all containers")
flags.BoolVarP(&cleanupOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&cleanupOptions.Remove, "rm", false, "After cleanup, remove the container entirely")
flags.BoolVar(&cleanupOptions.RemoveImage, "rmi", false, "After cleanup, remove the image entirely")

}

func cleanup(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().ContainerCleanup(registry.GetContext(), args, cleanupOptions)
if err != nil {
return err
}
for _, r := range responses {
if r.CleanErr == nil && r.RmErr == nil && r.RmiErr == nil {
fmt.Println(r.Id)
continue
}
if r.RmErr != nil {
errs = append(errs, r.RmErr)
}
if r.RmiErr != nil {
errs = append(errs, r.RmiErr)
}
if r.CleanErr != nil {
errs = append(errs, r.CleanErr)
}
}
return errs.PrintErrors()
}
37 changes: 31 additions & 6 deletions cmd/podmanV2/containers/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import (
"os"
"strings"

"github.com/sirupsen/logrus"

"github.com/containers/libpod/pkg/domain/entities"

"github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podmanV2/common"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -75,6 +74,30 @@ func run(cmd *cobra.Command, args []string) error {
return err
}

ie, err := registry.NewImageEngine(cmd, args)
if err != nil {
return err
}
br, err := ie.Exists(registry.GetContext(), args[0])
if err != nil {
return err
}
pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull)
if err != nil {
return err
}
if !br.Value || pullPolicy == config.PullImageAlways {
if pullPolicy == config.PullImageNever {
return errors.New("unable to find a name and tag match for busybox in repotags: no such image")
}
_, pullErr := ie.Pull(registry.GetContext(), args[0], entities.ImagePullOptions{
Authfile: cliVals.Authfile,
Quiet: cliVals.Quiet,
})
if pullErr != nil {
return pullErr
}
}
// If -i is not set, clear stdin
if !cliVals.Interactive {
runOpts.InputStream = nil
Expand Down Expand Up @@ -110,15 +133,17 @@ func run(cmd *cobra.Command, args []string) error {
runOpts.Spec = s
report, err := registry.ContainerEngine().ContainerRun(registry.GetContext(), runOpts)
// report.ExitCode is set by ContainerRun even it it returns an error
registry.SetExitCode(report.ExitCode)
if report != nil {
registry.SetExitCode(report.ExitCode)
}
if err != nil {
return err
}
if cliVals.Detach {
fmt.Println(report.Id)
}
if runRmi {
_, err := registry.ImageEngine().Delete(registry.GetContext(), []string{report.Id}, entities.ImageDeleteOptions{})
_, err := registry.ImageEngine().Delete(registry.GetContext(), []string{args[0]}, entities.ImageDeleteOptions{})
if err != nil {
logrus.Errorf("%s", errors.Wrapf(err, "failed removing image"))
}
Expand Down
5 changes: 1 addition & 4 deletions cmd/podmanV2/containers/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"time"

"github.com/containers/libpod/cmd/podmanV2/parse"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/cmd/podmanV2/utils"
"github.com/containers/libpod/libpod/define"
Expand All @@ -23,9 +22,7 @@ var (
Long: waitDescription,
RunE: wait,
PersistentPreRunE: preRunE,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Args: registry.IdOrLatestArgs,
Example: `podman wait --latest
podman wait --interval 5000 ctrID
podman wait ctrID1 ctrID2`,
Expand Down
2 changes: 1 addition & 1 deletion pkg/bindings/test/containers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ var _ = Describe("Podman containers ", func() {
_, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
Expect(err).To(BeNil())
containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil)
err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM")
err = containers.Kill(bt.conn, containerLatestList[0].Names(), "SIGTERM")
Expect(err).To(BeNil())
})

Expand Down
2 changes: 1 addition & 1 deletion pkg/domain/entities/container_ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (l ListContainer) State() string {
state = "Up " + t + " ago"
case "configured":
state = "Created"
case "exited":
case "exited", "stopped":
t := units.HumanDuration(time.Since(time.Unix(l.ExitedAt, 0)))
state = fmt.Sprintf("Exited (%d) %s ago", l.ExitCode, t)
default:
Expand Down
18 changes: 18 additions & 0 deletions pkg/domain/entities/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,21 @@ type ContainerRunReport struct {
ExitCode int
Id string
}

// ContainerCleanupOptions are the CLI values for the
// cleanup command
type ContainerCleanupOptions struct {
All bool
Latest bool
Remove bool
RemoveImage bool
}

// ContainerCleanupReport describes the response from a
// container cleanup
type ContainerCleanupReport struct {
CleanErr error
Id string
RmErr error
RmiErr error
}
1 change: 1 addition & 0 deletions pkg/domain/entities/engine_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type ContainerEngine interface {
ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error)
ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error)
ContainerDiff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
Expand Down
37 changes: 37 additions & 0 deletions pkg/domain/infra/abi/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,3 +757,40 @@ func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []strin

return nil
}

func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
var reports []*entities.ContainerCleanupReport
ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, ctr := range ctrs {
var err error
report := entities.ContainerCleanupReport{Id: ctr.ID()}
if options.Remove {
err = ic.Libpod.RemoveContainer(ctx, ctr, false, true)
if err != nil {
report.RmErr = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
}
} else {
err := ctr.Cleanup(ctx)
if err != nil {
report.CleanErr = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
}
}

if options.RemoveImage {
_, imageName := ctr.Image()
ctrImage, err := ic.Libpod.ImageRuntime().NewFromLocal(imageName)
if err != nil {
report.RmiErr = err
reports = append(reports, &report)
continue
}
_, err = ic.Libpod.RemoveImage(ctx, ctrImage, false)
report.RmiErr = err
}
reports = append(reports, &report)
}
return reports, nil
}
8 changes: 5 additions & 3 deletions pkg/domain/infra/abi/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
Expand All @@ -27,10 +28,11 @@ import (
)

func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
if _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId); err != nil {
return &entities.BoolReport{}, nil
_, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
if err != nil && errors.Cause(err) != define.ErrNoSuchImage {
return nil, err
}
return &entities.BoolReport{Value: true}, nil
return &entities.BoolReport{Value: err == nil}, nil
}

func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/domain/infra/tunnel/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,7 @@ func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, _
changes, err := containers.Diff(ic.ClientCxt, nameOrId)
return &entities.DiffReport{Changes: changes}, err
}

func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
return nil, errors.New("not implemented")
}

0 comments on commit 2a8db9d

Please sign in to comment.