mirror of https://github.com/containers/podman.git
The removeContainer function now accepts a struct
We had something like 6 different boolean options (removing a container turns out to be rather complicated, because there are a million-odd things that want to do it), and the function signature was getting unreasonably large. Change to a struct to clean things up. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
parent
4e6efbbbb3
commit
2c9f18182a
|
@ -359,7 +359,13 @@ func removeNode(ctx context.Context, node *containerNode, pod *Pod, force bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctrErrored {
|
if !ctrErrored {
|
||||||
if _, _, err := node.container.runtime.removeContainer(ctx, node.container, force, false, true, false, false, false, timeout); err != nil {
|
opts := ctrRmOpts{
|
||||||
|
Force: force,
|
||||||
|
RemovePod: true,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, _, err := node.container.runtime.removeContainer(ctx, node.container, opts); err != nil {
|
||||||
ctrErrored = true
|
ctrErrored = true
|
||||||
ctrErrors[node.id] = err
|
ctrErrors[node.id] = err
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,12 @@ func (p *Pod) startInitContainers(ctx context.Context) error {
|
||||||
icLock := initCon.lock
|
icLock := initCon.lock
|
||||||
icLock.Lock()
|
icLock.Lock()
|
||||||
var time *uint
|
var time *uint
|
||||||
if _, _, err := p.runtime.removeContainer(ctx, initCon, false, false, true, false, false, false, time); err != nil {
|
opts := ctrRmOpts{
|
||||||
|
RemovePod: true,
|
||||||
|
Timeout: time,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, _, err := p.runtime.removeContainer(ctx, initCon, opts); err != nil {
|
||||||
icLock.Unlock()
|
icLock.Unlock()
|
||||||
return fmt.Errorf("failed to remove once init container %s: %w", initCon.ID(), err)
|
return fmt.Errorf("failed to remove once init container %s: %w", initCon.ID(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,9 +607,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
||||||
// container will be removed also (iff the container is the sole user of the
|
// container will be removed also (iff the container is the sole user of the
|
||||||
// volumes). Timeout sets the stop timeout for the container if it is running.
|
// volumes). Timeout sets the stop timeout for the container if it is running.
|
||||||
func (r *Runtime) RemoveContainer(ctx context.Context, c *Container, force bool, removeVolume bool, timeout *uint) error {
|
func (r *Runtime) RemoveContainer(ctx context.Context, c *Container, force bool, removeVolume bool, timeout *uint) error {
|
||||||
|
opts := ctrRmOpts{
|
||||||
|
Force: force,
|
||||||
|
RemoveVolume: removeVolume,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: container will be locked down the road. There is no unlocked
|
// NOTE: container will be locked down the road. There is no unlocked
|
||||||
// version of removeContainer.
|
// version of removeContainer.
|
||||||
_, _, err := r.removeContainer(ctx, c, force, removeVolume, false, false, false, false, timeout)
|
_, _, err := r.removeContainer(ctx, c, opts)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,9 +627,40 @@ func (r *Runtime) RemoveContainer(ctx context.Context, c *Container, force bool,
|
||||||
// always returned, even if error is set, and indicate any containers that were
|
// always returned, even if error is set, and indicate any containers that were
|
||||||
// successfully removed prior to the error.
|
// successfully removed prior to the error.
|
||||||
func (r *Runtime) RemoveContainerAndDependencies(ctx context.Context, c *Container, force bool, removeVolume bool, timeout *uint) (map[string]error, map[string]error, error) {
|
func (r *Runtime) RemoveContainerAndDependencies(ctx context.Context, c *Container, force bool, removeVolume bool, timeout *uint) (map[string]error, map[string]error, error) {
|
||||||
|
opts := ctrRmOpts{
|
||||||
|
Force: force,
|
||||||
|
RemoveVolume: removeVolume,
|
||||||
|
RemoveDeps: true,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: container will be locked down the road. There is no unlocked
|
// NOTE: container will be locked down the road. There is no unlocked
|
||||||
// version of removeContainer.
|
// version of removeContainer.
|
||||||
return r.removeContainer(ctx, c, force, removeVolume, false, false, true, false, timeout)
|
return r.removeContainer(ctx, c, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options for removeContainer
|
||||||
|
type ctrRmOpts struct {
|
||||||
|
// Whether to stop running container(s)
|
||||||
|
Force bool
|
||||||
|
// Whether to remove anonymous volumes used by removing the container
|
||||||
|
RemoveVolume bool
|
||||||
|
// Only set by `removePod` as `removeContainer` is being called as part
|
||||||
|
// of removing a whole pod.
|
||||||
|
RemovePod bool
|
||||||
|
// Whether to ignore dependencies of the container when removing
|
||||||
|
// (This is *DANGEROUS* and should not be used outside of non-graph
|
||||||
|
// traversal pod removal code).
|
||||||
|
IgnoreDeps bool
|
||||||
|
// Remove all the dependencies associated with the container. Can cause
|
||||||
|
// multiple containers, and possibly one or more pods, to be removed.
|
||||||
|
RemoveDeps bool
|
||||||
|
// Do not lock the pod that the container is part of (used only by
|
||||||
|
// recursive calls of removeContainer, used when removing dependencies)
|
||||||
|
NoLockPod bool
|
||||||
|
// Timeout to use when stopping the container. Only used if `Force` is
|
||||||
|
// true.
|
||||||
|
Timeout *uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal function to remove a container.
|
// Internal function to remove a container.
|
||||||
|
@ -639,7 +676,7 @@ func (r *Runtime) RemoveContainerAndDependencies(ctx context.Context, c *Contain
|
||||||
// noLockPod is used for recursive removeContainer calls when the pod is already
|
// noLockPod is used for recursive removeContainer calls when the pod is already
|
||||||
// locked.
|
// locked.
|
||||||
// TODO: At this point we should just start accepting an options struct
|
// TODO: At this point we should just start accepting an options struct
|
||||||
func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, removeVolume, removePod, ignoreDeps, removeDeps, noLockPod bool, timeout *uint) (removedCtrs map[string]error, removedPods map[string]error, retErr error) {
|
func (r *Runtime) removeContainer(ctx context.Context, c *Container, opts ctrRmOpts) (removedCtrs map[string]error, removedPods map[string]error, retErr error) {
|
||||||
removedCtrs = make(map[string]error)
|
removedCtrs = make(map[string]error)
|
||||||
removedPods = make(map[string]error)
|
removedPods = make(map[string]error)
|
||||||
|
|
||||||
|
@ -652,7 +689,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if removePod && removeDeps {
|
if opts.RemovePod && opts.RemoveDeps {
|
||||||
retErr = fmt.Errorf("cannot remove dependencies while also removing a pod: %w", define.ErrInvalidArg)
|
retErr = fmt.Errorf("cannot remove dependencies while also removing a pod: %w", define.ErrInvalidArg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -685,13 +722,13 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !removePod {
|
if !opts.RemovePod {
|
||||||
// Lock the pod while we're removing container
|
// Lock the pod while we're removing container
|
||||||
if pod.config.LockID == c.config.LockID {
|
if pod.config.LockID == c.config.LockID {
|
||||||
retErr = fmt.Errorf("container %s and pod %s share lock ID %d: %w", c.ID(), pod.ID(), c.config.LockID, define.ErrWillDeadlock)
|
retErr = fmt.Errorf("container %s and pod %s share lock ID %d: %w", c.ID(), pod.ID(), c.config.LockID, define.ErrWillDeadlock)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !noLockPod {
|
if !opts.NoLockPod {
|
||||||
pod.lock.Lock()
|
pod.lock.Lock()
|
||||||
defer pod.lock.Unlock()
|
defer pod.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
@ -701,7 +738,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
}
|
}
|
||||||
|
|
||||||
infraID := pod.state.InfraContainerID
|
infraID := pod.state.InfraContainerID
|
||||||
if c.ID() == infraID && !removeDeps {
|
if c.ID() == infraID && !opts.RemoveDeps {
|
||||||
retErr = fmt.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID())
|
retErr = fmt.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -710,7 +747,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
|
|
||||||
// For pod removal, the container is already locked by the caller
|
// For pod removal, the container is already locked by the caller
|
||||||
locked := false
|
locked := false
|
||||||
if !removePod {
|
if !opts.RemovePod {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer func() {
|
defer func() {
|
||||||
if locked {
|
if locked {
|
||||||
|
@ -742,7 +779,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
retErr = err
|
retErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !removeDeps {
|
if !opts.RemoveDeps {
|
||||||
retErr = fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ","))
|
retErr = fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ","))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -754,7 +791,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logrus.Infof("Removing pod %s as container %s is its service container", depPod.ID(), c.ID())
|
logrus.Infof("Removing pod %s as container %s is its service container", depPod.ID(), c.ID())
|
||||||
podRemovedCtrs, err := r.RemovePod(ctx, depPod, true, force, timeout)
|
podRemovedCtrs, err := r.RemovePod(ctx, depPod, true, opts.Force, opts.Timeout)
|
||||||
for ctr, err := range podRemovedCtrs {
|
for ctr, err := range podRemovedCtrs {
|
||||||
removedCtrs[ctr] = err
|
removedCtrs[ctr] = err
|
||||||
}
|
}
|
||||||
|
@ -766,7 +803,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
removedPods[depPod.ID()] = nil
|
removedPods[depPod.ID()] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (serviceForPod || c.config.IsInfra) && !removePod {
|
if (serviceForPod || c.config.IsInfra) && !opts.RemovePod {
|
||||||
// We're going to remove the pod we are a part of.
|
// We're going to remove the pod we are a part of.
|
||||||
// This will get rid of us as well, so we can just return
|
// This will get rid of us as well, so we can just return
|
||||||
// immediately after.
|
// immediately after.
|
||||||
|
@ -776,7 +813,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Infof("Removing pod %s (dependency of container %s)", pod.ID(), c.ID())
|
logrus.Infof("Removing pod %s (dependency of container %s)", pod.ID(), c.ID())
|
||||||
podRemovedCtrs, err := r.removePod(ctx, pod, true, force, timeout)
|
podRemovedCtrs, err := r.removePod(ctx, pod, true, opts.Force, opts.Timeout)
|
||||||
for ctr, err := range podRemovedCtrs {
|
for ctr, err := range podRemovedCtrs {
|
||||||
removedCtrs[ctr] = err
|
removedCtrs[ctr] = err
|
||||||
}
|
}
|
||||||
|
@ -791,7 +828,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
|
|
||||||
// If we're not force-removing, we need to check if we're in a good
|
// If we're not force-removing, we need to check if we're in a good
|
||||||
// state to remove.
|
// state to remove.
|
||||||
if !force {
|
if !opts.Force {
|
||||||
if err := c.checkReadyForRemoval(); err != nil {
|
if err := c.checkReadyForRemoval(); err != nil {
|
||||||
retErr = err
|
retErr = err
|
||||||
return
|
return
|
||||||
|
@ -825,13 +862,13 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
// Check that no other containers depend on the container.
|
// Check that no other containers depend on the container.
|
||||||
// Only used if not removing a pod - pods guarantee that all
|
// Only used if not removing a pod - pods guarantee that all
|
||||||
// deps will be evicted at the same time.
|
// deps will be evicted at the same time.
|
||||||
if !ignoreDeps {
|
if !opts.IgnoreDeps {
|
||||||
deps, err := r.state.ContainerInUse(c)
|
deps, err := r.state.ContainerInUse(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
retErr = err
|
retErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !removeDeps {
|
if !opts.RemoveDeps {
|
||||||
if len(deps) != 0 {
|
if len(deps) != 0 {
|
||||||
depsStr := strings.Join(deps, ", ")
|
depsStr := strings.Join(deps, ", ")
|
||||||
retErr = fmt.Errorf("container %s has dependent containers which must be removed before it: %s: %w", c.ID(), depsStr, define.ErrCtrExists)
|
retErr = fmt.Errorf("container %s has dependent containers which must be removed before it: %s: %w", c.ID(), depsStr, define.ErrCtrExists)
|
||||||
|
@ -845,7 +882,14 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logrus.Infof("Removing container %s (dependency of container %s)", dep.ID(), c.ID())
|
logrus.Infof("Removing container %s (dependency of container %s)", dep.ID(), c.ID())
|
||||||
ctrs, pods, err := r.removeContainer(ctx, dep, force, removeVolume, false, false, true, true, timeout)
|
recursiveOpts := ctrRmOpts{
|
||||||
|
Force: opts.Force,
|
||||||
|
RemoveVolume: opts.RemoveVolume,
|
||||||
|
RemoveDeps: true,
|
||||||
|
NoLockPod: true,
|
||||||
|
Timeout: opts.Timeout,
|
||||||
|
}
|
||||||
|
ctrs, pods, err := r.removeContainer(ctx, dep, recursiveOpts)
|
||||||
for rmCtr, err := range ctrs {
|
for rmCtr, err := range ctrs {
|
||||||
removedCtrs[rmCtr] = err
|
removedCtrs[rmCtr] = err
|
||||||
}
|
}
|
||||||
|
@ -862,8 +906,8 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
// Check that the container's in a good state to be removed.
|
// Check that the container's in a good state to be removed.
|
||||||
if c.ensureState(define.ContainerStateRunning, define.ContainerStateStopping) {
|
if c.ensureState(define.ContainerStateRunning, define.ContainerStateStopping) {
|
||||||
time := c.StopTimeout()
|
time := c.StopTimeout()
|
||||||
if timeout != nil {
|
if opts.Timeout != nil {
|
||||||
time = *timeout
|
time = *opts.Timeout
|
||||||
}
|
}
|
||||||
// Ignore ErrConmonDead - we couldn't retrieve the container's
|
// Ignore ErrConmonDead - we couldn't retrieve the container's
|
||||||
// exit code properly, but it's still stopped.
|
// exit code properly, but it's still stopped.
|
||||||
|
@ -958,7 +1002,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
|
|
||||||
c.newContainerEvent(events.Remove)
|
c.newContainerEvent(events.Remove)
|
||||||
|
|
||||||
if !removeVolume {
|
if !opts.RemoveVolume {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,7 +1011,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
|
||||||
if !volume.Anonymous() {
|
if !volume.Anonymous() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := runtime.removeVolume(ctx, volume, false, timeout, false); err != nil && !errors.Is(err, define.ErrNoSuchVolume) {
|
if err := runtime.removeVolume(ctx, volume, false, opts.Timeout, false); err != nil && !errors.Is(err, define.ErrNoSuchVolume) {
|
||||||
if errors.Is(err, define.ErrVolumeBeingUsed) {
|
if errors.Is(err, define.ErrVolumeBeingUsed) {
|
||||||
// Ignore error, since podman will report original error
|
// Ignore error, since podman will report original error
|
||||||
volumesFrom, _ := c.volumesFrom()
|
volumesFrom, _ := c.volumesFrom()
|
||||||
|
@ -1021,7 +1065,12 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Infof("Container %s successfully retrieved from state, attempting normal removal", id)
|
logrus.Infof("Container %s successfully retrieved from state, attempting normal removal", id)
|
||||||
// Assume force = true for the evict case
|
// Assume force = true for the evict case
|
||||||
_, _, err = r.removeContainer(ctx, tmpCtr, true, removeVolume, false, false, false, false, timeout)
|
opts := ctrRmOpts{
|
||||||
|
Force: true,
|
||||||
|
RemoveVolume: removeVolume,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
_, _, err = r.removeContainer(ctx, tmpCtr, opts)
|
||||||
if !tmpCtr.valid {
|
if !tmpCtr.valid {
|
||||||
// If the container is marked invalid, remove succeeded
|
// If the container is marked invalid, remove succeeded
|
||||||
// in kicking it out of the state - no need to continue.
|
// in kicking it out of the state - no need to continue.
|
||||||
|
|
|
@ -46,7 +46,11 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage
|
||||||
return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err)
|
return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if _, _, err := r.removeContainer(ctx, ctr, true, false, false, false, false, false, timeout); err != nil {
|
opts := ctrRmOpts{
|
||||||
|
Force: true,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
if _, _, err := r.removeContainer(ctx, ctr, opts); err != nil {
|
||||||
return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err)
|
return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,13 @@ func (r *Runtime) removeMalformedPod(ctx context.Context, p *Pod, ctrs []*Contai
|
||||||
ctrNamedVolumes[vol.Name] = vol
|
ctrNamedVolumes[vol.Name] = vol
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err := r.removeContainer(ctx, ctr, force, false, true, true, false, false, timeout)
|
opts := ctrRmOpts{
|
||||||
|
Force: force,
|
||||||
|
RemovePod: true,
|
||||||
|
IgnoreDeps: true,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
_, _, err := r.removeContainer(ctx, ctr, opts)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
removedCtrs[ctr.ID()] = err
|
removedCtrs[ctr.ID()] = err
|
||||||
|
|
|
@ -388,7 +388,11 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo
|
||||||
|
|
||||||
logrus.Debugf("Removing container %s (depends on volume %q)", ctr.ID(), v.Name())
|
logrus.Debugf("Removing container %s (depends on volume %q)", ctr.ID(), v.Name())
|
||||||
|
|
||||||
if _, _, err := r.removeContainer(ctx, ctr, force, false, false, false, false, false, timeout); err != nil {
|
opts := ctrRmOpts{
|
||||||
|
Force: force,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
if _, _, err := r.removeContainer(ctx, ctr, opts); err != nil {
|
||||||
return fmt.Errorf("removing container %s that depends on volume %s: %w", ctr.ID(), v.Name(), err)
|
return fmt.Errorf("removing container %s that depends on volume %s: %w", ctr.ID(), v.Name(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue