Before this patch, an API response that's valid JSON, but not the right
schema would be silently discarded by the CLI. For example, due to a bug
in Docker Desktop's API proxy, the "normal" (not JSON error) response
would be returned together with a non-200 status code when using an
unsupported API version;
curl -s -w 'STATUS: %{http_code}\n' --unix-socket /var/run/docker.sock 'http://localhost/v1.99/version'
{"Platform":{"Name":"Docker Desktop 4.38.0 (181016)"},"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}
STATUS: 400
Before this patch, this resulted in no output being shown;
DOCKER_API_VERSION=1.99 docker version
Client:
Version: 27.5.1
API version: 1.99 (downgraded from 1.47)
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:37:19 2025
OS/Arch: darwin/arm64
Context: desktop-linux
Error response from daemon:
With this patch, an error is generated based on the status:
DOCKER_API_VERSION=1.99 docker version
Client:
Version: 27.5.1
API version: 1.99 (downgraded from 1.47)
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:37:19 2025
OS/Arch: darwin/arm64
Context: desktop-linux
Error response from daemon: API returned a 400 (Bad Request) but provided no error-message
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
We don't enable STP on bridges belonging to bridge networks,
but bridge ports still need to transition from "disabled" to
"forwarding", after the veth device comes "up". Until then,
the bridge will just drop packets.
So, if a container's network is a veth device, and its other
end is slaved to a bridge - wait for the bridge port to
be "forwarding".
Signed-off-by: Rob Murray <rob.murray@docker.com>
Make it more clear that this loop is for legacy-links, and the timer is
only needed for that purpose.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When failing to resolve the network container, a "not found" error should
not return a 404, but either a "invalid parameter" (400) or "system" (500)
error.
Given that this function is called on container start, not container create,
a 500 (internal server error) is more appropriate, because the API request
(start the container) is valid, but the state of the container isn't.
While working on this, I discovered that no validation happens during container
create; TODO's were added to look into that, but this may be partially
by design (allow a container to be created before the "donor" network
container is created).
Before this patch:
docker container create --name hello --network=container:nosuchcontainer alpine
docker container start hello
Error response from daemon: No such container: nosuchcontainer
Error: failed to start containers: hello
# daemon logs:
DEBU[2025-01-30T11:32:33.595636043Z] error response for POST request error-response="No such container: nosuchcontainer" method=POST module=api request-url=/v1.47/containers/hello/start status=404 vars="map[name:hello version:1.47]"
docker container create --name hello2 --network=container:hello2 alpine
docker container start hello2
Error response from daemon: cannot join own network
Error: failed to start containers: hello2
# daemon logs:
DEBU[2025-01-30T11:33:19.545287551Z] FIXME: Got an API for which error does not match any expected type!!! error="cannot join own network" error_type="*errors.errorString" module=api
DEBU[2025-01-30T11:33:19.545346093Z] error response for POST request error-response="cannot join own network" method=POST module=api request-url=/v1.47/containers/hello2/start status=500 vars="map[name:hello2 version:1.47]"
DEBU[2025-01-30T11:33:19.545369968Z] FIXME: Got an API for which error does not match any expected type!!! error="cannot join own network" error_type="*errors.errorString" module=api
ERRO[2025-01-30T11:33:19.545375426Z] Handler for POST /v1.47/containers/hello2/start returned error: cannot join own network
With this patch:
docker container create --name hello --network=container:nosuchcontainer alpine
docker container start hello
Error response from daemon: joining network of container: No such container: nosuchcontainer
Error: failed to start containers: hello
# daemon logs:
DEBU[2025-01-30T11:35:50.406462760Z] error response for POST request error-response="joining network of container: No such container: nosuchcontainer" method=POST module=api request-url=/v1.47/containers/hello/start status=500 vars="map[name:hello version:1.47]"
ERRO[2025-01-30T11:35:50.406501468Z] Handler for POST /v1.47/containers/hello/start returned error: joining network of container: No such container: nosuchcontainer
docker container create --name hello2 --network=container:hello2 alpine
docker container start hello2
Error response from daemon: cannot join own network namespace
Error: failed to start containers: hello2
# daemon logs:
DEBU[2025-01-30T11:36:15.178475049Z] error response for POST request error-response="cannot join own network" method=POST module=api request-url=/v1.47/containers/hello2/start status=500 vars="map[name:hello2 version:1.47]"
ERRO[2025-01-30T11:36:15.178536507Z] Handler for POST /v1.47/containers/hello2/start returned error: cannot join own network
docker run --name exitedcontainer alpine
docker run --rm --network=container:exitedcontainer alpine
docker: Error response from daemon: cannot join network namespace of a non running container: container exitedcontainer is exited.
# daemon logs:
DEBU[2025-01-30T12:54:28.040637429Z] error response for POST request error-response="cannot join network namespace of a non running container: container exitedcontainer is exited" method=POST module=api request-url=/v1.47/containers/hello2/start status=409 vars="map[name:hello2 version:1.47]"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
rmLink already looked up the parent container's ID, so we should not use
daemon.GetContainer to resolve the container, as that performs fuzzy
matching (name, ID-prefix, or ID).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It was the only use of errdefs inside api/types, which is the package
that's imported by external users.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
While there may be reasons to keep pkg/errors in production
code, we don't need them for these tests.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It was the only use of github.com/pkg/errors inside api/types,
which is the package that's imported by external users.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When overriding the API version through DOCKER_API_VERSION, no validation
happens on the given version. However, some code-paths in the client do
some minor normalizing, and strip the "v" prefix (if present) as part of
[`Client.getAPIPath()`][1].
This resulted in some inconsistent handling of the version that's set. For
example, [`Client.checkResponseErr()`][2] decides whether or not the API
response is expected to support errors in JSON format (`types.ErrorResponse`),
which would fail because `versions.GreaterThan()` does not strip the prefix,
therefore making the first element "zero" (ranking lower than any valid version).
Net result was "mixed" because of this; for example in the following, half
the output is handled correctly ("downgraded from 1.47"), but the response
is handled as < 1.23 (so printed as-is);
DOCKER_API_VERSION=v1.23 docker version
Client: Docker Engine - Community
Version: 27.5.1
API version: v1.23 (downgraded from 1.47)
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:41:13 2025
OS/Arch: linux/amd64
Context: default
Error response from daemon: {"message":"client version 1.23 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version"}
Passing the version without v-prefix corrects this problem;
DOCKER_API_VERSION=1.23 docker version
Client: Docker Engine - Community
Version: 27.5.1
API version: 1.99 (downgraded from 1.47)
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:41:13 2025
OS/Arch: linux/amd64
Context: default
Error response from daemon: client version 1.99 is too new. Maximum supported API version is 1.47
DOCKER_API_VERSION=v1.99 docker version
Client: Docker Engine - Community
Version: 27.5.1
API version: v1.99 (downgraded from 1.47)
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:41:13 2025
OS/Arch: linux/amd64
Context: default
Error response from daemon: {"message":"client version 1.99 is too new. Maximum supported API version is 1.47"}
This patch strips the prefix when setting a custom version, so that
normalization happens consistently. The existing code to strip the
prefix in [`Client.getAPIPath()`][1] is kept for now, in case values
are set through other ways.
[1]: 47dc8d5dd8/client/client.go (L303-L309)
[2]: 47dc8d5dd8/client/request.go (L231-L241)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
These errors implement errdefs interfaces, and are only used internally
for convenience. Un-export their implemetations because the types themselves
are not used as sentinel errors.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It was only used in a single place, and a generic errdefs.ErrInvalid; the
type itself was not used as sentinel error other than for a unit test.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It's a generic errdefs.ErrInvalidParameter, and the type itself is not
used as sentinel error anywhere.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It's a generic errdefs.ErrInvalidParameter, and the type itself is not
used as sentinel error anywhere.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The `InternalError()` method was added in [moby/libnetwork@50964c9] to
classify the error. However, the same commit defined interfaces for error
types (in the types package). The [InternalError] interface defined did
not match, as it defines a `Internal()` method instead of `InternalError()`.
In short; these errors were never matching any interface, and the actual
error implementations themselves were also never used as a sentinel error,
so we can safely remove these methods.
[moby/libnetwork@50964c9]: 50964c9948
[InternalError]: 50964c9948/types/types.go (L233-L237)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This removes the following errors, which were not used anywhere;
- ErrConfigExists
- ErrInvalidNetworkConfig
- ErrInvalidEndpointConfig
- ErrNetworkExists
- ErrIfaceName
- ErrUnsupportedAddressType
- NonDefaultBridgeNeedsIPError
- IPv6AddrNoMatchError
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It's a generic error, doesn't implement an errdefs type, is poorly formatted,
and not used as sentinel error anywhere. Let's remove it, and update the error
produced to be slightly more informative (include the invalid type). Worth
noting that there's no need to include the name of the driver in the error,
because the only uses of the error (in `registerNetworkDrivers`) already
decorates it; 5fd7ed2937/libnetwork/drivers_linux.go (L34-L36)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It was only used in a single place, and did not implement an errdef;
the type itself was not used as sentinel error.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Use Cobra-generated completion scripts for the CLI inside the dev
container shell.
Remove `DOCKER_BASH_COMPLETION_PATH`.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>