mirror of
https://github.com/containers/podman.git
synced 2025-08-06 03:19:52 +08:00
podman container rm: remove pod
Support removing the entire pod when --depend is used on an infra container. --all now implies --depend to properly support removing all containers and not error out when hitting infra containers. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
@ -110,6 +110,11 @@ func rm(cmd *cobra.Command, args []string) error {
|
||||
args = append(args, id)
|
||||
}
|
||||
|
||||
if rmOptions.All {
|
||||
logrus.Debug("--all is set: enforcing --depend=true")
|
||||
rmOptions.Depend = true
|
||||
}
|
||||
|
||||
return removeContainers(args, rmOptions, true)
|
||||
}
|
||||
|
||||
|
@ -915,9 +915,30 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol
|
||||
return id, cleanupErr
|
||||
}
|
||||
|
||||
// RemoveDepend removes all dependencies for a container
|
||||
// RemoveDepend removes all dependencies for a container.
|
||||
// If the container is an infra container, the entire pod gets removed.
|
||||
func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool, removeVolume bool, timeout *uint) ([]*reports.RmReport, error) {
|
||||
logrus.Debugf("Removing container %s and all dependent containers", rmCtr.ID())
|
||||
rmReports := make([]*reports.RmReport, 0)
|
||||
if rmCtr.IsInfra() {
|
||||
pod, err := r.GetPod(rmCtr.PodID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("Removing pod %s: depends on infra container %s", pod.ID(), rmCtr.ID())
|
||||
podContainerIDS, err := pod.AllContainersByID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.RemovePod(ctx, pod, true, force, timeout); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, cID := range podContainerIDS {
|
||||
rmReports = append(rmReports, &reports.RmReport{Id: cID})
|
||||
}
|
||||
return rmReports, nil
|
||||
}
|
||||
|
||||
deps, err := r.state.ContainerInUse(rmCtr)
|
||||
if err != nil {
|
||||
if err == define.ErrCtrRemoved {
|
||||
@ -940,9 +961,9 @@ func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool
|
||||
}
|
||||
rmReports = append(rmReports, reports...)
|
||||
}
|
||||
|
||||
report := reports.RmReport{Id: rmCtr.ID()}
|
||||
report.Err = r.removeContainer(ctx, rmCtr, force, removeVolume, false, timeout)
|
||||
|
||||
return append(rmReports, &report), nil
|
||||
}
|
||||
|
||||
|
@ -357,24 +357,56 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||
return rmReports, nil
|
||||
}
|
||||
|
||||
alreadyRemoved := make(map[string]bool)
|
||||
addReports := func(newReports []*reports.RmReport) {
|
||||
for i := range newReports {
|
||||
alreadyRemoved[newReports[i].Id] = true
|
||||
rmReports = append(rmReports, newReports[i])
|
||||
}
|
||||
}
|
||||
if !options.All && options.Depend {
|
||||
// Add additional containers based on dependencies to container map
|
||||
for _, ctr := range ctrs {
|
||||
if alreadyRemoved[ctr.ID()] {
|
||||
continue
|
||||
}
|
||||
reports, err := ic.Libpod.RemoveDepend(ctx, ctr, options.Force, options.Volumes, options.Timeout)
|
||||
if err != nil {
|
||||
return rmReports, err
|
||||
}
|
||||
rmReports = append(rmReports, reports...)
|
||||
addReports(reports)
|
||||
}
|
||||
return rmReports, nil
|
||||
}
|
||||
|
||||
// If --all is set, make sure to remove the infra containers'
|
||||
// dependencies before doing the parallel removal below.
|
||||
if options.All {
|
||||
for _, ctr := range ctrs {
|
||||
if alreadyRemoved[ctr.ID()] || !ctr.IsInfra() {
|
||||
continue
|
||||
}
|
||||
reports, err := ic.Libpod.RemoveDepend(ctx, ctr, options.Force, options.Volumes, options.Timeout)
|
||||
if err != nil {
|
||||
return rmReports, err
|
||||
}
|
||||
addReports(reports)
|
||||
}
|
||||
}
|
||||
|
||||
errMap, err := parallelctr.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
|
||||
if alreadyRemoved[c.ID()] {
|
||||
return nil
|
||||
}
|
||||
return ic.removeContainer(ctx, c, options)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for ctr, err := range errMap {
|
||||
if alreadyRemoved[ctr.ID()] {
|
||||
continue
|
||||
}
|
||||
report := new(reports.RmReport)
|
||||
report.Id = ctr.ID()
|
||||
report.Err = err
|
||||
|
@ -188,35 +188,53 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||
if opts.Timeout != nil {
|
||||
options = options.WithTimeout(*opts.Timeout)
|
||||
}
|
||||
|
||||
toRemove := []string{}
|
||||
alreadyRemoved := make(map[string]bool) // Avoids trying to remove already removed containers
|
||||
if opts.All {
|
||||
ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, opts.Ignore, namesOrIds)
|
||||
ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, opts.Ignore, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rmReports := make([]*reports.RmReport, 0, len(ctrs))
|
||||
for _, c := range ctrs {
|
||||
report, err := containers.Remove(ic.ClientCtx, c.ID, options)
|
||||
if err != nil {
|
||||
return rmReports, err
|
||||
}
|
||||
rmReports = append(rmReports, report...)
|
||||
toRemove = append(toRemove, c.ID)
|
||||
}
|
||||
} else {
|
||||
for _, ctr := range namesOrIds {
|
||||
// NOTE that we set ignore=true here to support
|
||||
// removing external containers (e.g., Buildah
|
||||
// containers). If we don't find the container,
|
||||
// we'll use the raw input provided by the user
|
||||
// instead of the ID. Since this can only happen
|
||||
// with external containers, it poses no threat
|
||||
// to the `alreadyRemoved` checks below.
|
||||
ctrs, err := getContainersByContext(ic.ClientCtx, false, true, []string{ctr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id := ctr
|
||||
if len(ctrs) == 1 {
|
||||
id = ctrs[0].ID
|
||||
}
|
||||
toRemove = append(toRemove, id)
|
||||
}
|
||||
return rmReports, nil
|
||||
}
|
||||
|
||||
rmReports := make([]*reports.RmReport, 0, len(namesOrIds))
|
||||
for _, name := range namesOrIds {
|
||||
report, err := containers.Remove(ic.ClientCtx, name, options)
|
||||
if err != nil {
|
||||
rmReports = append(rmReports, &reports.RmReport{
|
||||
Id: name,
|
||||
Err: err,
|
||||
})
|
||||
rmReports := make([]*reports.RmReport, 0, len(toRemove))
|
||||
for _, nameOrID := range toRemove {
|
||||
if alreadyRemoved[nameOrID] {
|
||||
continue
|
||||
}
|
||||
rmReports = append(rmReports, report...)
|
||||
newReports, err := containers.Remove(ic.ClientCtx, nameOrID, options)
|
||||
if err != nil {
|
||||
rmReports = append(rmReports, &reports.RmReport{Id: nameOrID, Err: err})
|
||||
continue
|
||||
}
|
||||
for i := range newReports {
|
||||
alreadyRemoved[newReports[i].Id] = true
|
||||
rmReports = append(rmReports, newReports[i])
|
||||
}
|
||||
}
|
||||
|
||||
return rmReports, nil
|
||||
}
|
||||
|
||||
|
@ -362,4 +362,38 @@ EOF
|
||||
run_podman run --rm --pod "new:$pod_name" $IMAGE hostname
|
||||
is "$output" "$pod_name" "new:POD should have hostname name set to podname"
|
||||
}
|
||||
|
||||
@test "podman rm --force to remove infra container" {
|
||||
local pod_name="$(random_string 10 | tr A-Z a-z)"
|
||||
run_podman create --pod "new:$pod_name" $IMAGE
|
||||
container_ID="$output"
|
||||
run_podman pod inspect --format "{{.InfraContainerID}}" $pod_name
|
||||
infra_ID="$output"
|
||||
|
||||
run_podman 125 container rm $infra_ID
|
||||
is "$output" ".* and cannot be removed without removing the pod"
|
||||
run_podman 125 container rm --force $infra_ID
|
||||
is "$output" ".* and cannot be removed without removing the pod"
|
||||
|
||||
run_podman container rm --depend $infra_ID
|
||||
is "$output" ".*$infra_ID.*"
|
||||
is "$output" ".*$container_ID.*"
|
||||
|
||||
# Now make sure that --force --all works as well
|
||||
run_podman create --pod "new:$pod_name" $IMAGE
|
||||
container_1_ID="$output"
|
||||
run_podman create --pod "$pod_name" $IMAGE
|
||||
container_2_ID="$output"
|
||||
run_podman create $IMAGE
|
||||
container_3_ID="$output"
|
||||
run_podman pod inspect --format "{{.InfraContainerID}}" $pod_name
|
||||
infra_ID="$output"
|
||||
|
||||
run_podman container rm --force --all $infraID
|
||||
is "$output" ".*$infra_ID.*"
|
||||
is "$output" ".*$container_1_ID.*"
|
||||
is "$output" ".*$container_2_ID.*"
|
||||
is "$output" ".*$container_3_ID.*"
|
||||
}
|
||||
|
||||
# vim: filetype=sh
|
||||
|
Reference in New Issue
Block a user