78 Commits

Author SHA1 Message Date
Sebastiaan van Stijn
f39912a30e client: fix some missing error checks in tests (ineffassign)
client/client_test.go:367:5: ineffectual assignment to err (ineffassign)
        _, err = client.Ping(t.Context(), PingOptions{
           ^
    client/client_test.go:381:5: ineffectual assignment to err (ineffassign)
        _, err = client.Ping(t.Context(), PingOptions{
           ^
    client/client_test.go:425:5: ineffectual assignment to err (ineffassign)
        _, err = client.Ping(t.Context(), PingOptions{
           ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-12-18 17:11:15 +01:00
Sebastiaan van Stijn
04ab3d562c client: don't downgrade when failing to negotiate
Historically, the client would downgrade to API v1.24 when failing
to negotiate as this was the API version from before API-version
negotiation was introduced.

Given that those daemons are EOL and those API versions no longer
supported, we should not fall back to an older API version, and
just continue using the latest / current version.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-27 13:52:27 +01:00
Sebastiaan van Stijn
189942570a client: enable API-version negotiation by default
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-27 13:52:27 +01:00
Sebastiaan van Stijn
701f2fdade client: improve mocking responses
Make the mocked responses match the API closer;

- Add headers as returned by the daemon's VersionMiddleware
- By default handle "/_ping" requests to allow the client to
  perform API-version negotiation as part of tests.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-27 12:05:27 +01:00
Sebastiaan van Stijn
ef588715b6 client: add mockPingResponse utility
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-27 12:05:26 +01:00
Sebastiaan van Stijn
d9ee22d1ab Merge pull request #51530 from thaJeztah/allow_renegotiate
client: client.Ping: allow ForceNegotiate with manual override
2025-11-14 20:07:27 +01:00
Sebastiaan van Stijn
6857132911 client: client.Ping: allow ForceNegotiate with manual override
While a manual overridden version shouldn't perform automatic version
negotiation, the "ForceNegotiate" option could still be used to (re)
negotiate a version. This allows a client to be configured with an
initial API version, then triggered to perform API-version negotiation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-14 17:41:56 +01:00
Sebastiaan van Stijn
bcc1db1ce5 client: WithAPIVersion, WithAPIVersionFromEnv: validate well-formedness
Make these options more strict to not allow arbitrary values. Historically,
the `DOCKER_API_VERSION` env-var did not perform any validation as it was
intended for testing-purposes, but given the wider use of this env-var,
we should perform some amount of validation.

Both `WithAPIVersion` and `WithAPIVersionFromEnv` still allow specifying
API versions that are not supported by the client for testing purposes
(e.g. to use API versions beyond `MinAPIVersion` and `MaxAPIVersion`),
but must be well-formed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-14 13:54:31 +01:00
Sebastiaan van Stijn
611c7dce43 client: export fallbackAPIVersion as MinAPIVersion
Export the const and rename it to better reflect its intent.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-14 10:26:37 +01:00
Sebastiaan van Stijn
dae3650dcc client: rename/deprecate WithVersion, WithVersionFromEnv
Add WithAPIVersion and WithAPIVersionFromEnv to be more clear on
the intent, and to align with other related options and fields.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-12 22:39:05 +01:00
Sebastiaan van Stijn
d1f70d4f54 client: deprecate NewClientWithOpts in favor of New
Use a more idiomatic name so that it can be used as `client.New()`.

We should look if we want `New()` to have different / updated defaults
i.e., enable `WithEnv` as default, and have an opt-out and have API-
version negotiation enabled by default (with an opt-out option).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-30 18:09:44 +01:00
Austin Vazquez
e46058cbae client: refactor Events, Info, RegistryLogin
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-29 09:36:23 +01:00
Sebastiaan van Stijn
edbf321ce6 client: remove NegotiateAPIVersion, NegotiateAPIVersionPing
Remove these methods in favor of adding negotiation options to the
Ping method.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-27 19:27:48 +01:00
Sebastiaan van Stijn
0fe6be8c38 client: remove roundTripFunc, bytesBufferClose
- Use the `mockResponse` instead
- `bytesBufferClose` was our own implementation of `io.NopCloser`

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-23 13:01:54 +02:00
Sebastiaan van Stijn
8dc5d1e64d api/types: move Ping and swarm.Status to client
The API does not produce these as a response; the fields in the Ping
struct, including the Swarm status are propagated from headers returned
by the /_ping endpoint.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-22 11:05:08 +02:00
Sebastiaan van Stijn
96b29f5a1f client: remove support for negotiating API version < v1.44 (docker 25.0)
Docker versions below 25.0 have reached EOL; 25.0 is currently maintained
as an LTS version by Mirantis, and we want to allow current versions of the
CLI to be able to connect to such setups.

This patch raises the fallback API version to API v1.44; when negotiating an API
version with a daemon, this will be the lowest version negotiated.

Currently, it still allows manually overriding the version to versions that
are not supported (`WithVersion`, `WithVersionFromEnv`), and no code has
been removed yet that adjusts the client for old API versions, but this
can be done in a follow-up.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-08 13:57:28 +02:00
Sebastiaan van Stijn
04318e0d86 client: update some tests using obsolete API versions
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-08 13:44:39 +02:00
Sebastiaan van Stijn
af5988238a client: reduce uses of obsolete API versions in tests
TestGetAPIPath: don't use obsolete API versions in test

This test was using API v1.22 as "old" version to verify the given
version overrode the default. Update it to use a previous API version
that's still supported by the client.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-30 14:39:48 +02:00
Sebastiaan van Stijn
af3f971431 client: TestNegotiateAPIVersionAutomatic: gofumpt
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-22 11:30:52 +02:00
Sebastiaan van Stijn
e46a991dc5 api: remove unused DefaultVersion, MinSupportedAPIVersion consts
These consts are no longer used, and separate consts were added in both
the client and daemon packages;

- client: 41da5700a4
- daemon: a632b8495b

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-04 07:30:35 -05:00
Paweł Gronowski
6452807fb4 client/client_test: Use functional option to create mock client
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-08-29 15:17:22 +02:00
Derek McGowan
afd6487b2e Create github.com/moby/moby/api module
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-21 09:30:05 -07:00
Sebastiaan van Stijn
41da5700a4 client: define default (and maximum) API version
With the client and API migrating to separate modules, users of the Client
module may upgrade the API module to higher versions. Currently, the Client
uses the API's Default version. While the version of the API module is
allowed to be updated (following SemVer), we should not allow the Client
to support higher API versions than it was written for.

This patch introduces a DefaultAPIVersion in the client package that is
used as default version of the API for the client to use.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-07-17 11:20:17 +02:00
Derek McGowan
e93e15afb0 Replace use of env test util with standard library call
As of Go 1.17, `Setenv` can be used to set environment variables
specific to a single test. This also removes a package which gets
vendored just for this.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-02 15:34:01 -07:00
Matthieu MOREL
469afa5f8f fix httpNoBody from go-critic
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-07 09:57:58 +02:00
Sebastiaan van Stijn
4856e8ffad client: remove // import comments
These comments were added to enforce using the correct import path for
our packages ("github.com/docker/docker", not "github.com/moby/moby").
However, when working in go module mode (not GOPATH / vendor), they have
no effect, so their impact is limited.

Remove these imports in preparation of migrating our code to become an
actual go module.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-05-30 15:59:10 +02:00
Paweł Gronowski
bfc684d3f7 client/client_test: use gotest.tools-style asserts
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-05-19 12:04:04 +02:00
Sebastiaan van Stijn
97b50bca2c client: WithVersion: strip v-prefix when setting API version
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>
2025-01-28 21:32:23 +01:00
maggie44
76a5ca1d4d Accurately reflect the canonical casing of API-Version and OS-Type headers
Go automatically canonicalises HTTP headers, meaning the string `API-Version` passed as a header has always been returned as `Api-Version`. Similarly, `OSType` is returned as `Ostype`.

This commit updates the documentation to reflect this behaviour and modifies the codebase to ensure that input strings are aligned with their canonical output values.

Signed-off-by: maggie44 <64841595+maggie44@users.noreply.github.com>
2024-12-08 22:23:57 +00:00
Sebastiaan van Stijn
ce1a39ab34 client: remove redundant capturing of loop vars (copyloopvar)
client/client_test.go:91:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/client_test.go:326:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/client_test.go:481:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/image_list_test.go:183:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/image_push_test.go:163:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/image_tag_test.go:50:3: The copy of the 'for' variable "repo" can be deleted (Go 1.22+) (copyloopvar)
            repo := repo
            ^
    client/image_tag_test.go:61:3: The copy of the 'for' variable "repotag" can be deleted (Go 1.22+) (copyloopvar)
            repotag := repotag
            ^
    client/ping_test.go:114:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^
    client/request_test.go:53:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
            tc := tc
            ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-12 14:02:12 +01:00
Sebastiaan van Stijn
fa95f8a070 client: fix typos in test-names and godoc
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-09 22:35:04 +02:00
Sebastiaan van Stijn
6aea26b431 client: fix connection-errors being shadowed by API version mismatch errors
Commit e6907243af applied a fix for situations
where the client was configured with API-version negotiation, but did not yet
negotiate a version.

However, the checkVersion() function that was implemented copied the semantics
of cli.NegotiateAPIVersion, which ignored connection failures with the
assumption that connection errors would still surface further down.

However, when using the result of a failed negotiation for NewVersionError,
an API version mismatch error would be produced, masking the actual connection
error.

This patch changes the signature of checkVersion to return unexpected errors,
including failures to connect to the API.

Before this patch:

    docker -H unix:///no/such/socket.sock secret ls
    "secret list" requires API version 1.25, but the Docker daemon API version is 1.24

With this patch applied:

    docker -H unix:///no/such/socket.sock secret ls
    Cannot connect to the Docker daemon at unix:///no/such/socket.sock. Is the docker daemon running?

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-23 15:17:10 +01:00
Sebastiaan van Stijn
901b90593d client: NegotiateAPIVersion: do not ignore (connection) errors from Ping
NegotiateAPIVersion was ignoring errors returned by Ping. The intent here
was to handle API responses from a daemon that may be in an unhealthy state,
however this case is already handled by Ping itself.

Ping only returns an error when either failing to connect to the API (daemon
not running or permissions errors), or when failing to parse the API response.

Neither of those should be ignored in this code, or considered a successful
"ping", so update the code to return

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-23 14:31:55 +01:00
Sebastiaan van Stijn
981a878cf5 vendor: github.com/docker/go-connections fa09c952e3ea (v0.5.0-dev)
0b8c1f4e07...fa09c952e3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-11-10 23:23:37 +01:00
Brian Goff
642e9917ff Add otel support
This uses otel standard environment variables to configure tracing in
the daemon.
It also adds support for propagating trace contexts in the client and
reading those from the API server.

See
https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/
for details on otel environment variables.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2023-09-07 18:38:19 +00:00
Sebastiaan van Stijn
9d1e690751 client: TestGetAPIPath: don't use un-keyed structs
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-07-15 18:31:56 +02:00
Sebastiaan van Stijn
6552441b46 client: TestClientRedirect: cleanup
- don't use un-keyed structs
- use http consts where possible
- use errors.As instead of manually checking the error-type

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-07-15 18:31:56 +02:00
Sebastiaan van Stijn
31ee158394 client: defaultHTTPClient() accept URL
We're parsing the URL either way, so may just as well use the result.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-01-01 13:35:16 +01:00
Sebastiaan van Stijn
0af7b4961a client: TestNewClientWithOpsFromEnv(): use sub-tests
Had this stashed as part of some other changes, so thought I'd push
as a PR; with this patch:

    === RUN   TestNewClientWithOpsFromEnv/invalid_cert_path
    === RUN   TestNewClientWithOpsFromEnv/default_api_version_with_cert_path
    === RUN   TestNewClientWithOpsFromEnv/default_api_version_with_cert_path_and_tls_verify
    === RUN   TestNewClientWithOpsFromEnv/default_api_version_with_cert_path_and_host
    === RUN   TestNewClientWithOpsFromEnv/invalid_docker_host
    === RUN   TestNewClientWithOpsFromEnv/invalid_docker_host,_with_good_format
    === RUN   TestNewClientWithOpsFromEnv/override_api_version
    --- PASS: TestNewClientWithOpsFromEnv (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/default_api_version (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/invalid_cert_path (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/default_api_version_with_cert_path (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/default_api_version_with_cert_path_and_tls_verify (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/default_api_version_with_cert_path_and_host (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/invalid_docker_host (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/invalid_docker_host,_with_good_format (0.00s)
        --- PASS: TestNewClientWithOpsFromEnv/override_api_version (0.00s)
PASS

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-09-22 19:48:39 +02:00
Sebastiaan van Stijn
a5f6500958 replace deprecated gotest.tools' env.Patch() with t.SetEnv()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-05-28 12:12:39 +02:00
Eng Zer Jun
36049a04d2 test: use T.Setenv to set env vars in tests
This commit replaces `os.Setenv` with `t.Setenv` in tests. The
environment variable is automatically restored to its original value
when the test and all its subtests complete.

Reference: https://pkg.go.dev/testing#T.Setenv
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2022-04-23 17:44:16 +08:00
Sebastiaan van Stijn
8512cf076c client: TestNegotiateAPIVersion(), TestClientRedirect(): use sub-tests
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-07 11:13:52 +01:00
Sebastiaan van Stijn
25a336ab6a client: TestGetAPIPath(): update test to use more realistic results
This test was setting the non-exported `Client.basePath` directly, however,
it was setting it to a value that would never realistically happen, because
`NewClientWithOpts()` initializes the Client with the default API version:
ea5b4765d9/client/client.go (L119-L130)

Which is used by `getAPIPath()` to construct the URL/path:
ea5b4765d9/client/client.go (L176-L190)

While this didn't render the test "invalid", using a Client that's constructed
in the usual way, makes it more representative.

Given that we deprecated (but still support) the non-versioned API paths, with
the exception of the `/_ping` API endpoint, we should probably change `getAPIPath()`
to default to the "current version", instead of allowing it to use an empty string.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-07 11:13:02 +01:00
Sebastiaan van Stijn
65e4ea27cd client: various small test-improvements
- avoid accessing non-exported fields where possible, and test using accessors
  instead, so that we're closer to how it's actually used.
- use a variable or const for "expected" in some tests, so that "expected" is
  printed as part of the test-failure output (instead of just a "value").
- swap the order of "actual" and "expected" for consistency, and to make it
  easier to see what the "expected" value is in some cases ("expected" on the
  right, so that it reads `val (actual) != val (expected)`).
- don't set fields in the Ping response that are not relevant to the test.
- rename some variables for consistency.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-07 10:58:03 +01:00
Eng Zer Jun
c55a4ac779 refactor: move from io/ioutil to io and os package
The io/ioutil package has been deprecated in Go 1.16. This commit
replaces the existing io/ioutil functions with their new definitions in
io and os packages.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-08-27 14:56:57 +08:00
Sebastiaan van Stijn
9f0b3f5609 bump gotest.tools v3.0.1 for compatibility with Go 1.14
full diff: https://github.com/gotestyourself/gotest.tools/compare/v2.3.0...v3.0.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-11 00:06:42 +01:00
Sebastiaan van Stijn
b26aa97914 Add client.WithAPIVersionNegotiation() option
WithAPIVersionNegotiation enables automatic API version negotiation for the client.

With this option enabled, the client automatically negotiates the API version
to use when making requests. API version negotiation is performed on the first
request; subsequent requests will not re-negotiate.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-10 19:23:47 +02:00
Sebastiaan van Stijn
0041e2419a Fix empty WithVersion blocking version negotiation
commit 3d72963ab8 fixed
situations where a version negotiation could override
the version, even though a client was initialized with a
fixed version.

In situations where the "fixed" version is empty, we
should ignore the option, and treat the client as
"not having a fixed version", so that API version
negotiation can still be performed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-10 11:14:37 +02:00
Sebastiaan van Stijn
c8ff5ecc09 Remove use of deprecated client.NewEnvClient()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-03 22:49:00 +01:00
Vincent Demeester
3845728524 Update tests to use gotest.tools 👼
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2018-06-13 09:04:30 +02:00