1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- package libcontainerd // import "github.com/docker/docker/libcontainerd"
- import (
- "context"
- "github.com/containerd/containerd"
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "github.com/docker/docker/errdefs"
- "github.com/docker/docker/libcontainerd/types"
- )
- // ReplaceContainer creates a new container, replacing any existing container
- // with the same id if necessary.
- func ReplaceContainer(ctx context.Context, client types.Client, id string, spec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) (types.Container, error) {
- newContainer := func() (types.Container, error) {
- return client.NewContainer(ctx, id, spec, shim, runtimeOptions, opts...)
- }
- ctr, err := newContainer()
- if err == nil || !errdefs.IsConflict(err) {
- return ctr, err
- }
- log := logrus.WithContext(ctx).WithField("container", id)
- log.Debug("A container already exists with the same ID. Attempting to clean up the old container.")
- ctr, err = client.LoadContainer(ctx, id)
- if err != nil {
- if errdefs.IsNotFound(err) {
- // Task failed successfully: the container no longer exists,
- // despite us not doing anything. May as well try to create
- // the container again. It might succeed.
- return newContainer()
- }
- return nil, errors.Wrap(err, "could not load stale containerd container object")
- }
- tsk, err := ctr.Task(ctx)
- if err != nil {
- if errdefs.IsNotFound(err) {
- goto deleteContainer
- }
- // There is no point in trying to delete the container if we
- // cannot determine whether or not it has a task. The containerd
- // client would just try to load the task itself, get the same
- // error, and give up.
- return nil, errors.Wrap(err, "could not load stale containerd task object")
- }
- if err := tsk.ForceDelete(ctx); err != nil {
- if !errdefs.IsNotFound(err) {
- return nil, errors.Wrap(err, "could not delete stale containerd task object")
- }
- // The task might have exited on its own. Proceed with
- // attempting to delete the container.
- }
- deleteContainer:
- if err := ctr.Delete(ctx); err != nil && !errdefs.IsNotFound(err) {
- return nil, errors.Wrap(err, "could not delete stale containerd container object")
- }
- return newContainer()
- }
|