From 839e46f97cc45878f3e215c9c7fa3ca75b6dada3 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 15 Sep 2025 21:27:58 +0200 Subject: [PATCH] client: remove support for API < v1.22 filter format The format for filters changed in 93d1dd8036d57f5cf1e5cbbbad875ae9a6fa6180 (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]: https://github.com/docker-archive-public/docker.engine-api//commit/81388f00dde756d73eaf3bc653be4bf567547a98 Signed-off-by: Sebastiaan van Stijn --- client/container_list.go | 18 --------- client/image_list.go | 7 ---- client/network_list.go | 9 ----- client/plugin_list.go | 8 ---- client/system_events.go | 22 +---------- client/utils.go | 38 ------------------- client/utils_test.go | 20 ---------- client/volume_list.go | 8 ---- .../moby/moby/client/container_list.go | 18 --------- .../github.com/moby/moby/client/image_list.go | 7 ---- .../moby/moby/client/network_list.go | 9 ----- .../moby/moby/client/plugin_list.go | 8 ---- .../moby/moby/client/system_events.go | 22 +---------- vendor/github.com/moby/moby/client/utils.go | 38 ------------------- .../moby/moby/client/volume_list.go | 8 ---- 15 files changed, 4 insertions(+), 236 deletions(-) diff --git a/client/container_list.go b/client/container_list.go index f30004f1af..9e1c3ab3ea 100644 --- a/client/container_list.go +++ b/client/container_list.go @@ -8,7 +8,6 @@ import ( "github.com/moby/moby/api/types/container" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" ) // ContainerListOptions holds parameters to list containers with. @@ -47,27 +46,10 @@ func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptio } if options.Filters.Len() > 0 { - // Make sure we negotiated (if the client is configured to do so), - // as code below contains API-version specific handling of options. - // - // Normally, version-negotiation (if enabled) would not happen until - // the API request is made. - if err := cli.checkVersion(ctx); err != nil { - return nil, err - } - filterJSON, err := filters.ToJSON(options.Filters) if err != nil { return nil, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } - query.Set("filters", filterJSON) } diff --git a/client/image_list.go b/client/image_list.go index fe5e0ea6a6..6ca906c5ad 100644 --- a/client/image_list.go +++ b/client/image_list.go @@ -43,13 +43,6 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i if err != nil { return images, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } if options.All { diff --git a/client/network_list.go b/client/network_list.go index 2dd9525931..2eefe4cfa6 100644 --- a/client/network_list.go +++ b/client/network_list.go @@ -7,7 +7,6 @@ import ( "github.com/moby/moby/api/types/filters" "github.com/moby/moby/api/types/network" - "github.com/moby/moby/api/types/versions" ) // NetworkList returns the list of networks configured in the docker host. @@ -18,14 +17,6 @@ func (cli *Client) NetworkList(ctx context.Context, options NetworkListOptions) if err != nil { return nil, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } - query.Set("filters", filterJSON) } var networkResources []network.Summary diff --git a/client/plugin_list.go b/client/plugin_list.go index a7f80ebc23..238aed70e3 100644 --- a/client/plugin_list.go +++ b/client/plugin_list.go @@ -7,7 +7,6 @@ import ( "github.com/moby/moby/api/types/filters" "github.com/moby/moby/api/types/plugin" - "github.com/moby/moby/api/types/versions" ) // PluginList returns the installed plugins @@ -20,13 +19,6 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (plugin. if err != nil { return plugins, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return plugins, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } resp, err := cli.get(ctx, "/plugins", query, nil) diff --git a/client/system_events.go b/client/system_events.go index d67bd4793c..93b12cdefd 100644 --- a/client/system_events.go +++ b/client/system_events.go @@ -8,7 +8,6 @@ import ( "github.com/moby/moby/api/types/events" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client/internal/timestamp" ) @@ -31,17 +30,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha go func() { defer close(errs) - // Make sure we negotiated (if the client is configured to do so), - // as code below contains API-version specific handling of options. - // - // Normally, version-negotiation (if enabled) would not happen until - // the API request is made. - if err := cli.checkVersion(ctx); err != nil { - close(started) - errs <- err - return - } - query, err := buildEventsQueryParams(cli.version, options) + query, err := buildEventsQueryParams(options) if err != nil { close(started) errs <- err @@ -85,7 +74,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha return messages, errs } -func buildEventsQueryParams(cliVersion string, options EventsListOptions) (url.Values, error) { +func buildEventsQueryParams(options EventsListOptions) (url.Values, error) { query := url.Values{} ref := time.Now() @@ -110,13 +99,6 @@ func buildEventsQueryParams(cliVersion string, options EventsListOptions) (url.V if err != nil { return nil, err } - if cliVersion != "" && versions.LessThan(cliVersion, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } diff --git a/client/utils.go b/client/utils.go index 8f99284c5a..6908542419 100644 --- a/client/utils.go +++ b/client/utils.go @@ -81,41 +81,3 @@ func encodePlatform(platform *ocispec.Platform) (string, error) { } return string(p), nil } - -// encodeLegacyFilters encodes Args in the legacy format as used in API v1.21 and older. -// where values are a list of strings, instead of a set. -// -// Don't use in any new code; use [filters.ToJSON]] instead. -func encodeLegacyFilters(currentFormat string) (string, error) { - // The Args.fields field is not exported, but used to marshal JSON, - // so we'll marshal to the new format, then unmarshal to get the - // fields, and marshal again. - // - // This is far from optimal, but this code is only used for deprecated - // API versions, so should not be hit commonly. - var argsFields map[string]map[string]bool - err := json.Unmarshal([]byte(currentFormat), &argsFields) - if err != nil { - return "", err - } - - buf, err := json.Marshal(convertArgsToSlice(argsFields)) - if err != nil { - return "", err - } - return string(buf), nil -} - -func convertArgsToSlice(f map[string]map[string]bool) map[string][]string { - m := map[string][]string{} - for k, v := range f { - values := []string{} - for kk := range v { - if v[kk] { - values = append(values, kk) - } - } - m[k] = values - } - return m -} diff --git a/client/utils_test.go b/client/utils_test.go index 2c431d9c6c..04d01ed7d5 100644 --- a/client/utils_test.go +++ b/client/utils_test.go @@ -3,7 +3,6 @@ package client import ( "testing" - "github.com/moby/moby/api/types/filters" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -56,22 +55,3 @@ func TestEncodePlatforms(t *testing.T) { }) } } - -func TestEncodeLegacyFilters(t *testing.T) { - a := filters.NewArgs( - filters.Arg("created", "today"), - filters.Arg("image.name", "ubuntu*"), - filters.Arg("image.name", "*untu"), - ) - - currentFormat, err := filters.ToJSON(a) - assert.NilError(t, err) - - // encode in the API v1.21 (and older) format - str1, err := encodeLegacyFilters(currentFormat) - assert.Check(t, err) - if str1 != `{"created":["today"],"image.name":["*untu","ubuntu*"]}` && - str1 != `{"created":["today"],"image.name":["ubuntu*","*untu"]}` { - t.Errorf("incorrectly marshaled the filters: %s", str1) - } -} diff --git a/client/volume_list.go b/client/volume_list.go index 8a4d6af7dd..975d3330c1 100644 --- a/client/volume_list.go +++ b/client/volume_list.go @@ -6,7 +6,6 @@ import ( "net/url" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/api/types/volume" ) @@ -19,13 +18,6 @@ func (cli *Client) VolumeList(ctx context.Context, options VolumeListOptions) (v if err != nil { return volume.ListResponse{}, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return volume.ListResponse{}, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } resp, err := cli.get(ctx, "/volumes", query, nil) diff --git a/vendor/github.com/moby/moby/client/container_list.go b/vendor/github.com/moby/moby/client/container_list.go index f30004f1af..9e1c3ab3ea 100644 --- a/vendor/github.com/moby/moby/client/container_list.go +++ b/vendor/github.com/moby/moby/client/container_list.go @@ -8,7 +8,6 @@ import ( "github.com/moby/moby/api/types/container" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" ) // ContainerListOptions holds parameters to list containers with. @@ -47,27 +46,10 @@ func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptio } if options.Filters.Len() > 0 { - // Make sure we negotiated (if the client is configured to do so), - // as code below contains API-version specific handling of options. - // - // Normally, version-negotiation (if enabled) would not happen until - // the API request is made. - if err := cli.checkVersion(ctx); err != nil { - return nil, err - } - filterJSON, err := filters.ToJSON(options.Filters) if err != nil { return nil, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } - query.Set("filters", filterJSON) } diff --git a/vendor/github.com/moby/moby/client/image_list.go b/vendor/github.com/moby/moby/client/image_list.go index fe5e0ea6a6..6ca906c5ad 100644 --- a/vendor/github.com/moby/moby/client/image_list.go +++ b/vendor/github.com/moby/moby/client/image_list.go @@ -43,13 +43,6 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i if err != nil { return images, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } if options.All { diff --git a/vendor/github.com/moby/moby/client/network_list.go b/vendor/github.com/moby/moby/client/network_list.go index 2dd9525931..2eefe4cfa6 100644 --- a/vendor/github.com/moby/moby/client/network_list.go +++ b/vendor/github.com/moby/moby/client/network_list.go @@ -7,7 +7,6 @@ import ( "github.com/moby/moby/api/types/filters" "github.com/moby/moby/api/types/network" - "github.com/moby/moby/api/types/versions" ) // NetworkList returns the list of networks configured in the docker host. @@ -18,14 +17,6 @@ func (cli *Client) NetworkList(ctx context.Context, options NetworkListOptions) if err != nil { return nil, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } - query.Set("filters", filterJSON) } var networkResources []network.Summary diff --git a/vendor/github.com/moby/moby/client/plugin_list.go b/vendor/github.com/moby/moby/client/plugin_list.go index a7f80ebc23..238aed70e3 100644 --- a/vendor/github.com/moby/moby/client/plugin_list.go +++ b/vendor/github.com/moby/moby/client/plugin_list.go @@ -7,7 +7,6 @@ import ( "github.com/moby/moby/api/types/filters" "github.com/moby/moby/api/types/plugin" - "github.com/moby/moby/api/types/versions" ) // PluginList returns the installed plugins @@ -20,13 +19,6 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (plugin. if err != nil { return plugins, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return plugins, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } resp, err := cli.get(ctx, "/plugins", query, nil) diff --git a/vendor/github.com/moby/moby/client/system_events.go b/vendor/github.com/moby/moby/client/system_events.go index d67bd4793c..93b12cdefd 100644 --- a/vendor/github.com/moby/moby/client/system_events.go +++ b/vendor/github.com/moby/moby/client/system_events.go @@ -8,7 +8,6 @@ import ( "github.com/moby/moby/api/types/events" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client/internal/timestamp" ) @@ -31,17 +30,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha go func() { defer close(errs) - // Make sure we negotiated (if the client is configured to do so), - // as code below contains API-version specific handling of options. - // - // Normally, version-negotiation (if enabled) would not happen until - // the API request is made. - if err := cli.checkVersion(ctx); err != nil { - close(started) - errs <- err - return - } - query, err := buildEventsQueryParams(cli.version, options) + query, err := buildEventsQueryParams(options) if err != nil { close(started) errs <- err @@ -85,7 +74,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha return messages, errs } -func buildEventsQueryParams(cliVersion string, options EventsListOptions) (url.Values, error) { +func buildEventsQueryParams(options EventsListOptions) (url.Values, error) { query := url.Values{} ref := time.Now() @@ -110,13 +99,6 @@ func buildEventsQueryParams(cliVersion string, options EventsListOptions) (url.V if err != nil { return nil, err } - if cliVersion != "" && versions.LessThan(cliVersion, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return nil, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } diff --git a/vendor/github.com/moby/moby/client/utils.go b/vendor/github.com/moby/moby/client/utils.go index 8f99284c5a..6908542419 100644 --- a/vendor/github.com/moby/moby/client/utils.go +++ b/vendor/github.com/moby/moby/client/utils.go @@ -81,41 +81,3 @@ func encodePlatform(platform *ocispec.Platform) (string, error) { } return string(p), nil } - -// encodeLegacyFilters encodes Args in the legacy format as used in API v1.21 and older. -// where values are a list of strings, instead of a set. -// -// Don't use in any new code; use [filters.ToJSON]] instead. -func encodeLegacyFilters(currentFormat string) (string, error) { - // The Args.fields field is not exported, but used to marshal JSON, - // so we'll marshal to the new format, then unmarshal to get the - // fields, and marshal again. - // - // This is far from optimal, but this code is only used for deprecated - // API versions, so should not be hit commonly. - var argsFields map[string]map[string]bool - err := json.Unmarshal([]byte(currentFormat), &argsFields) - if err != nil { - return "", err - } - - buf, err := json.Marshal(convertArgsToSlice(argsFields)) - if err != nil { - return "", err - } - return string(buf), nil -} - -func convertArgsToSlice(f map[string]map[string]bool) map[string][]string { - m := map[string][]string{} - for k, v := range f { - values := []string{} - for kk := range v { - if v[kk] { - values = append(values, kk) - } - } - m[k] = values - } - return m -} diff --git a/vendor/github.com/moby/moby/client/volume_list.go b/vendor/github.com/moby/moby/client/volume_list.go index 8a4d6af7dd..975d3330c1 100644 --- a/vendor/github.com/moby/moby/client/volume_list.go +++ b/vendor/github.com/moby/moby/client/volume_list.go @@ -6,7 +6,6 @@ import ( "net/url" "github.com/moby/moby/api/types/filters" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/api/types/volume" ) @@ -19,13 +18,6 @@ func (cli *Client) VolumeList(ctx context.Context, options VolumeListOptions) (v if err != nil { return volume.ListResponse{}, err } - if cli.version != "" && versions.LessThan(cli.version, "1.22") { - legacyFormat, err := encodeLegacyFilters(filterJSON) - if err != nil { - return volume.ListResponse{}, err - } - filterJSON = legacyFormat - } query.Set("filters", filterJSON) } resp, err := cli.get(ctx, "/volumes", query, nil)