Add a new type to use for building filter predicates for API requests,
replacing "./api/types/filters".Args in the client. Remove the now
unused api/types/filters package.
Signed-off-by: Cory Snider <csnider@mirantis.com>
The format for filters changed in 93d1dd8036
(docker v1.10 / API v1.22). As part of that implementation, the daemon
would parse the new format, and fall back to parsing the old format if
this failed. This fallback was not based on API version, so any version
of the API released since would continue to accept both the legacy and
curent format.
For the client, the change in format caused a regression when connecting
to an older daemon; a `ToParamWithVersion` utility was introduced in
[docker/engine-api@81388f0] to produce the old format when the client was
connected to a docker v1.9 or older daemon, using an old API version.
Given that any version of docker 1.10 or above would support both formats,
regardless of the API version used, and API v1.22 is no longer supported,
it should be safe to assume we can drop the version-specific format in the
client. Even if the client would be using API v1.22 (or older), the format
would only be necessary for an actual docker v1.9 daemon, which would be
very unlikely, and a daemon that's 9 Years old.
[docker/engine-api@81388f0]: 81388f00dd
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Move the option-types to the client and in some cases create a
copy for the backend. These types are used to construct query-
args, and not marshaled to JSON, and can be replaced with functional
options in the client.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It's only used by the client to support API versions older than v1.22.
Make it an internal utility that doesn't depend on internal fields of
`filter.Args`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Originally I've found this datarace on a project I'm working at. I'm not
able to consistently reproduce this. But by looking at the codebase I
took a chance to fix other 2 possible function that might produce such
data race.
Original stack trace produced when running `go test -race` on GH CI:
```
WARNING: DATA RACE
Write at 0x00c0005dc688 by goroutine 43:
github.com/docker/docker/client.(*Client).negotiateAPIVersionPing()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/client.go:389 +0x12f
github.com/docker/docker/client.(*Client).checkVersion()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/client.go:298 +0x249
github.com/docker/docker/client.(*Client).getAPIPath()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/client.go:307 +0x76
github.com/docker/docker/client.(*Client).sendRequest()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/request.go:111 +0x9b
github.com/docker/docker/client.(*Client).get()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/request.go:28 +0x736
github.com/docker/docker/client.(*Client).ContainerList()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/container_list.go:47 +0x6f0
Previous read at 0x00c0005dc688 by goroutine 42:
github.com/docker/docker/client.(*Client).ContainerList()
/home/runner/go/pkg/mod/github.com/docker/docker@v28.2.2+incompatible/client/container_list.go:39 +0x5ef
```
Co-authored-by: Luca Rinaldi <lucarin@protonmail.com>
Signed-off-by: Alessio Perugini <alessio@perugini.xyz>
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>
Looking in history to learn why this struct existed, shows that this type
was mostly the result of tech-debt accumulating over time;
- originally ([moby@1aa7f13]) most of the request handling was internal;
the [`call()` function][1] would make a request, read the `response.Body`,
and return it as a `[]byte` (or an error if one happened).
- some features needed the statuscode, so [moby@a4bcf7e] added an extra
output variable to return the `response.StatusCode`.
- some new features required streaming, so [moby@fdd8d4b] changed the
function to return the `response.Body` as a `io.ReadCloser`, instead
of a `[]byte`.
- some features needed access to the content-type header, so a new
`clientRequest` method was introduced in [moby@6b2eeaf] to read the
`Content-Type` header from `response.Headers` and return it as a string.
- of course, `Content-Type` may not be the only header needed, so [moby@0cdc3b7]
changed the signature to return `response.Headers` as a whole as a
`http.Header`
- things became a bit unwieldy now, with the function having four (4) output
variables, so [moby@126529c] chose to refactor this code, introducing a
`serverResponse` struct to wrap them all, not realizing that all these
values were effectively deconstructed from the `url.Response`, so now
re-assembling them into our own "URL response", only preserving a subset
of the information available.
- now that we had a custom struct, it was possible to add more information
to it without changing the signature. When there was a need to know the
URL of the request that initiated the response, [moby@27ef09a] introduced
a `reqURL` field to hold the `request.URL` which notably also is available
in `response.Request.URL`.
In short;
- The original implementation tried to (pre-maturely) abstract the underlying
response to provide a simplified interface.
- While initially not needed, abstracting caused relevant information from
the response (and request) to be unavailable to callers.
- As a result, we ended up in a situation where we are deconstructing the
original `url.Response`, only to re-assemble it into our own, custom struct
(`serverResponsee`) with only a subset of the information preserved.
This patch removes the `serverResponse` struct, instead returning the
`url.Response` as-is, so that all information is preserved, allowing callers
to use the information they need.
There is one follow-up change to consider; commit [moby@589df17] introduced
a `ensureReaderClosed` utility. Before that commit, the response body would
be closed in a more idiomatic way through a [`defer serverResp.body.Close()`][2].
A later change in [docker/engine-api@5dd6452] added an optimization to that
utility, draining the response to allow connections to be reused. While
skipping that utility (and not draining the response) would not be a critical
issue, it may be easy to overlook that utility, and to close the response
body in the "idiomatic" way, resulting in a possible performance regression.
We need to check if that optimization is still relevant or if later changes
in Go itself already take care of this; we should also look if context
cancellation is handled correctly for these. If it's still relevant, we could
- Wrap the the `url.Response` in a custom struct ("drainCloser") to provide
a `Close()` function handling the draining and closing; this would re-
introduce a custom type to be returned, so perhaps not what we want.
- Wrap the `url.Response.Body` in the response returned (so, calling)
`response.Body.Close()` would call the wrapped closer.
- Change the signature of `Client.sendRequest()` (and related) to return
a `close()` func to handle this; doing so would more strongly encourage
callers to close the response body.
[1]: 1aa7f1392d/commands.go (L1008-L1027)
[2]: 589df17a1a/api/client/ps.go (L84-L89)
[moby@1aa7f13]: 1aa7f1392d
[moby@a4bcf7e]: a4bcf7e1ac
[moby@fdd8d4b]: fdd8d4b7d9
[moby@6b2eeaf]: 6b2eeaf896
[moby@0cdc3b7]: 0cdc3b7539
[moby@126529c]: 126529c6d0
[moby@27ef09a]: 27ef09a46f
[moby@589df17]: 589df17a1a
[docker/engine-api@5dd6452]: 5dd6452d4d
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This moves the `Container` type to the containere package, rename
it to `Summary`, and deprecates the old location.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
both -1 and 0 are accepted as "no limit", so don't send the
limit option if no limit was set. For simplicity, we're ignoring
values <= 0.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The old nolint comment didn't seem to work anymore;
```
client/container_list.go:39:22: SA1019: filters.ToParamWithVersion is deprecated: do not use in any new code; use ToJSON instead (staticcheck)
client/events.go:94:22: SA1019: filters.ToParamWithVersion is deprecated: do not use in any new code; use ToJSON instead (staticcheck)
client/image_list.go:28:22: SA1019: filters.ToParamWithVersion is deprecated: do not use in any new code; use ToJSON instead (staticcheck)
```
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Add annotations to suppress warnings like this one:
> client/container_list.go:38:22: SA1019: filters.ToParamWithVersion is deprecated: Use ToJSON (staticcheck)
> filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
> ^
Modify the deprecation notice to specify it is applicable to new code
only.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Unlike a plain `net/http/client.Do()`, requests made through client/request
use the `sendRequest` function, which parses the server response, and may
convert non-transport errors into errors (through `cli.checkResponseErr()`).
This means that we cannot assume that no reader was opened if an error is
returned.
This patch changes various locations where `ensureReaderClosed` was only
called in the non-error situation, and uses a `defer` to make sure it's
always called.
`ensureReaderClosed` itself already checks if the response's body was set,
so in situations where the error was due to a transport error, calling
`ensureReaderClosed` should be a no-op.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Since Go 1.7, context is a standard package. Since Go 1.9, everything
that is provided by "x/net/context" is a couple of type aliases to
types in "context".
Many vendored packages still use x/net/context, so vendor entry remains
for now.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
In file `api/types/client.go`, some of the "*Options{}" structs own a
`Filters` field while some else have the name of `Filter`, this commit
will rename all `Filter` to `Filters` for consistency. Also `Filters`
is consistent with API with format `/xxx?filters=xxx`, that's why
`Filters` is the right name.
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>