From d36f16e22490a0ff1585b7cea41a6e140ca2de4c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 10 Oct 2025 18:54:19 +0200 Subject: [PATCH] remove API-version compatibility for API < v1.44 Support for API versions < v1.44 was removed in the client in [moby@96b29f5] and [moby@7652f38], so we can remove fallback-code from the CLI as well, as it won't be able to use those versions. [moby@96b29f5]: https://github.com/moby/moby/commit/96b29f5a1f7fc5e5d8b2b4dbd130e215bbb92ae9 [moby@7652f38]: https://github.com/moby/moby/commit/7652f38c289909bc61b1113c0570b9de345bbed9 Signed-off-by: Sebastiaan van Stijn --- cli/command/builder/prune.go | 9 ----- cli/command/cli_test.go | 4 +- cli/command/container/create.go | 7 +--- cli/command/container/run_test.go | 12 +++--- cli/command/formatter/buildcache.go | 2 - cli/command/service/create.go | 7 +--- cli/command/service/list_test.go | 59 ++-------------------------- cli/command/service/rollback.go | 3 +- cli/command/service/rollback_test.go | 3 +- cli/command/service/scale.go | 3 +- cli/command/service/update.go | 34 +++------------- cli/command/stack/client_test.go | 6 +-- cli/command/stack/deploy.go | 8 ---- cli/command/stack/remove.go | 19 +++------ cli/command/stack/remove_test.go | 43 ++++---------------- cli/command/system/prune_test.go | 18 +-------- cli/command/volume/prune.go | 14 ++----- cli/compose/convert/service.go | 18 +-------- cli/compose/convert/service_test.go | 4 +- e2e/container/run_test.go | 1 - e2e/global/cli_test.go | 3 -- 21 files changed, 49 insertions(+), 228 deletions(-) diff --git a/cli/command/builder/prune.go b/cli/command/builder/prune.go index 2c5e0c8769..a7c88dcc42 100644 --- a/cli/command/builder/prune.go +++ b/cli/command/builder/prune.go @@ -12,7 +12,6 @@ import ( "github.com/docker/cli/internal/prompt" "github.com/docker/cli/opts" "github.com/docker/go-units" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -112,17 +111,9 @@ type cancelledErr struct{ error } func (cancelledErr) Cancelled() {} -type errNotImplemented struct{ error } - -func (errNotImplemented) NotImplemented() {} - // pruneFn prunes the build cache for use in "docker system prune" and // returns the amount of space reclaimed and a detailed output string. func pruneFn(ctx context.Context, dockerCLI command.Cli, options pruner.PruneOptions) (uint64, string, error) { - if ver := dockerCLI.Client().ClientVersion(); ver != "" && versions.LessThan(ver, "1.31") { - // Not supported on older daemons. - return 0, "", errNotImplemented{errors.New("builder prune requires API version 1.31 or greater")} - } if !options.Confirmed { // Dry-run: perform validation and produce confirmation before pruning. var confirmMsg string diff --git a/cli/command/cli_test.go b/cli/command/cli_test.go index 3fea155757..adc087a213 100644 --- a/cli/command/cli_test.go +++ b/cli/command/cli_test.go @@ -164,7 +164,7 @@ func TestInitializeFromClient(t *testing.T) { { doc: "successful ping", pingFunc: func() (types.Ping, error) { - return types.Ping{Experimental: true, OSType: "linux", APIVersion: "v1.30"}, nil + return types.Ping{Experimental: true, OSType: "linux", APIVersion: "v1.44"}, nil }, expectedServer: ServerInfo{HasExperimental: true, OSType: "linux"}, negotiated: true, @@ -179,7 +179,7 @@ func TestInitializeFromClient(t *testing.T) { { doc: "failed ping, with API version", pingFunc: func() (types.Ping, error) { - return types.Ping{APIVersion: "v1.33"}, errors.New("failed") + return types.Ping{APIVersion: "v1.44"}, errors.New("failed") }, expectedServer: ServerInfo{HasExperimental: true}, negotiated: true, diff --git a/cli/command/container/create.go b/cli/command/container/create.go index 3faacc382a..55b09a22c1 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -25,7 +25,6 @@ import ( "github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/opts" "github.com/moby/moby/api/types/mount" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/cobra" @@ -306,11 +305,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c } var platform *ocispec.Platform - // Engine API version 1.41 first introduced the option to specify platform on - // create. It will produce an error if you try to set a platform on older API - // versions, so check the API version here to maintain backwards - // compatibility for CLI users. - if options.platform != "" && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.41") { + if options.platform != "" { p, err := platforms.Parse(options.platform) if err != nil { return "", invalidParameter(fmt.Errorf("error parsing specified platform: %w", err)) diff --git a/cli/command/container/run_test.go b/cli/command/container/run_test.go index 925fc0d73f..232d700a69 100644 --- a/cli/command/container/run_test.go +++ b/cli/command/container/run_test.go @@ -61,7 +61,7 @@ func TestRunLabel(t *testing.T) { ID: "id", }, nil }, - Version: "1.36", + Version: client.MaxAPIVersion, }) cmd := newRunCommand(fakeCLI) cmd.SetArgs([]string{"--detach=true", "--label", "foo", "busybox"}) @@ -103,8 +103,8 @@ func TestRunAttach(t *testing.T) { return responseChan, errChan }, // use new (non-legacy) wait API - // see: 38591f20d07795aaef45d400df89ca12f29c603b - Version: "1.30", + // see: https://github.com/docker/cli/commit/38591f20d07795aaef45d400df89ca12f29c603b + Version: client.MaxAPIVersion, }, func(fc *test.FakeCli) { fc.SetOut(streams.NewOut(tty)) fc.SetIn(streams.NewIn(tty)) @@ -180,8 +180,8 @@ func TestRunAttachTermination(t *testing.T) { return responseChan, errChan }, // use new (non-legacy) wait API - // see: 38591f20d07795aaef45d400df89ca12f29c603b - Version: "1.30", + // see: https://github.com/docker/cli/commit/38591f20d07795aaef45d400df89ca12f29c603b + Version: client.MaxAPIVersion, }, func(fc *test.FakeCli) { fc.SetOut(streams.NewOut(tty)) fc.SetIn(streams.NewIn(tty)) @@ -262,7 +262,7 @@ func TestRunPullTermination(t *testing.T) { attachCh <- struct{}{} return respReader, nil }, - Version: "1.30", + Version: client.MaxAPIVersion, }) cmd := newRunCommand(fakeCLI) diff --git a/cli/command/formatter/buildcache.go b/cli/command/formatter/buildcache.go index 68ad421ae0..5fa4541efa 100644 --- a/cli/command/formatter/buildcache.go +++ b/cli/command/formatter/buildcache.go @@ -126,8 +126,6 @@ func (c *buildCacheContext) Parent() string { var parent string if len(c.v.Parents) > 0 { parent = strings.Join(c.v.Parents, ", ") - } else { - parent = c.v.Parent //nolint:staticcheck // Ignore SA1019: Field was deprecated in API v1.42, but kept for backward compatibility } if c.trunc { return TruncateID(parent) diff --git a/cli/command/service/create.go b/cli/command/service/create.go index d5830f5c9d..c3c9565b19 100644 --- a/cli/command/service/create.go +++ b/cli/command/service/create.go @@ -9,7 +9,6 @@ import ( "github.com/docker/cli/cli/command/completion" cliopts "github.com/docker/cli/opts" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -132,9 +131,7 @@ func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, } // query registry if flag disabling it was not set - if !opts.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - createOpts.QueryRegistry = true - } + createOpts.QueryRegistry = !opts.noResolveImage response, err := apiClient.ServiceCreate(ctx, service, createOpts) if err != nil { @@ -147,7 +144,7 @@ func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, _, _ = fmt.Fprintln(dockerCLI.Out(), response.ID) - if opts.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { + if opts.detach { return nil } diff --git a/cli/command/service/list_test.go b/cli/command/service/list_test.go index 479e9a9539..5bb2f6a71d 100644 --- a/cli/command/service/list_test.go +++ b/cli/command/service/list_test.go @@ -10,7 +10,6 @@ import ( "github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test/builders" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -63,59 +62,12 @@ func TestServiceListServiceStatus(t *testing.T) { cluster: &cluster{}, // force an empty cluster expected: []listResponse{}, }, - { - // Services are running, but no active nodes were found. On API v1.40 - // and below, this will cause looking up the "running" tasks to fail, - // as well as looking up "desired" tasks for global services. - doc: "API v1.40 no active nodes", - opts: clusterOpts{ - apiVersion: "1.40", - activeNodes: 0, - runningTasks: 2, - desiredTasks: 4, - }, - expected: []listResponse{ - {ID: "replicated", Replicas: "0/4"}, - {ID: "global", Replicas: "0/0"}, - {ID: "none-id", Replicas: "0/0"}, - }, - }, - { - doc: "API v1.40 3 active nodes, 1 task running", - opts: clusterOpts{ - apiVersion: "1.40", - activeNodes: 3, - runningTasks: 1, - desiredTasks: 2, - }, - expected: []listResponse{ - {ID: "replicated", Replicas: "1/2"}, - {ID: "global", Replicas: "1/3"}, - {ID: "none-id", Replicas: "0/0"}, - }, - }, - { - doc: "API v1.40 3 active nodes, all tasks running", - opts: clusterOpts{ - apiVersion: "1.40", - activeNodes: 3, - runningTasks: 3, - desiredTasks: 3, - }, - expected: []listResponse{ - {ID: "replicated", Replicas: "3/3"}, - {ID: "global", Replicas: "3/3"}, - {ID: "none-id", Replicas: "0/0"}, - }, - }, - { // Services are running, but no active nodes were found. On API v1.41 // and up, the ServiceStatus is sent by the daemon, so this should not // affect the results. - doc: "API v1.41 no active nodes", + doc: "no active nodes", opts: clusterOpts{ - apiVersion: "1.41", activeNodes: 0, runningTasks: 2, desiredTasks: 4, @@ -127,9 +79,8 @@ func TestServiceListServiceStatus(t *testing.T) { }, }, { - doc: "API v1.41 3 active nodes, 1 task running", + doc: "active nodes, 1 task running", opts: clusterOpts{ - apiVersion: "1.41", activeNodes: 3, runningTasks: 1, desiredTasks: 2, @@ -141,9 +92,8 @@ func TestServiceListServiceStatus(t *testing.T) { }, }, { - doc: "API v1.41 3 active nodes, all tasks running", + doc: "active nodes, all tasks running", opts: clusterOpts{ - apiVersion: "1.41", activeNodes: 3, runningTasks: 3, desiredTasks: 3, @@ -174,7 +124,7 @@ func TestServiceListServiceStatus(t *testing.T) { } cli := test.NewFakeCli(&fakeClient{ serviceListFunc: func(ctx context.Context, options client.ServiceListOptions) ([]swarm.Service, error) { - if !options.Status || versions.LessThan(tc.opts.apiVersion, "1.41") { + if !options.Status { // Don't return "ServiceStatus" if not requested, or on older API versions for i := range tc.cluster.services { tc.cluster.services[i].ServiceStatus = nil @@ -214,7 +164,6 @@ func TestServiceListServiceStatus(t *testing.T) { } type clusterOpts struct { - apiVersion string activeNodes uint64 desiredTasks uint64 runningTasks uint64 diff --git a/cli/command/service/rollback.go b/cli/command/service/rollback.go index 4957ea517a..c781a45707 100644 --- a/cli/command/service/rollback.go +++ b/cli/command/service/rollback.go @@ -6,7 +6,6 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -54,7 +53,7 @@ func runRollback(ctx context.Context, dockerCLI command.Cli, options *serviceOpt _, _ = fmt.Fprintln(dockerCLI.Out(), serviceID) - if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { + if options.detach { return nil } diff --git a/cli/command/service/rollback_test.go b/cli/command/service/rollback_test.go index 9c378a3db3..5f43332ddc 100644 --- a/cli/command/service/rollback_test.go +++ b/cli/command/service/rollback_test.go @@ -48,7 +48,8 @@ func TestRollback(t *testing.T) { }) cmd := newRollbackCommand(cli) cmd.SetArgs(tc.args) - cmd.Flags().Set("quiet", "true") + assert.NilError(t, cmd.Flags().Set("quiet", "true")) + assert.NilError(t, cmd.Flags().Set("detach", "true")) cmd.SetOut(io.Discard) assert.NilError(t, cmd.Execute()) assert.Check(t, is.Equal(strings.TrimSpace(cli.ErrBuffer().String()), tc.expectedDockerCliErr)) diff --git a/cli/command/service/scale.go b/cli/command/service/scale.go index 34efd28305..9cfb5f94f1 100644 --- a/cli/command/service/scale.go +++ b/cli/command/service/scale.go @@ -9,7 +9,6 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -83,7 +82,7 @@ func runScale(ctx context.Context, dockerCLI command.Cli, options *scaleOptions, serviceIDs = append(serviceIDs, serviceID) } - if len(serviceIDs) > 0 && !options.detach && versions.GreaterThanOrEqualTo(dockerCLI.Client().ClientVersion(), "1.29") { + if len(serviceIDs) > 0 && !options.detach { for _, serviceID := range serviceIDs { if err := WaitOnService(ctx, dockerCLI, serviceID, false); err != nil { errs = append(errs, fmt.Errorf("%s: %v", serviceID, err)) diff --git a/cli/command/service/update.go b/cli/command/service/update.go index e4ffd4ceb7..4292e66be0 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -22,7 +22,6 @@ import ( "github.com/moby/moby/api/types/mount" "github.com/moby/moby/api/types/network" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/moby/swarmkit/v2/api/defaults" "github.com/spf13/cobra" @@ -165,14 +164,6 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, return err } - // There are two ways to do user-requested rollback. The old way is - // client-side, but with a sufficiently recent daemon we prefer - // server-side, because it will honor the rollback parameters. - var ( - clientSideRollback bool - serverSideRollback bool - ) - spec := &service.Spec if rollback { // Rollback can't be combined with other flags. @@ -188,20 +179,10 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, if otherFlagsPassed { return errors.New("other flags may not be combined with --rollback") } - - if versions.LessThan(apiClient.ClientVersion(), "1.28") { - clientSideRollback = true - spec = service.PreviousSpec - if spec == nil { - return errors.New("service does not have a previous specification to roll back to") - } - } else { - serverSideRollback = true - } } updateOpts := client.ServiceUpdateOptions{} - if serverSideRollback { + if rollback { updateOpts.Rollback = "previous" } @@ -214,9 +195,7 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, if err := resolveServiceImageDigestContentTrust(dockerCLI, spec); err != nil { return err } - if !options.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - updateOpts.QueryRegistry = true - } + updateOpts.QueryRegistry = !options.noResolveImage } updatedSecrets, err := getUpdatedSecrets(ctx, apiClient, flags, spec.TaskTemplate.ContainerSpec.Secrets) @@ -243,8 +222,7 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, if err != nil { return err } - switch { - case sendAuth: + if sendAuth { // Retrieve encoded auth token from the image reference // This would be the old image if it didn't change in this update image := spec.TaskTemplate.ContainerSpec.Image @@ -253,9 +231,7 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, return err } updateOpts.EncodedRegistryAuth = encodedAuth - case clientSideRollback: - updateOpts.RegistryAuthFrom = swarm.RegistryAuthFromPreviousSpec - default: + } else { updateOpts.RegistryAuthFrom = swarm.RegistryAuthFromSpec } @@ -270,7 +246,7 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, _, _ = fmt.Fprintln(dockerCLI.Out(), serviceID) - if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { + if options.detach { return nil } diff --git a/cli/command/stack/client_test.go b/cli/command/stack/client_test.go index 8c2c98f409..4c4a30d0b7 100644 --- a/cli/command/stack/client_test.go +++ b/cli/command/stack/client_test.go @@ -14,8 +14,6 @@ import ( type fakeClient struct { client.Client - version string - services []string networks []string secrets []string @@ -49,8 +47,8 @@ func (*fakeClient) ServerVersion(context.Context) (types.Version, error) { }, nil } -func (cli *fakeClient) ClientVersion() string { - return cli.version +func (*fakeClient) ClientVersion() string { + return client.MaxAPIVersion } func (cli *fakeClient) ServiceList(_ context.Context, options client.ServiceListOptions) ([]swarm.Service, error) { diff --git a/cli/command/stack/deploy.go b/cli/command/stack/deploy.go index 2d3427be8c..944e6ca510 100644 --- a/cli/command/stack/deploy.go +++ b/cli/command/stack/deploy.go @@ -10,7 +10,6 @@ import ( "github.com/docker/cli/cli/compose/convert" composetypes "github.com/docker/cli/cli/compose/types" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -81,13 +80,6 @@ func runDeploy(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, return fmt.Errorf("invalid option %s for flag --resolve-image", opts.resolveImage) } - // client side image resolution should not be done when the supported - // server version is older than 1.30 - if versions.LessThan(dockerCLI.Client().ClientVersion(), "1.30") { - // TODO(thaJeztah): should this error if "opts.ResolveImage" is already other (unsupported) values? - opts.resolveImage = resolveImageNever - } - if opts.detach && !flags.Changed("detach") { _, _ = fmt.Fprintln(dockerCLI.Err(), "Since --detach=false was not specified, tasks will be created in the background.\n"+ "In a future release, --detach=false will become the default.") diff --git a/cli/command/stack/remove.go b/cli/command/stack/remove.go index c5ef0e2194..0484847aca 100644 --- a/cli/command/stack/remove.go +++ b/cli/command/stack/remove.go @@ -10,7 +10,6 @@ import ( "github.com/docker/cli/cli/command" "github.com/moby/moby/api/types/network" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -61,20 +60,14 @@ func runRemove(ctx context.Context, dockerCli command.Cli, opts removeOptions) e return err } - var secrets []swarm.Secret - if versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.25") { - secrets, err = getStackSecrets(ctx, apiClient, namespace) - if err != nil { - return err - } + secrets, err := getStackSecrets(ctx, apiClient, namespace) + if err != nil { + return err } - var configs []swarm.Config - if versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - configs, err = getStackConfigs(ctx, apiClient, namespace) - if err != nil { - return err - } + configs, err := getStackConfigs(ctx, apiClient, namespace) + if err != nil { + return err } if len(services)+len(networks)+len(secrets)+len(configs) == 0 { diff --git a/cli/command/stack/remove_test.go b/cli/command/stack/remove_test.go index 6c843e6f6e..7c5d4033a5 100644 --- a/cli/command/stack/remove_test.go +++ b/cli/command/stack/remove_test.go @@ -11,7 +11,7 @@ import ( is "gotest.tools/v3/assert/cmp" ) -func fakeClientForRemoveStackTest(version string) *fakeClient { +func fakeClientForRemoveStackTest() *fakeClient { allServices := []string{ objectName("foo", "service1"), objectName("foo", "service2"), @@ -33,7 +33,6 @@ func fakeClientForRemoveStackTest(version string) *fakeClient { objectName("bar", "config1"), } return &fakeClient{ - version: version, services: allServices, networks: allNetworks, secrets: allSecrets, @@ -50,40 +49,16 @@ func TestRemoveWithEmptyName(t *testing.T) { assert.ErrorContains(t, cmd.Execute(), `invalid stack name: "' '"`) } -func TestRemoveStackVersion124DoesNotRemoveConfigsOrSecrets(t *testing.T) { - client := fakeClientForRemoveStackTest("1.24") - cmd := newRemoveCommand(test.NewFakeCli(client)) +func TestRemoveStackRemovesEverything(t *testing.T) { + apiClient := fakeClientForRemoveStackTest() + cmd := newRemoveCommand(test.NewFakeCli(apiClient)) cmd.SetArgs([]string{"foo", "bar"}) assert.NilError(t, cmd.Execute()) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.services), client.removedServices)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.networks), client.removedNetworks)) - assert.Check(t, is.Len(client.removedSecrets, 0)) - assert.Check(t, is.Len(client.removedConfigs, 0)) -} - -func TestRemoveStackVersion125DoesNotRemoveConfigs(t *testing.T) { - client := fakeClientForRemoveStackTest("1.25") - cmd := newRemoveCommand(test.NewFakeCli(client)) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NilError(t, cmd.Execute()) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.services), client.removedServices)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.networks), client.removedNetworks)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.secrets), client.removedSecrets)) - assert.Check(t, is.Len(client.removedConfigs, 0)) -} - -func TestRemoveStackVersion130RemovesEverything(t *testing.T) { - client := fakeClientForRemoveStackTest("1.30") - cmd := newRemoveCommand(test.NewFakeCli(client)) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NilError(t, cmd.Execute()) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.services), client.removedServices)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.networks), client.removedNetworks)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.secrets), client.removedSecrets)) - assert.Check(t, is.DeepEqual(buildObjectIDs(client.configs), client.removedConfigs)) + assert.Check(t, is.DeepEqual(buildObjectIDs(apiClient.services), apiClient.removedServices)) + assert.Check(t, is.DeepEqual(buildObjectIDs(apiClient.networks), apiClient.removedNetworks)) + assert.Check(t, is.DeepEqual(buildObjectIDs(apiClient.secrets), apiClient.removedSecrets)) + assert.Check(t, is.DeepEqual(buildObjectIDs(apiClient.configs), apiClient.removedConfigs)) } func TestRemoveStackSkipEmpty(t *testing.T) { @@ -100,7 +75,6 @@ func TestRemoveStackSkipEmpty(t *testing.T) { allConfigIDs := buildObjectIDs(allConfigs) apiClient := &fakeClient{ - version: "1.30", services: allServices, networks: allNetworks, secrets: allSecrets, @@ -141,7 +115,6 @@ func TestRemoveContinueAfterError(t *testing.T) { removedServices := []string{} apiClient := &fakeClient{ - version: "1.30", services: allServices, networks: allNetworks, secrets: allSecrets, diff --git a/cli/command/system/prune_test.go b/cli/command/system/prune_test.go index b8c2f23f2e..e2ee7cc9e8 100644 --- a/cli/command/system/prune_test.go +++ b/cli/command/system/prune_test.go @@ -22,24 +22,8 @@ import ( _ "github.com/docker/cli/cli/command/volume" ) -func TestPrunePromptPre131DoesNotIncludeBuildCache(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{version: "1.30"}) - cmd := newPruneCommand(cli) - cmd.SetArgs([]string{}) - cmd.SetOut(io.Discard) - cmd.SetErr(io.Discard) - assert.ErrorContains(t, cmd.Execute(), "system prune has been cancelled") - expected := `WARNING! This will remove: - - all stopped containers - - all networks not used by at least one container - - all dangling images - -Are you sure you want to continue? [y/N] ` - assert.Check(t, is.Equal(expected, cli.OutBuffer().String())) -} - func TestPrunePromptFilters(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{version: "1.31"}) + cli := test.NewFakeCli(&fakeClient{version: "1.51"}) cli.SetConfigFile(&configfile.ConfigFile{ PruneFilters: []string{"label!=never=remove-me", "label=remove=me"}, }) diff --git a/cli/command/volume/prune.go b/cli/command/volume/prune.go index 9b9ffdf805..d174c65b5a 100644 --- a/cli/command/volume/prune.go +++ b/cli/command/volume/prune.go @@ -11,7 +11,6 @@ import ( "github.com/docker/cli/internal/prompt" "github.com/docker/cli/opts" "github.com/docker/go-units" - "github.com/moby/moby/api/types/versions" "github.com/spf13/cobra" ) @@ -72,16 +71,11 @@ func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) pruneFilters := command.PruneFilters(dockerCli, options.filter.Value()) warning := unusedVolumesWarning - if versions.GreaterThanOrEqualTo(dockerCli.CurrentVersion(), "1.42") { - if options.all { - if _, ok := pruneFilters["all"]; ok { - return 0, "", invalidParamErr{errors.New("conflicting options: cannot specify both --all and --filter all=1")} - } - pruneFilters.Add("all", "true") - warning = allVolumesWarning + if options.all { + if _, ok := pruneFilters["all"]; ok { + return 0, "", invalidParamErr{errors.New("conflicting options: cannot specify both --all and --filter all=1")} } - } else { - // API < v1.42 removes all volumes (anonymous and named) by default. + pruneFilters.Add("all", "true") warning = allVolumesWarning } if !options.force { diff --git a/cli/compose/convert/service.go b/cli/compose/convert/service.go index 5ae8e122e9..746a9656f3 100644 --- a/cli/compose/convert/service.go +++ b/cli/compose/convert/service.go @@ -16,7 +16,6 @@ import ( "github.com/moby/moby/api/types/container" "github.com/moby/moby/api/types/network" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/versions" "github.com/moby/moby/client" ) @@ -44,7 +43,7 @@ func Services( return nil, fmt.Errorf("service %s: %w", service.Name, err) } - serviceSpec, err := Service(apiClient.ClientVersion(), namespace, service, config.Networks, config.Volumes, secrets, configs) + serviceSpec, err := Service(namespace, service, config.Networks, config.Volumes, secrets, configs) if err != nil { return nil, fmt.Errorf("service %s: %w", service.Name, err) } @@ -56,7 +55,6 @@ func Services( // Service converts a ServiceConfig into a swarm ServiceSpec func Service( - apiVersion string, namespace Namespace, service composetypes.ServiceConfig, networkConfigs map[string]composetypes.NetworkConfig, @@ -161,6 +159,7 @@ func Service( Preferences: getPlacementPreference(service.Deploy.Placement.Preferences), MaxReplicas: service.Deploy.Placement.MaxReplicas, }, + Networks: networks, }, EndpointSpec: endpoint, Mode: mode, @@ -171,18 +170,6 @@ func Service( // add an image label to serviceSpec serviceSpec.Labels[LabelImage] = service.Image - // ServiceSpec.Networks is deprecated and should not have been used by - // this package. It is possible to update TaskTemplate.Networks, but it - // is not possible to update ServiceSpec.Networks. Unfortunately, we - // can't unconditionally start using TaskTemplate.Networks, because that - // will break with older daemons that don't support migrating from - // ServiceSpec.Networks to TaskTemplate.Networks. So which field to use - // is conditional on daemon version. - if versions.LessThan(apiVersion, "1.29") { - serviceSpec.Networks = networks //nolint:staticcheck // ignore SA1019: field is deprecated. - } else { - serviceSpec.TaskTemplate.Networks = networks - } return serviceSpec, nil } @@ -670,7 +657,6 @@ func toNetipAddrSlice(ips []string) []netip.Addr { func convertCredentialSpec(namespace Namespace, spec composetypes.CredentialSpecConfig, refs []*swarm.ConfigReference) (*swarm.CredentialSpec, error) { var o []string - // Config was added in API v1.40 if spec.Config != "" { o = append(o, `"Config"`) } diff --git a/cli/compose/convert/service_test.go b/cli/compose/convert/service_test.go index 165e5bf99c..db094f8a6b 100644 --- a/cli/compose/convert/service_test.go +++ b/cli/compose/convert/service_test.go @@ -495,7 +495,7 @@ func TestServiceConvertsIsolation(t *testing.T) { src := composetypes.ServiceConfig{ Isolation: "hyperv", } - result, err := Service("1.35", Namespace{name: "foo"}, src, nil, nil, nil, nil) + result, err := Service(Namespace{name: "foo"}, src, nil, nil, nil, nil) assert.NilError(t, err) assert.Check(t, is.Equal(container.IsolationHyperV, result.TaskTemplate.ContainerSpec.Isolation)) } @@ -692,7 +692,7 @@ func TestConvertServiceCapAddAndCapDrop(t *testing.T) { } for _, tc := range tests { t.Run(tc.title, func(t *testing.T) { - result, err := Service("1.41", Namespace{name: "foo"}, tc.in, nil, nil, nil, nil) + result, err := Service(Namespace{name: "foo"}, tc.in, nil, nil, nil, nil) assert.NilError(t, err) assert.Check(t, is.DeepEqual(result.TaskTemplate.ContainerSpec.CapabilityAdd, tc.out.CapAdd)) assert.Check(t, is.DeepEqual(result.TaskTemplate.ContainerSpec.CapabilityDrop, tc.out.CapDrop)) diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index 55382ad465..af0486fdee 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -210,7 +210,6 @@ func TestRunWithCgroupNamespace(t *testing.T) { func TestMountSubvolume(t *testing.T) { skip.If(t, versions.LessThan(environment.DaemonAPIVersion(t), "1.45")) - volName := "test-volume-" + t.Name() icmd.RunCommand("docker", "volume", "create", volName).Assert(t, icmd.Success) diff --git a/e2e/global/cli_test.go b/e2e/global/cli_test.go index 5275ee9458..036a965194 100644 --- a/e2e/global/cli_test.go +++ b/e2e/global/cli_test.go @@ -16,7 +16,6 @@ import ( "github.com/docker/cli/e2e/testutils" "github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test/environment" - "github.com/moby/moby/api/types/versions" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" @@ -144,7 +143,6 @@ func TestPromptExitCode(t *testing.T) { run: func(t *testing.T) icmd.Cmd { t.Helper() t.Skip("flaky test: see https://github.com/docker/cli/issues/6248") - skip.If(t, versions.LessThan(environment.DaemonAPIVersion(t), "1.44")) const plugin = "registry:5000/plugin-install-test:latest" @@ -162,7 +160,6 @@ func TestPromptExitCode(t *testing.T) { run: func(t *testing.T) icmd.Cmd { t.Helper() t.Skip("flaky test: see https://github.com/docker/cli/issues/6248") - skip.If(t, versions.LessThan(environment.DaemonAPIVersion(t), "1.44")) const plugin = "registry:5000/plugin-upgrade-test"