While working on this file, I noticed the `isContainerCreateNameConflict`,
`isUnknownContainer`, and `isStoppedContainer` utilities, which are used
to perform error-type detection through string-matching.
These utilities were added in 534a90a99367af6f6bba1ddcc7eb07506e41f774,
as part of the initial implementation of the Swarm executor in Docker.
At that time, the Docker API client did not return typed errors, and
various part of the code depended on string matching, which is brittle,
and it looks like `isContainerCreateNameConflict` at least is already
broken since c9d0a77657ccc3be144ed4de12d43c8cfcca8590, which changed
the error-message.
Starting with ebcb7d6b406fe50ea9a237c73004d75884184c33, we use typed
errors through the errdefs package, so we can replace these utilities:
The `isUnknownContainer` utility is replace by `errdefs.IsNotFound`,
which is returned if the object is not found. Interestingly, this utility
was checking for containers only (`No such container`), but was also
used for an `removeNetworks` call. Tracking back history of that use to
verify if it was _intentionally_ checking for a "container not found"
error;
- This check added in the initial implementation 534a90a99367af6f6bba1ddcc7eb07506e41f774
- Moved from `controller.Remove` to `container.Shutdown` to make sure the
sandbox was removed in 680d0ba4abfb00c8ac959638c72003dba0826b46
- And finally touched again in 70fa7b6a3fd9aaada582ae02c50710f218b54d1a,
which was a follow-up to the previous one, and fixed the conditions
to prevent returning early before the network was removed.
None of those patches mention that these errors are related to containers,
and checking the codepath that's executed, we can only expect a
`libmetwork.ErrNoSuchNetwork` to be returned, so this looks to have been
a bug.
The `isStoppedContainer` utility is replaced by `errdefs.IsNotModified`,
which is the error (status) returned in situations where the container
is already stopped; https://github.com/moby/moby/blob/caf502a0bc44c19b4e1dde50428de07ff756a8d3/daemon/stop.go#L30-L35
This is the only
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -557,16 +557,3 @@ func (c *containerAdapter) logs(ctx context.Context, options api.LogSubscription |
| 557 | 557 |
} |
| 558 | 558 |
return msgs, nil |
| 559 | 559 |
} |
| 560 |
- |
|
| 561 |
-// todo: typed/wrapped errors |
|
| 562 |
-func isContainerCreateNameConflict(err error) bool {
|
|
| 563 |
- return strings.Contains(err.Error(), "Conflict. The name") |
|
| 564 |
-} |
|
| 565 |
- |
|
| 566 |
-func isUnknownContainer(err error) bool {
|
|
| 567 |
- return strings.Contains(err.Error(), "No such container:") |
|
| 568 |
-} |
|
| 569 |
- |
|
| 570 |
-func isStoppedContainer(err error) bool {
|
|
| 571 |
- return strings.Contains(err.Error(), "is already stopped") |
|
| 572 |
-} |
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
"github.com/docker/docker/api/types/events" |
| 13 | 13 |
executorpkg "github.com/docker/docker/daemon/cluster/executor" |
| 14 |
+ "github.com/docker/docker/errdefs" |
|
| 14 | 15 |
"github.com/docker/docker/libnetwork" |
| 15 | 16 |
"github.com/docker/go-connections/nat" |
| 16 | 17 |
gogotypes "github.com/gogo/protobuf/types" |
| ... | ... |
@@ -65,7 +66,7 @@ func (r *controller) Task() (*api.Task, error) {
|
| 65 | 65 |
func (r *controller) ContainerStatus(ctx context.Context) (*api.ContainerStatus, error) {
|
| 66 | 66 |
ctnr, err := r.adapter.inspect(ctx) |
| 67 | 67 |
if err != nil {
|
| 68 |
- if isUnknownContainer(err) {
|
|
| 68 |
+ if errdefs.IsNotFound(err) {
|
|
| 69 | 69 |
return nil, nil |
| 70 | 70 |
} |
| 71 | 71 |
return nil, err |
| ... | ... |
@@ -76,7 +77,7 @@ func (r *controller) ContainerStatus(ctx context.Context) (*api.ContainerStatus, |
| 76 | 76 |
func (r *controller) PortStatus(ctx context.Context) (*api.PortStatus, error) {
|
| 77 | 77 |
ctnr, err := r.adapter.inspect(ctx) |
| 78 | 78 |
if err != nil {
|
| 79 |
- if isUnknownContainer(err) {
|
|
| 79 |
+ if errdefs.IsNotFound(err) {
|
|
| 80 | 80 |
return nil, nil |
| 81 | 81 |
} |
| 82 | 82 |
|
| ... | ... |
@@ -178,7 +179,7 @@ func (r *controller) Prepare(ctx context.Context) error {
|
| 178 | 178 |
} |
| 179 | 179 |
} |
| 180 | 180 |
if err := r.adapter.create(ctx); err != nil {
|
| 181 |
- if isContainerCreateNameConflict(err) {
|
|
| 181 |
+ if errdefs.IsConflict(err) {
|
|
| 182 | 182 |
if _, err := r.adapter.inspect(ctx); err != nil {
|
| 183 | 183 |
return err |
| 184 | 184 |
} |
| ... | ... |
@@ -379,7 +380,7 @@ func (r *controller) Shutdown(ctx context.Context) error {
|
| 379 | 379 |
} |
| 380 | 380 |
|
| 381 | 381 |
if err := r.adapter.shutdown(ctx); err != nil {
|
| 382 |
- if !(isUnknownContainer(err) || isStoppedContainer(err)) {
|
|
| 382 |
+ if !(errdefs.IsNotFound(err) || errdefs.IsNotModified(err)) {
|
|
| 383 | 383 |
return err |
| 384 | 384 |
} |
| 385 | 385 |
} |
| ... | ... |
@@ -387,7 +388,7 @@ func (r *controller) Shutdown(ctx context.Context) error {
|
| 387 | 387 |
// Try removing networks referenced in this task in case this |
| 388 | 388 |
// task is the last one referencing it |
| 389 | 389 |
if err := r.adapter.removeNetworks(ctx); err != nil {
|
| 390 |
- if !isUnknownContainer(err) {
|
|
| 390 |
+ if !errdefs.IsNotFound(err) {
|
|
| 391 | 391 |
return err |
| 392 | 392 |
} |
| 393 | 393 |
} |
| ... | ... |
@@ -406,7 +407,7 @@ func (r *controller) Terminate(ctx context.Context) error {
|
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 | 408 |
if err := r.adapter.terminate(ctx); err != nil {
|
| 409 |
- if isUnknownContainer(err) {
|
|
| 409 |
+ if errdefs.IsNotFound(err) {
|
|
| 410 | 410 |
return nil |
| 411 | 411 |
} |
| 412 | 412 |
|
| ... | ... |
@@ -428,7 +429,7 @@ func (r *controller) Remove(ctx context.Context) error {
|
| 428 | 428 |
|
| 429 | 429 |
// It may be necessary to shut down the task before removing it. |
| 430 | 430 |
if err := r.Shutdown(ctx); err != nil {
|
| 431 |
- if isUnknownContainer(err) {
|
|
| 431 |
+ if errdefs.IsNotFound(err) {
|
|
| 432 | 432 |
return nil |
| 433 | 433 |
} |
| 434 | 434 |
// This may fail if the task was already shut down. |
| ... | ... |
@@ -436,7 +437,7 @@ func (r *controller) Remove(ctx context.Context) error {
|
| 436 | 436 |
} |
| 437 | 437 |
|
| 438 | 438 |
if err := r.adapter.remove(ctx); err != nil {
|
| 439 |
- if isUnknownContainer(err) {
|
|
| 439 |
+ if errdefs.IsNotFound(err) {
|
|
| 440 | 440 |
return nil |
| 441 | 441 |
} |
| 442 | 442 |
|
| ... | ... |
@@ -459,7 +460,7 @@ func (r *controller) waitReady(pctx context.Context) error {
|
| 459 | 459 |
|
| 460 | 460 |
ctnr, err := r.adapter.inspect(ctx) |
| 461 | 461 |
if err != nil {
|
| 462 |
- if !isUnknownContainer(err) {
|
|
| 462 |
+ if !errdefs.IsNotFound(err) {
|
|
| 463 | 463 |
return errors.Wrap(err, "inspect container failed") |
| 464 | 464 |
} |
| 465 | 465 |
} else {
|