diff --git a/Makefile b/Makefile index 34004f1114..601abd1cad 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ example-provider: ## build example provider for e2e tests mocks: mockgen --version >/dev/null 2>&1 || go install go.uber.org/mock/mockgen@v0.4.0 mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli - mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/docker/docker/client APIClient + mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/moby/moby/client APIClient mockgen -destination pkg/mocks/mock_docker_compose_api.go -package mocks -source=./pkg/api/api.go Service .PHONY: e2e diff --git a/cmd/compose/bridge.go b/cmd/compose/bridge.go index 22f78b6899..6c8533d387 100644 --- a/cmd/compose/bridge.go +++ b/cmd/compose/bridge.go @@ -23,9 +23,9 @@ import ( "github.com/distribution/reference" "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/pkg/stringid" "github.com/docker/go-units" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/client/pkg/stringid" "github.com/spf13/cobra" "github.com/docker/compose/v2/cmd/formatter" diff --git a/cmd/compose/config.go b/cmd/compose/config.go index 4d781c8671..08788c9d8b 100644 --- a/cmd/compose/config.go +++ b/cmd/compose/config.go @@ -324,17 +324,17 @@ func resolveImageDigests(ctx context.Context, dockerCli command.Cli, model map[s func formatModel(model map[string]any, format string) (content []byte, err error) { switch format { case "json": - content, err = json.MarshalIndent(model, "", " ") + return json.MarshalIndent(model, "", " ") case "yaml": buf := bytes.NewBuffer([]byte{}) encoder := yaml.NewEncoder(buf) encoder.SetIndent(2) err = encoder.Encode(model) content = buf.Bytes() + return content, err default: return nil, fmt.Errorf("unsupported format %q", format) } - return } func runServices(ctx context.Context, dockerCli command.Cli, opts configOptions) error { diff --git a/cmd/compose/images.go b/cmd/compose/images.go index 4f305e4919..d1d381f706 100644 --- a/cmd/compose/images.go +++ b/cmd/compose/images.go @@ -27,8 +27,8 @@ import ( "github.com/containerd/platforms" "github.com/docker/cli/cli/command" - "github.com/docker/docker/pkg/stringid" "github.com/docker/go-units" + "github.com/moby/moby/client/pkg/stringid" "github.com/spf13/cobra" "github.com/docker/compose/v2/cmd/formatter" diff --git a/cmd/compose/list.go b/cmd/compose/list.go index 38fb2ce8c5..c0059b24ad 100644 --- a/cmd/compose/list.go +++ b/cmd/compose/list.go @@ -18,12 +18,15 @@ package compose import ( "context" + "errors" "fmt" "io" + "regexp" "strings" "github.com/docker/cli/cli/command" "github.com/docker/compose/v2/cmd/formatter" + "github.com/moby/moby/client" "github.com/docker/cli/opts" "github.com/spf13/cobra" @@ -61,11 +64,32 @@ var acceptedListFilters = map[string]bool{ "name": true, } +// match returns true if any of the values at key match the source string +func match(filters client.Filters, field, source string) bool { + if f, ok := filters[field]; ok && f[source] { + return true + } + + fieldValues := filters[field] + for name2match := range fieldValues { + isMatch, err := regexp.MatchString(name2match, source) + if err != nil { + continue + } + if isMatch { + return true + } + } + return false +} + func runList(ctx context.Context, dockerCli command.Cli, backend api.Service, lsOpts lsOptions) error { filters := lsOpts.Filter.Value() - err := filters.Validate(acceptedListFilters) - if err != nil { - return err + + for filter := range filters { + if _, ok := acceptedListFilters[filter]; !ok { + return errors.New("invalid filter '" + filter + "'") + } } stackList, err := backend.List(ctx, api.ListOptions{All: lsOpts.All}) @@ -73,13 +97,12 @@ func runList(ctx context.Context, dockerCli command.Cli, backend api.Service, ls return err } - if filters.Len() > 0 { + if len(filters) > 0 { var filtered []api.Stack for _, s := range stackList { - if filters.Contains("name") && !filters.Match("name", s.Name) { - continue + if match(filters, "name", s.Name) { + filtered = append(filtered, s) } - filtered = append(filtered, s) } stackList = filtered } diff --git a/cmd/compose/stats.go b/cmd/compose/stats.go index 98d5aa63af..2f4d3ffa93 100644 --- a/cmd/compose/stats.go +++ b/cmd/compose/stats.go @@ -22,7 +22,7 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/container" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/client" "github.com/spf13/cobra" "github.com/docker/compose/v2/pkg/api" @@ -67,18 +67,17 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts statsOptions, ser if err != nil { return err } - filter := []filters.KeyValuePair{ - filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, name)), - } + f := client.Filters{} + f.Add("label", fmt.Sprintf("%s=%s", api.ProjectLabel, name)) + if len(service) > 0 { - filter = append(filter, filters.Arg("label", fmt.Sprintf("%s=%s", api.ServiceLabel, service[0]))) + f.Add("label", fmt.Sprintf("%s=%s", api.ServiceLabel, service[0])) } - args := filters.NewArgs(filter...) return container.RunStats(ctx, dockerCli, &container.StatsOptions{ All: opts.all, NoStream: opts.noStream, NoTrunc: opts.noTrunc, Format: opts.format, - Filters: &args, + Filters: f, }) } diff --git a/cmd/formatter/container.go b/cmd/formatter/container.go index e8e331b805..fed0249c59 100644 --- a/cmd/formatter/container.go +++ b/cmd/formatter/container.go @@ -18,15 +18,16 @@ package formatter import ( "fmt" + "net/netip" "strconv" "strings" "time" "github.com/docker/cli/cli/command/formatter" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/stringid" "github.com/docker/go-units" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client/pkg/stringid" ) const ( @@ -212,10 +213,14 @@ func (c *ContainerContext) Publishers() api.PortPublishers { } func (c *ContainerContext) Ports() string { - var ports []container.Port + var ports []container.PortSummary for _, publisher := range c.c.Publishers { - ports = append(ports, container.Port{ - IP: publisher.URL, + var pIP netip.Addr + if publisher.URL != "" { + pIP, _ = netip.ParseAddr(publisher.URL) + } + ports = append(ports, container.PortSummary{ + IP: pIP, PrivatePort: uint16(publisher.TargetPort), PublicPort: uint16(publisher.PublishedPort), Type: publisher.Protocol, diff --git a/cmd/formatter/logs.go b/cmd/formatter/logs.go index 430cf1b039..b3bf49d154 100644 --- a/cmd/formatter/logs.go +++ b/cmd/formatter/logs.go @@ -27,7 +27,7 @@ import ( "github.com/buger/goterm" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/pkg/jsonmessage" + "github.com/moby/moby/client/pkg/jsonmessage" ) // LogConsumer consume logs from services and format them diff --git a/go.mod b/go.mod index 0cd8f7a7b6..dc05b9cfa4 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,11 @@ module github.com/docker/compose/v2 go 1.24.9 +replace github.com/docker/buildx => github.com/thaJeztah/buildx v0.2.1-0.20251014131213-dc504d137a66 // https://github.com/docker/buildx/pull/3326 + +// Need a replace, because master pseudo-version is considered "older" than the 28.x branch +replace github.com/docker/cli => github.com/docker/cli v29.0.0-rc.1.0.20251014130057-171a9b70b273+incompatible // master (v29.0.0-dev) + require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e @@ -15,7 +20,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/distribution/reference v0.6.0 github.com/docker/buildx v0.29.1 - github.com/docker/cli v28.5.1+incompatible + github.com/docker/cli v29.0.0-rc.1.0.20251014130057-171a9b70b273+incompatible // master (v29.0.0-dev) github.com/docker/cli-docs-tool v0.10.0 github.com/docker/docker v28.5.1+incompatible github.com/docker/go-connections v0.6.0 @@ -30,6 +35,8 @@ require ( github.com/mitchellh/go-ps v1.0.0 github.com/moby/buildkit v0.25.1 github.com/moby/go-archive v0.1.0 + github.com/moby/moby/api v1.52.0-beta.2 + github.com/moby/moby/client v0.1.0-beta.2 github.com/moby/patternmatcher v0.6.0 github.com/moby/sys/atomicwriter v0.1.0 github.com/moby/term v0.5.2 diff --git a/go.sum b/go.sum index 807b1e602e..b6be7518e4 100644 --- a/go.sum +++ b/go.sum @@ -126,10 +126,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/buildx v0.29.1 h1:58hxM5Z4mnNje3G5NKfULT9xCr8ooM8XFtlfUK9bKaA= -github.com/docker/buildx v0.29.1/go.mod h1:J4EFv6oxlPiV1MjO0VyJx2u5tLM7ImDEl9zyB8d4wPI= -github.com/docker/cli v28.5.1+incompatible h1:ESutzBALAD6qyCLqbQSEf1a/U8Ybms5agw59yGVc+yY= -github.com/docker/cli v28.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.0.0-rc.1.0.20251014130057-171a9b70b273+incompatible h1:G2VeAxjFsbWMhTgf2qE908e32M040txrCkHYzsYCRTo= +github.com/docker/cli v29.0.0-rc.1.0.20251014130057-171a9b70b273+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU= github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -324,6 +322,10 @@ github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/moby/api v1.52.0-beta.2 h1:cuilbu4cLBZnlNpJXuv3QTleOxgo3kGqkNGt3ICe1yY= +github.com/moby/moby/api v1.52.0-beta.2/go.mod h1:/ou52HkRydg4+odrUR3vFsGgjIyHvprrpEQEkweL10s= +github.com/moby/moby/client v0.1.0-beta.2 h1:Uy7JhcAOvQAQriowODpHaAJokfw/AhUya0216sk1hAk= +github.com/moby/moby/client v0.1.0-beta.2/go.mod h1:yYEv2G6pYi8u63ga0zlU9KsM7DpoGXubtMaZMJE7/dw= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= @@ -470,6 +472,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/thaJeztah/buildx v0.2.1-0.20251014131213-dc504d137a66 h1:GPS+PcI1H6ykqHO2YaaGw2ZiTbSHrEFMGPK+nNdbHsU= +github.com/thaJeztah/buildx v0.2.1-0.20251014131213-dc504d137a66/go.mod h1:SVX7uR2LLY2hMOcI2lOTb/S/9nvbbkdY2yfPIcvXiZk= github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA= @@ -668,6 +672,8 @@ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= diff --git a/internal/sync/tar.go b/internal/sync/tar.go index 4250b6afc4..216155e44c 100644 --- a/internal/sync/tar.go +++ b/internal/sync/tar.go @@ -31,8 +31,8 @@ import ( "strings" "sync" - "github.com/docker/docker/api/types/container" "github.com/moby/go-archive" + "github.com/moby/moby/api/types/container" "golang.org/x/sync/errgroup" ) diff --git a/internal/tracing/attributes.go b/internal/tracing/attributes.go index 2c8779bc86..8957009150 100644 --- a/internal/tracing/attributes.go +++ b/internal/tracing/attributes.go @@ -25,7 +25,7 @@ import ( "time" "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/api/api.go b/pkg/api/api.go index c82c8618a4..e698df6ed0 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -27,7 +27,7 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/platforms" "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/volume" ) // Service manages a compose project diff --git a/pkg/api/dryrunclient.go b/pkg/api/dryrunclient.go index b7e623652b..46b7b496c4 100644 --- a/pkg/api/dryrunclient.go +++ b/pkg/api/dryrunclient.go @@ -25,7 +25,6 @@ import ( "fmt" "io" "net" - "net/http" "runtime" "strings" "sync" @@ -33,20 +32,19 @@ import ( "github.com/docker/buildx/builder" "github.com/docker/buildx/util/imagetools" "github.com/docker/cli/cli/command" - moby "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/build" - "github.com/docker/docker/api/types/checkpoint" - containerType "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/system" - "github.com/docker/docker/api/types/volume" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/jsonmessage" + moby "github.com/moby/moby/api/types" + containerType "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/events" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/jsonstream" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/api/types/plugin" + "github.com/moby/moby/api/types/registry" + "github.com/moby/moby/api/types/swarm" + "github.com/moby/moby/api/types/system" + "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" specs "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -97,8 +95,8 @@ func getCallingFunction() string { // All methods and functions which need to be overridden for dry run. -func (d *DryRunClient) ContainerAttach(ctx context.Context, container string, options containerType.AttachOptions) (moby.HijackedResponse, error) { - return moby.HijackedResponse{}, errors.New("interactive run is not supported in dry-run mode") +func (d *DryRunClient) ContainerAttach(ctx context.Context, container string, options client.ContainerAttachOptions) (client.HijackedResponse, error) { + return client.HijackedResponse{}, errors.New("interactive run is not supported in dry-run mode") } func (d *DryRunClient) ContainerCreate(ctx context.Context, config *containerType.Config, hostConfig *containerType.HostConfig, @@ -126,14 +124,12 @@ func (d *DryRunClient) ContainerInspect(ctx context.Context, container string) ( } } return containerType.InspectResponse{ - ContainerJSONBase: &containerType.ContainerJSONBase{ - ID: id, - Name: container, - State: &containerType.State{ - Status: containerType.StateRunning, // needed for --wait option - Health: &containerType.Health{ - Status: containerType.Healthy, // needed for healthcheck control - }, + ID: id, + Name: container, + State: &containerType.State{ + Status: containerType.StateRunning, // needed for --wait option + Health: &containerType.Health{ + Status: containerType.Healthy, // needed for healthcheck control }, }, Mounts: nil, @@ -148,7 +144,7 @@ func (d *DryRunClient) ContainerKill(ctx context.Context, container, signal stri return nil } -func (d *DryRunClient) ContainerList(ctx context.Context, options containerType.ListOptions) ([]containerType.Summary, error) { +func (d *DryRunClient) ContainerList(ctx context.Context, options client.ContainerListOptions) ([]containerType.Summary, error) { caller := getCallingFunction() switch caller { case "start": @@ -167,7 +163,7 @@ func (d *DryRunClient) ContainerPause(ctx context.Context, container string) err return nil } -func (d *DryRunClient) ContainerRemove(ctx context.Context, container string, options containerType.RemoveOptions) error { +func (d *DryRunClient) ContainerRemove(ctx context.Context, container string, options client.ContainerRemoveOptions) error { return nil } @@ -175,15 +171,15 @@ func (d *DryRunClient) ContainerRename(ctx context.Context, container, newContai return nil } -func (d *DryRunClient) ContainerRestart(ctx context.Context, container string, options containerType.StopOptions) error { +func (d *DryRunClient) ContainerRestart(ctx context.Context, container string, options client.ContainerStopOptions) error { return nil } -func (d *DryRunClient) ContainerStart(ctx context.Context, container string, options containerType.StartOptions) error { +func (d *DryRunClient) ContainerStart(ctx context.Context, container string, options client.ContainerStartOptions) error { return nil } -func (d *DryRunClient) ContainerStop(ctx context.Context, container string, options containerType.StopOptions) error { +func (d *DryRunClient) ContainerStop(ctx context.Context, container string, options client.ContainerStopOptions) error { return nil } @@ -199,25 +195,26 @@ func (d *DryRunClient) CopyFromContainer(ctx context.Context, container, srcPath return rc, containerType.PathStat{}, nil } -func (d *DryRunClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options containerType.CopyToContainerOptions) error { +func (d *DryRunClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options client.CopyToContainerOptions) error { if _, err := d.ContainerStatPath(ctx, container, path); err != nil { return fmt.Errorf(" %s Could not find the file %s in container %s", DRYRUN_PREFIX, path, container) } return nil } -func (d *DryRunClient) ImageBuild(ctx context.Context, reader io.Reader, options build.ImageBuildOptions) (build.ImageBuildResponse, error) { +func (d *DryRunClient) ImageBuild(ctx context.Context, reader io.Reader, options client.ImageBuildOptions) (client.ImageBuildResponse, error) { + // TODO(thaJeztah): can we use api/types/jsonstream (or api/pkg/xxxxx) for this? jsonMessage, err := json.Marshal(&jsonmessage.JSONMessage{ Status: fmt.Sprintf("%[1]sSuccessfully built: dryRunID\n%[1]sSuccessfully tagged: %[2]s\n", DRYRUN_PREFIX, options.Tags[0]), Progress: &jsonmessage.JSONProgress{}, ID: "", }) if err != nil { - return build.ImageBuildResponse{}, err + return client.ImageBuildResponse{}, err } rc := io.NopCloser(bytes.NewReader(jsonMessage)) - return build.ImageBuildResponse{ + return client.ImageBuildResponse{ Body: rc, }, nil } @@ -242,26 +239,29 @@ func (d *DryRunClient) ImageInspectWithRaw(ctx context.Context, imageName string return resp, buf.Bytes(), err } -func (d *DryRunClient) ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ImagePull(ctx context.Context, ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) { if _, _, err := d.resolver.Resolve(ctx, ref); err != nil { - return nil, err + return client.ImagePullResponse{}, err } - rc := io.NopCloser(strings.NewReader("")) - return rc, nil + return client.ImagePullResponse{}, nil } -func (d *DryRunClient) ImagePush(ctx context.Context, ref string, options image.PushOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ImagePush(ctx context.Context, ref string, options client.ImagePushOptions) (io.ReadCloser, error) { if _, _, err := d.resolver.Resolve(ctx, ref); err != nil { return nil, err } + + // TODO(thaJeztah): can we use api/types/jsonstream (or api/pkg/xxxxx) for this? jsonMessage, err := json.Marshal(&jsonmessage.JSONMessage{ Status: "Pushed", Progress: &jsonmessage.JSONProgress{ - Current: 100, - Total: 100, - Start: 0, - HideCounts: false, - Units: "Mb", + Progress: jsonstream.Progress{ + Current: 100, + Total: 100, + Start: 0, + HideCounts: false, + Units: "Mb", + }, }, ID: ref, }) @@ -272,7 +272,7 @@ func (d *DryRunClient) ImagePush(ctx context.Context, ref string, options image. return rc, nil } -func (d *DryRunClient) ImageRemove(ctx context.Context, imageName string, options image.RemoveOptions) ([]image.DeleteResponse, error) { +func (d *DryRunClient) ImageRemove(ctx context.Context, imageName string, options client.ImageRemoveOptions) ([]image.DeleteResponse, error) { return nil, nil } @@ -280,7 +280,7 @@ func (d *DryRunClient) NetworkConnect(ctx context.Context, networkName, containe return nil } -func (d *DryRunClient) NetworkCreate(ctx context.Context, name string, options network.CreateOptions) (network.CreateResponse, error) { +func (d *DryRunClient) NetworkCreate(ctx context.Context, name string, options client.NetworkCreateOptions) (network.CreateResponse, error) { return network.CreateResponse{ ID: name, Warning: "", @@ -309,7 +309,7 @@ func (d *DryRunClient) VolumeRemove(ctx context.Context, volumeID string, force return nil } -func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string, config containerType.ExecOptions) (containerType.ExecCreateResponse, error) { +func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string, config client.ExecCreateOptions) (containerType.ExecCreateResponse, error) { b := make([]byte, 32) _, _ = rand.Read(b) id := fmt.Sprintf("%x", b) @@ -322,7 +322,7 @@ func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string }, nil } -func (d *DryRunClient) ContainerExecStart(ctx context.Context, execID string, config containerType.ExecStartOptions) error { +func (d *DryRunClient) ContainerExecStart(ctx context.Context, execID string, config client.ExecStartOptions) error { v, ok := d.execs.LoadAndDelete(execID) if !ok { return fmt.Errorf("invalid exec ID %q", execID) @@ -334,7 +334,7 @@ func (d *DryRunClient) ContainerExecStart(ctx context.Context, execID string, co // Functions delegated to original APIClient (not used by Compose or not modifying the Compose stack -func (d *DryRunClient) ConfigList(ctx context.Context, options swarm.ConfigListOptions) ([]swarm.Config, error) { +func (d *DryRunClient) ConfigList(ctx context.Context, options client.ConfigListOptions) ([]swarm.Config, error) { return d.apiClient.ConfigList(ctx, options) } @@ -354,7 +354,7 @@ func (d *DryRunClient) ConfigUpdate(ctx context.Context, id string, version swar return d.apiClient.ConfigUpdate(ctx, id, version, config) } -func (d *DryRunClient) ContainerCommit(ctx context.Context, container string, options containerType.CommitOptions) (containerType.CommitResponse, error) { +func (d *DryRunClient) ContainerCommit(ctx context.Context, container string, options client.ContainerCommitOptions) (containerType.CommitResponse, error) { return d.apiClient.ContainerCommit(ctx, container, options) } @@ -362,15 +362,15 @@ func (d *DryRunClient) ContainerDiff(ctx context.Context, container string) ([]c return d.apiClient.ContainerDiff(ctx, container) } -func (d *DryRunClient) ContainerExecAttach(ctx context.Context, execID string, config containerType.ExecStartOptions) (moby.HijackedResponse, error) { - return moby.HijackedResponse{}, errors.New("interactive exec is not supported in dry-run mode") +func (d *DryRunClient) ContainerExecAttach(ctx context.Context, execID string, config client.ExecStartOptions) (client.HijackedResponse, error) { + return client.HijackedResponse{}, errors.New("interactive exec is not supported in dry-run mode") } -func (d *DryRunClient) ContainerExecInspect(ctx context.Context, execID string) (containerType.ExecInspect, error) { +func (d *DryRunClient) ContainerExecInspect(ctx context.Context, execID string) (client.ExecInspect, error) { return d.apiClient.ContainerExecInspect(ctx, execID) } -func (d *DryRunClient) ContainerExecResize(ctx context.Context, execID string, options containerType.ResizeOptions) error { +func (d *DryRunClient) ContainerExecResize(ctx context.Context, execID string, options client.ContainerResizeOptions) error { return d.apiClient.ContainerExecResize(ctx, execID, options) } @@ -382,11 +382,11 @@ func (d *DryRunClient) ContainerInspectWithRaw(ctx context.Context, container st return d.apiClient.ContainerInspectWithRaw(ctx, container, getSize) } -func (d *DryRunClient) ContainerLogs(ctx context.Context, container string, options containerType.LogsOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ContainerLogs(ctx context.Context, container string, options client.ContainerLogsOptions) (io.ReadCloser, error) { return d.apiClient.ContainerLogs(ctx, container, options) } -func (d *DryRunClient) ContainerResize(ctx context.Context, container string, options containerType.ResizeOptions) error { +func (d *DryRunClient) ContainerResize(ctx context.Context, container string, options client.ContainerResizeOptions) error { return d.apiClient.ContainerResize(ctx, container, options) } @@ -394,11 +394,11 @@ func (d *DryRunClient) ContainerStatPath(ctx context.Context, container, path st return d.apiClient.ContainerStatPath(ctx, container, path) } -func (d *DryRunClient) ContainerStats(ctx context.Context, container string, stream bool) (containerType.StatsResponseReader, error) { +func (d *DryRunClient) ContainerStats(ctx context.Context, container string, stream bool) (client.StatsResponseReader, error) { return d.apiClient.ContainerStats(ctx, container, stream) } -func (d *DryRunClient) ContainerStatsOneShot(ctx context.Context, container string) (containerType.StatsResponseReader, error) { +func (d *DryRunClient) ContainerStatsOneShot(ctx context.Context, container string) (client.StatsResponseReader, error) { return d.apiClient.ContainerStatsOneShot(ctx, container) } @@ -414,7 +414,7 @@ func (d *DryRunClient) ContainerWait(ctx context.Context, container string, cond return d.apiClient.ContainerWait(ctx, container, condition) } -func (d *DryRunClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (containerType.PruneReport, error) { +func (d *DryRunClient) ContainersPrune(ctx context.Context, pruneFilters client.Filters) (containerType.PruneReport, error) { return d.apiClient.ContainersPrune(ctx, pruneFilters) } @@ -422,15 +422,15 @@ func (d *DryRunClient) DistributionInspect(ctx context.Context, imageName, encod return d.apiClient.DistributionInspect(ctx, imageName, encodedRegistryAuth) } -func (d *DryRunClient) BuildCachePrune(ctx context.Context, opts build.CachePruneOptions) (*build.CachePruneReport, error) { +func (d *DryRunClient) BuildCachePrune(ctx context.Context, opts client.BuildCachePruneOptions) (client.BuildCachePruneResult, error) { return d.apiClient.BuildCachePrune(ctx, opts) } -func (d *DryRunClient) BuildCancel(ctx context.Context, id string) error { - return d.apiClient.BuildCancel(ctx, id) +func (d *DryRunClient) BuildCancel(ctx context.Context, id string, opts client.BuildCancelOptions) error { + return d.apiClient.BuildCancel(ctx, id, opts) } -func (d *DryRunClient) ImageCreate(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ImageCreate(ctx context.Context, parentReference string, options client.ImageCreateOptions) (io.ReadCloser, error) { return d.apiClient.ImageCreate(ctx, parentReference, options) } @@ -438,19 +438,19 @@ func (d *DryRunClient) ImageHistory(ctx context.Context, imageName string, optio return d.apiClient.ImageHistory(ctx, imageName, options...) } -func (d *DryRunClient) ImageImport(ctx context.Context, source image.ImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ImageImport(ctx context.Context, source client.ImageImportSource, ref string, options client.ImageImportOptions) (io.ReadCloser, error) { return d.apiClient.ImageImport(ctx, source, ref, options) } -func (d *DryRunClient) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) { +func (d *DryRunClient) ImageList(ctx context.Context, options client.ImageListOptions) ([]image.Summary, error) { return d.apiClient.ImageList(ctx, options) } -func (d *DryRunClient) ImageLoad(ctx context.Context, input io.Reader, options ...client.ImageLoadOption) (image.LoadResponse, error) { +func (d *DryRunClient) ImageLoad(ctx context.Context, input io.Reader, options ...client.ImageLoadOption) (client.LoadResponse, error) { return d.apiClient.ImageLoad(ctx, input, options...) } -func (d *DryRunClient) ImageSearch(ctx context.Context, term string, options registry.SearchOptions) ([]registry.SearchResult, error) { +func (d *DryRunClient) ImageSearch(ctx context.Context, term string, options client.ImageSearchOptions) ([]registry.SearchResult, error) { return d.apiClient.ImageSearch(ctx, term, options) } @@ -462,7 +462,7 @@ func (d *DryRunClient) ImageTag(ctx context.Context, imageName, ref string) erro return d.apiClient.ImageTag(ctx, imageName, ref) } -func (d *DryRunClient) ImagesPrune(ctx context.Context, pruneFilter filters.Args) (image.PruneReport, error) { +func (d *DryRunClient) ImagesPrune(ctx context.Context, pruneFilter client.Filters) (image.PruneReport, error) { return d.apiClient.ImagesPrune(ctx, pruneFilter) } @@ -470,11 +470,11 @@ func (d *DryRunClient) NodeInspectWithRaw(ctx context.Context, nodeID string) (s return d.apiClient.NodeInspectWithRaw(ctx, nodeID) } -func (d *DryRunClient) NodeList(ctx context.Context, options swarm.NodeListOptions) ([]swarm.Node, error) { +func (d *DryRunClient) NodeList(ctx context.Context, options client.NodeListOptions) ([]swarm.Node, error) { return d.apiClient.NodeList(ctx, options) } -func (d *DryRunClient) NodeRemove(ctx context.Context, nodeID string, options swarm.NodeRemoveOptions) error { +func (d *DryRunClient) NodeRemove(ctx context.Context, nodeID string, options client.NodeRemoveOptions) error { return d.apiClient.NodeRemove(ctx, nodeID, options) } @@ -482,43 +482,43 @@ func (d *DryRunClient) NodeUpdate(ctx context.Context, nodeID string, version sw return d.apiClient.NodeUpdate(ctx, nodeID, version, node) } -func (d *DryRunClient) NetworkInspect(ctx context.Context, networkName string, options network.InspectOptions) (network.Inspect, error) { +func (d *DryRunClient) NetworkInspect(ctx context.Context, networkName string, options client.NetworkInspectOptions) (network.Inspect, error) { return d.apiClient.NetworkInspect(ctx, networkName, options) } -func (d *DryRunClient) NetworkInspectWithRaw(ctx context.Context, networkName string, options network.InspectOptions) (network.Inspect, []byte, error) { +func (d *DryRunClient) NetworkInspectWithRaw(ctx context.Context, networkName string, options client.NetworkInspectOptions) (network.Inspect, []byte, error) { return d.apiClient.NetworkInspectWithRaw(ctx, networkName, options) } -func (d *DryRunClient) NetworkList(ctx context.Context, options network.ListOptions) ([]network.Inspect, error) { +func (d *DryRunClient) NetworkList(ctx context.Context, options client.NetworkListOptions) ([]network.Summary, error) { return d.apiClient.NetworkList(ctx, options) } -func (d *DryRunClient) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (network.PruneReport, error) { +func (d *DryRunClient) NetworksPrune(ctx context.Context, pruneFilter client.Filters) (network.PruneReport, error) { return d.apiClient.NetworksPrune(ctx, pruneFilter) } -func (d *DryRunClient) PluginList(ctx context.Context, filter filters.Args) (moby.PluginsListResponse, error) { +func (d *DryRunClient) PluginList(ctx context.Context, filter client.Filters) (plugin.ListResponse, error) { return d.apiClient.PluginList(ctx, filter) } -func (d *DryRunClient) PluginRemove(ctx context.Context, name string, options moby.PluginRemoveOptions) error { +func (d *DryRunClient) PluginRemove(ctx context.Context, name string, options client.PluginRemoveOptions) error { return d.apiClient.PluginRemove(ctx, name, options) } -func (d *DryRunClient) PluginEnable(ctx context.Context, name string, options moby.PluginEnableOptions) error { +func (d *DryRunClient) PluginEnable(ctx context.Context, name string, options client.PluginEnableOptions) error { return d.apiClient.PluginEnable(ctx, name, options) } -func (d *DryRunClient) PluginDisable(ctx context.Context, name string, options moby.PluginDisableOptions) error { +func (d *DryRunClient) PluginDisable(ctx context.Context, name string, options client.PluginDisableOptions) error { return d.apiClient.PluginDisable(ctx, name, options) } -func (d *DryRunClient) PluginInstall(ctx context.Context, name string, options moby.PluginInstallOptions) (io.ReadCloser, error) { +func (d *DryRunClient) PluginInstall(ctx context.Context, name string, options client.PluginInstallOptions) (io.ReadCloser, error) { return d.apiClient.PluginInstall(ctx, name, options) } -func (d *DryRunClient) PluginUpgrade(ctx context.Context, name string, options moby.PluginInstallOptions) (io.ReadCloser, error) { +func (d *DryRunClient) PluginUpgrade(ctx context.Context, name string, options client.PluginInstallOptions) (io.ReadCloser, error) { return d.apiClient.PluginUpgrade(ctx, name, options) } @@ -530,23 +530,23 @@ func (d *DryRunClient) PluginSet(ctx context.Context, name string, args []string return d.apiClient.PluginSet(ctx, name, args) } -func (d *DryRunClient) PluginInspectWithRaw(ctx context.Context, name string) (*moby.Plugin, []byte, error) { +func (d *DryRunClient) PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) { return d.apiClient.PluginInspectWithRaw(ctx, name) } -func (d *DryRunClient) PluginCreate(ctx context.Context, createContext io.Reader, options moby.PluginCreateOptions) error { +func (d *DryRunClient) PluginCreate(ctx context.Context, createContext io.Reader, options client.PluginCreateOptions) error { return d.apiClient.PluginCreate(ctx, createContext, options) } -func (d *DryRunClient) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options swarm.ServiceCreateOptions) (swarm.ServiceCreateResponse, error) { +func (d *DryRunClient) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options client.ServiceCreateOptions) (swarm.ServiceCreateResponse, error) { return d.apiClient.ServiceCreate(ctx, service, options) } -func (d *DryRunClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options swarm.ServiceInspectOptions) (swarm.Service, []byte, error) { +func (d *DryRunClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options client.ServiceInspectOptions) (swarm.Service, []byte, error) { return d.apiClient.ServiceInspectWithRaw(ctx, serviceID, options) } -func (d *DryRunClient) ServiceList(ctx context.Context, options swarm.ServiceListOptions) ([]swarm.Service, error) { +func (d *DryRunClient) ServiceList(ctx context.Context, options client.ServiceListOptions) ([]swarm.Service, error) { return d.apiClient.ServiceList(ctx, options) } @@ -554,15 +554,15 @@ func (d *DryRunClient) ServiceRemove(ctx context.Context, serviceID string) erro return d.apiClient.ServiceRemove(ctx, serviceID) } -func (d *DryRunClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options swarm.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { - return d.apiClient.ServiceUpdate(ctx, serviceID, version, service, options) +func (d *DryRunClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, spec swarm.ServiceSpec, options client.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { + return d.apiClient.ServiceUpdate(ctx, serviceID, version, spec, options) } -func (d *DryRunClient) ServiceLogs(ctx context.Context, serviceID string, options containerType.LogsOptions) (io.ReadCloser, error) { +func (d *DryRunClient) ServiceLogs(ctx context.Context, serviceID string, options client.ContainerLogsOptions) (io.ReadCloser, error) { return d.apiClient.ServiceLogs(ctx, serviceID, options) } -func (d *DryRunClient) TaskLogs(ctx context.Context, taskID string, options containerType.LogsOptions) (io.ReadCloser, error) { +func (d *DryRunClient) TaskLogs(ctx context.Context, taskID string, options client.ContainerLogsOptions) (io.ReadCloser, error) { return d.apiClient.TaskLogs(ctx, taskID, options) } @@ -570,7 +570,7 @@ func (d *DryRunClient) TaskInspectWithRaw(ctx context.Context, taskID string) (s return d.apiClient.TaskInspectWithRaw(ctx, taskID) } -func (d *DryRunClient) TaskList(ctx context.Context, options swarm.TaskListOptions) ([]swarm.Task, error) { +func (d *DryRunClient) TaskList(ctx context.Context, options client.TaskListOptions) ([]swarm.Task, error) { return d.apiClient.TaskList(ctx, options) } @@ -598,11 +598,11 @@ func (d *DryRunClient) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { return d.apiClient.SwarmInspect(ctx) } -func (d *DryRunClient) SwarmUpdate(ctx context.Context, version swarm.Version, swarmSpec swarm.Spec, flags swarm.UpdateFlags) error { +func (d *DryRunClient) SwarmUpdate(ctx context.Context, version swarm.Version, swarmSpec swarm.Spec, flags client.SwarmUpdateFlags) error { return d.apiClient.SwarmUpdate(ctx, version, swarmSpec, flags) } -func (d *DryRunClient) SecretList(ctx context.Context, options swarm.SecretListOptions) ([]swarm.Secret, error) { +func (d *DryRunClient) SecretList(ctx context.Context, options client.SecretListOptions) ([]swarm.Secret, error) { return d.apiClient.SecretList(ctx, options) } @@ -622,7 +622,7 @@ func (d *DryRunClient) SecretUpdate(ctx context.Context, id string, version swar return d.apiClient.SecretUpdate(ctx, id, version, secret) } -func (d *DryRunClient) Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error) { +func (d *DryRunClient) Events(ctx context.Context, options client.EventsListOptions) (<-chan events.Message, <-chan error) { return d.apiClient.Events(ctx, options) } @@ -634,7 +634,7 @@ func (d *DryRunClient) RegistryLogin(ctx context.Context, auth registry.AuthConf return d.apiClient.RegistryLogin(ctx, auth) } -func (d *DryRunClient) DiskUsage(ctx context.Context, options moby.DiskUsageOptions) (moby.DiskUsage, error) { +func (d *DryRunClient) DiskUsage(ctx context.Context, options client.DiskUsageOptions) (system.DiskUsage, error) { return d.apiClient.DiskUsage(ctx, options) } @@ -650,11 +650,11 @@ func (d *DryRunClient) VolumeInspectWithRaw(ctx context.Context, volumeID string return d.apiClient.VolumeInspectWithRaw(ctx, volumeID) } -func (d *DryRunClient) VolumeList(ctx context.Context, opts volume.ListOptions) (volume.ListResponse, error) { +func (d *DryRunClient) VolumeList(ctx context.Context, opts client.VolumeListOptions) (volume.ListResponse, error) { return d.apiClient.VolumeList(ctx, opts) } -func (d *DryRunClient) VolumesPrune(ctx context.Context, pruneFilter filters.Args) (volume.PruneReport, error) { +func (d *DryRunClient) VolumesPrune(ctx context.Context, pruneFilter client.Filters) (volume.PruneReport, error) { return d.apiClient.VolumesPrune(ctx, pruneFilter) } @@ -670,10 +670,6 @@ func (d *DryRunClient) DaemonHost() string { return d.apiClient.DaemonHost() } -func (d *DryRunClient) HTTPClient() *http.Client { - return d.apiClient.HTTPClient() -} - func (d *DryRunClient) ServerVersion(ctx context.Context) (moby.Version, error) { return d.apiClient.ServerVersion(ctx) } @@ -698,14 +694,14 @@ func (d *DryRunClient) Close() error { return d.apiClient.Close() } -func (d *DryRunClient) CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error { +func (d *DryRunClient) CheckpointCreate(ctx context.Context, container string, options client.CheckpointCreateOptions) error { return d.apiClient.CheckpointCreate(ctx, container, options) } -func (d *DryRunClient) CheckpointDelete(ctx context.Context, container string, options checkpoint.DeleteOptions) error { +func (d *DryRunClient) CheckpointDelete(ctx context.Context, container string, options client.CheckpointDeleteOptions) error { return d.apiClient.CheckpointDelete(ctx, container, options) } -func (d *DryRunClient) CheckpointList(ctx context.Context, container string, options checkpoint.ListOptions) ([]checkpoint.Summary, error) { +func (d *DryRunClient) CheckpointList(ctx context.Context, container string, options client.CheckpointListOptions) (client.CheckpointListResult, error) { return d.apiClient.CheckpointList(ctx, container, options) } diff --git a/pkg/bridge/convert.go b/pkg/bridge/convert.go index 8e9995b824..ded4bfbec4 100644 --- a/pkg/bridge/convert.go +++ b/pkg/bridge/convert.go @@ -32,11 +32,12 @@ import ( cli "github.com/docker/cli/cli/command/container" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/utils" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" "gopkg.in/yaml.v3" ) @@ -206,13 +207,14 @@ func inspectWithPull(ctx context.Context, dockerCli command.Cli, imageName strin inspect, err := dockerCli.Client().ImageInspect(ctx, imageName) if errdefs.IsNotFound(err) { var stream io.ReadCloser - stream, err = dockerCli.Client().ImagePull(ctx, imageName, image.PullOptions{}) + stream, err = dockerCli.Client().ImagePull(ctx, imageName, client.ImagePullOptions{}) if err != nil { return image.InspectResponse{}, err } defer func() { _ = stream.Close() }() - err = jsonmessage.DisplayJSONMessagesToStream(stream, dockerCli.Out(), nil) + out := dockerCli.Out() + err = jsonmessage.DisplayJSONMessagesStream(stream, out, out.FD(), out.IsTerminal(), nil) if err != nil { return image.InspectResponse{}, err } diff --git a/pkg/bridge/transformers.go b/pkg/bridge/transformers.go index dbf4fc6d9d..7df97fa8a4 100644 --- a/pkg/bridge/transformers.go +++ b/pkg/bridge/transformers.go @@ -23,11 +23,11 @@ import ( "path/filepath" "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" "github.com/moby/go-archive" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" ) const ( @@ -69,7 +69,7 @@ func CreateTransformer(ctx context.Context, dockerCli command.Cli, options Creat Image: options.From, }, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") defer func() { - _ = dockerCli.Client().ContainerRemove(context.Background(), created.ID, container.RemoveOptions{Force: true}) + _ = dockerCli.Client().ContainerRemove(context.Background(), created.ID, client.ContainerRemoveOptions{Force: true}) }() if err != nil { @@ -112,9 +112,7 @@ COPY templates /templates func ListTransformers(ctx context.Context, dockerCli command.Cli) ([]image.Summary, error) { api := dockerCli.Client() - return api.ImageList(ctx, image.ListOptions{ - Filters: filters.NewArgs( - filters.Arg("label", fmt.Sprintf("%s=%s", TransformerLabel, "transformation")), - ), + return api.ImageList(ctx, client.ImageListOptions{ + Filters: make(client.Filters).Add("label", fmt.Sprintf("%s=%s", TransformerLabel, "transformation")), }) } diff --git a/pkg/compose/attach.go b/pkg/compose/attach.go index 897c473317..19f975ae43 100644 --- a/pkg/compose/attach.go +++ b/pkg/compose/attach.go @@ -25,8 +25,9 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/docker/cli/cli/streams" - containerType "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/stdcopy" + "github.com/moby/moby/api/pkg/stdcopy" + containerType "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/moby/term" "github.com/docker/compose/v2/pkg/api" @@ -151,7 +152,7 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.WriteCloser, io.ReadCloser, error) { var stdout io.ReadCloser var stdin io.WriteCloser - cnx, err := s.apiClient().ContainerAttach(ctx, container, containerType.AttachOptions{ + cnx, err := s.apiClient().ContainerAttach(ctx, container, client.ContainerAttachOptions{ Stream: true, Stdin: true, Stdout: true, @@ -165,7 +166,7 @@ func (s *composeService) getContainerStreams(ctx context.Context, container stri } // Fallback to logs API - logs, err := s.apiClient().ContainerLogs(ctx, container, containerType.LogsOptions{ + logs, err := s.apiClient().ContainerLogs(ctx, container, client.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, diff --git a/pkg/compose/build.go b/pkg/compose/build.go index 4fa3fa3097..b5702e5fec 100644 --- a/pkg/compose/build.go +++ b/pkg/compose/build.go @@ -38,7 +38,6 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" "github.com/docker/compose/v2/pkg/utils" - "github.com/docker/docker/api/types/container" bclient "github.com/moby/buildkit/client" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/auth/authprovider" @@ -46,6 +45,7 @@ import ( "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/progress/progressui" + "github.com/moby/moby/api/types/container" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" "go.opentelemetry.io/otel/attribute" diff --git a/pkg/compose/build_bake.go b/pkg/compose/build_bake.go index 299c6f2f43..4817b333c1 100644 --- a/pkg/compose/build_bake.go +++ b/pkg/compose/build_bake.go @@ -37,7 +37,7 @@ import ( "github.com/containerd/errdefs" "github.com/docker/cli/cli-plugins/manager" "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image/build" + buildpkg "github.com/docker/cli/cli/command/image/build" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" "github.com/moby/buildkit/client" @@ -501,7 +501,7 @@ func dockerFilePath(ctxName string, dockerfile string) string { if dockerfile == "" { return "" } - if contextType, _ := build.DetectContextType(ctxName); contextType == build.ContextTypeGit { + if contextType, _ := buildpkg.DetectContextType(ctxName); contextType == buildpkg.ContextTypeGit { return dockerfile } if !filepath.IsAbs(dockerfile) { diff --git a/pkg/compose/build_classic.go b/pkg/compose/build_classic.go index a84929193e..ef51805b63 100644 --- a/pkg/compose/build_classic.go +++ b/pkg/compose/build_classic.go @@ -31,13 +31,15 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/image/build" "github.com/docker/compose/v2/pkg/api" - buildtypes "github.com/docker/docker/api/types/build" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" "github.com/moby/go-archive" + "github.com/moby/moby/api/pkg/progress" + "github.com/moby/moby/api/pkg/streamformatter" + buildtypes "github.com/moby/moby/api/types/build" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/jsonstream" + "github.com/moby/moby/api/types/registry" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" "github.com/sirupsen/logrus" ) @@ -202,7 +204,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, progBuff.FD(), true, aux) if err != nil { - var jerr *jsonmessage.JSONError + var jerr *jsonstream.Error if errors.As(err, &jerr) { // If no error code is set, default to 1 if jerr.Code == 0 { @@ -215,9 +217,9 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj return imageID, nil } -func imageBuildOptions(dockerCli command.Cli, project *types.Project, service types.ServiceConfig, options api.BuildOptions) buildtypes.ImageBuildOptions { +func imageBuildOptions(dockerCli command.Cli, project *types.Project, service types.ServiceConfig, options api.BuildOptions) client.ImageBuildOptions { config := service.Build - return buildtypes.ImageBuildOptions{ + return client.ImageBuildOptions{ Version: buildtypes.BuilderV1, Tags: config.Tags, NoCache: config.NoCache, diff --git a/pkg/compose/commit.go b/pkg/compose/commit.go index 85d19df7c7..9ba57f91fc 100644 --- a/pkg/compose/commit.go +++ b/pkg/compose/commit.go @@ -23,7 +23,7 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/client" ) func (s *composeService) Commit(ctx context.Context, projectName string, options api.CommitOptions) error { @@ -65,12 +65,12 @@ func (s *composeService) commit(ctx context.Context, projectName string, options return nil } - response, err := clnt.ContainerCommit(ctx, ctr.ID, container.CommitOptions{ + response, err := clnt.ContainerCommit(ctx, ctr.ID, client.ContainerCommitOptions{ Reference: options.Reference, Comment: options.Comment, Author: options.Author, Changes: options.Changes.GetSlice(), - Pause: options.Pause, + NoPause: !options.Pause, }) if err != nil { return err diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 10c3225549..69c6ee90a7 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -30,13 +30,10 @@ import ( "github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/flags" "github.com/docker/cli/cli/streams" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/volume" - "github.com/docker/docker/client" "github.com/jonboulle/clockwork" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/swarm" + "github.com/moby/moby/client" "github.com/docker/compose/v2/internal/desktop" "github.com/docker/compose/v2/internal/experimental" @@ -243,8 +240,8 @@ func increment(scale *int) *int { } func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) { - opts := volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(projectName)), + opts := client.VolumeListOptions{ + Filters: projectFilter(projectName), } volumes, err := s.apiClient().VolumeList(ctx, opts) if err != nil { @@ -263,8 +260,8 @@ func (s *composeService) actualVolumes(ctx context.Context, projectName string) } func (s *composeService) actualNetworks(ctx context.Context, projectName string) (types.Networks, error) { - networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{ - Filters: filters.NewArgs(projectFilter(projectName)), + networks, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{ + Filters: projectFilter(projectName), }) if err != nil { return nil, err @@ -312,6 +309,7 @@ type runtimeVersionCache struct { var runtimeVersion runtimeVersionCache func (s *composeService) RuntimeVersion(ctx context.Context) (string, error) { + // TODO(thaJeztah): this should use Client.ClientVersion), which has the negotiated version. runtimeVersion.once.Do(func() { version, err := s.dockerCli.Client().ServerVersion(ctx) if err != nil { diff --git a/pkg/compose/container.go b/pkg/compose/container.go index 502547ddc9..7e503153f8 100644 --- a/pkg/compose/container.go +++ b/pkg/compose/container.go @@ -19,14 +19,14 @@ package compose import ( "io" - moby "github.com/docker/docker/api/types" + "github.com/moby/moby/client" ) var _ io.ReadCloser = ContainerStdout{} // ContainerStdout implement ReadCloser for moby.HijackedResponse type ContainerStdout struct { - moby.HijackedResponse + client.HijackedResponse } // Read implement io.ReadCloser @@ -44,7 +44,7 @@ var _ io.WriteCloser = ContainerStdin{} // ContainerStdin implement WriteCloser for moby.HijackedResponse type ContainerStdin struct { - moby.HijackedResponse + client.HijackedResponse } // Write implement io.WriteCloser diff --git a/pkg/compose/containers.go b/pkg/compose/containers.go index 1403e43d90..3a01a70ba7 100644 --- a/pkg/compose/containers.go +++ b/pkg/compose/containers.go @@ -25,8 +25,8 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) // Containers is a set of moby Container @@ -42,9 +42,9 @@ const ( func (s *composeService) getContainers(ctx context.Context, project string, oneOff oneOff, all bool, selectedServices ...string) (Containers, error) { var containers Containers - f := getDefaultFilters(project, oneOff, selectedServices...) - containers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs(f...), + var err error + containers, err = s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: getDefaultFilters(project, oneOff, selectedServices...), All: all, }) if err != nil { @@ -56,17 +56,17 @@ func (s *composeService) getContainers(ctx context.Context, project string, oneO return containers, nil } -func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...string) []filters.KeyValuePair { - f := []filters.KeyValuePair{projectFilter(projectName)} +func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...string) client.Filters { + f := projectFilter(projectName) if len(selectedServices) == 1 { - f = append(f, serviceFilter(selectedServices[0])) + f.Add("label", serviceFilter(selectedServices[0])) } - f = append(f, hasConfigHashLabel()) + f.Add("label", hasConfigHashLabel()) switch oneOff { case oneOffOnly: - f = append(f, oneOffFilter(true)) + f.Add("label", oneOffFilter(true)) case oneOffExclude: - f = append(f, oneOffFilter(false)) + f.Add("label", oneOffFilter(false)) case oneOffInclude: } return f @@ -75,13 +75,11 @@ func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...st func (s *composeService) getSpecifiedContainer(ctx context.Context, projectName string, oneOff oneOff, all bool, serviceName string, containerIndex int) (container.Summary, error) { defaultFilters := getDefaultFilters(projectName, oneOff, serviceName) if containerIndex > 0 { - defaultFilters = append(defaultFilters, containerNumberFilter(containerIndex)) + defaultFilters.Add("label", containerNumberFilter(containerIndex)) } - containers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs( - defaultFilters..., - ), - All: all, + containers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: defaultFilters, + All: all, }) if err != nil { return container.Summary{}, err diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index e75fa94efe..43297e82f3 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -30,9 +30,9 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/platforms" - "github.com/docker/docker/api/types/container" - mmount "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/versions" + "github.com/moby/moby/api/types/container" + mmount "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/client" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" "go.opentelemetry.io/otel/attribute" @@ -655,12 +655,12 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P } timeoutInSecond := utils.DurationSecondToInt(timeout) - err = s.apiClient().ContainerStop(ctx, replaced.ID, container.StopOptions{Timeout: timeoutInSecond}) + err = s.apiClient().ContainerStop(ctx, replaced.ID, client.ContainerStopOptions{Timeout: timeoutInSecond}) if err != nil { return created, err } - err = s.apiClient().ContainerRemove(ctx, replaced.ID, container.RemoveOptions{}) + err = s.apiClient().ContainerRemove(ctx, replaced.ID, client.ContainerRemoveOptions{}) if err != nil { return created, err } @@ -682,7 +682,7 @@ func (s *composeService) startContainer(ctx context.Context, ctr container.Summa w.Event(progress.NewEvent(getContainerProgressName(ctr), progress.Working, "Restart")) startMx.Lock() defer startMx.Unlock() - err := s.apiClient().ContainerStart(ctx, ctr.ID, container.StartOptions{}) + err := s.apiClient().ContainerStart(ctx, ctr.ID, client.ContainerStartOptions{}) if err != nil { return err } @@ -742,29 +742,6 @@ func (s *composeService) createMobyContainer(ctx context.Context, }, } - apiVersion, err := s.RuntimeVersion(ctx) - if err != nil { - return created, err - } - // Starting API version 1.44, the ContainerCreate API call takes multiple networks - // so we include all the configurations there and can skip the one-by-one calls here - if versions.LessThan(apiVersion, "1.44") { - // the highest-priority network is the primary and is included in the ContainerCreate API - // call via container.NetworkMode & network.NetworkingConfig - // any remaining networks are connected one-by-one here after creation (but before start) - serviceNetworks := service.NetworksByPriority() - for _, networkKey := range serviceNetworks { - mobyNetworkName := project.Networks[networkKey].Name - if string(cfgs.Host.NetworkMode) == mobyNetworkName { - // primary network already configured as part of ContainerCreate - continue - } - epSettings := createEndpointSettings(project, service, number, networkKey, cfgs.Links, opts.UseNetworkAliases) - if err := s.apiClient().NetworkConnect(ctx, mobyNetworkName, created.ID, epSettings); err != nil { - return created, err - } - } - } return created, nil } @@ -912,7 +889,7 @@ func (s *composeService) startService(ctx context.Context, eventName := getContainerProgressName(ctr) w.Event(progress.StartingEvent(eventName)) - err = s.apiClient().ContainerStart(ctx, ctr.ID, container.StartOptions{}) + err = s.apiClient().ContainerStart(ctx, ctr.ID, client.ContainerStartOptions{}) if err != nil { return err } diff --git a/pkg/compose/convergence_test.go b/pkg/compose/convergence_test.go index 319c811e76..efd460b2c4 100644 --- a/pkg/compose/convergence_test.go +++ b/pkg/compose/convergence_test.go @@ -24,12 +24,11 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/docker/cli/cli/config/configfile" - moby "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/go-connections/nat" + moby "github.com/moby/moby/api/types" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -71,9 +70,8 @@ func TestServiceLinks(t *testing.T) { Scale: intPtr(1), } - containerListOptions := container.ListOptions{ - Filters: filters.NewArgs( - projectFilter(testProject), + containerListOptions := client.ContainerListOptions{ + Filters: projectFilter(testProject).Add("label", serviceFilter("db"), oneOffFilter(false), hasConfigHashLabel(), @@ -197,9 +195,8 @@ func TestServiceLinks(t *testing.T) { s.Labels = s.Labels.Add(api.OneoffLabel, "True") c := testContainer("web", webContainerName, true) - containerListOptionsOneOff := container.ListOptions{ - Filters: filters.NewArgs( - projectFilter(testProject), + containerListOptionsOneOff := client.ContainerListOptions{ + Filters: projectFilter(testProject).Add("label", serviceFilter("web"), oneOffFilter(false), hasConfigHashLabel(), @@ -258,179 +255,86 @@ func TestWaitDependencies(t *testing.T) { } func TestCreateMobyContainer(t *testing.T) { - t.Run("connects container networks one by one if API <1.44", func(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - apiClient := mocks.NewMockAPIClient(mockCtrl) - cli := mocks.NewMockCli(mockCtrl) - tested := composeService{ - dockerCli: cli, - } - cli.EXPECT().Client().Return(apiClient).AnyTimes() - cli.EXPECT().ConfigFile().Return(&configfile.ConfigFile{}).AnyTimes() - apiClient.EXPECT().DaemonHost().Return("").AnyTimes() - apiClient.EXPECT().ImageInspect(gomock.Any(), gomock.Any()).Return(image.InspectResponse{}, nil).AnyTimes() - // force `RuntimeVersion` to fetch again - runtimeVersion = runtimeVersionCache{} - apiClient.EXPECT().ServerVersion(gomock.Any()).Return(moby.Version{ - APIVersion: "1.43", - }, nil).AnyTimes() - - service := types.ServiceConfig{ - Name: "test", - Networks: map[string]*types.ServiceNetworkConfig{ - "a": { - Priority: 10, - }, - "b": { - Priority: 100, - }, + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + apiClient := mocks.NewMockAPIClient(mockCtrl) + cli := mocks.NewMockCli(mockCtrl) + tested := composeService{ + dockerCli: cli, + } + cli.EXPECT().Client().Return(apiClient).AnyTimes() + cli.EXPECT().ConfigFile().Return(&configfile.ConfigFile{}).AnyTimes() + apiClient.EXPECT().DaemonHost().Return("").AnyTimes() + apiClient.EXPECT().ImageInspect(gomock.Any(), gomock.Any()).Return(image.InspectResponse{}, nil).AnyTimes() + // force `RuntimeVersion` to fetch fresh version + runtimeVersion = runtimeVersionCache{} + apiClient.EXPECT().ServerVersion(gomock.Any()).Return(moby.Version{ + APIVersion: "1.44", + }, nil).AnyTimes() + + service := types.ServiceConfig{ + Name: "test", + Networks: map[string]*types.ServiceNetworkConfig{ + "a": { + Priority: 10, }, - } - project := types.Project{ - Name: "bork", - Services: types.Services{ - "test": service, + "b": { + Priority: 100, }, - Networks: types.Networks{ - "a": types.NetworkConfig{ - Name: "a-moby-name", - }, - "b": types.NetworkConfig{ - Name: "b-moby-name", - }, + }, + } + project := types.Project{ + Name: "bork", + Services: types.Services{ + "test": service, + }, + Networks: types.Networks{ + "a": types.NetworkConfig{ + Name: "a-moby-name", }, - } - - var falseBool bool - apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any(), gomock.Eq( - &container.HostConfig{ - PortBindings: nat.PortMap{}, - ExtraHosts: []string{}, - Tmpfs: map[string]string{}, - Resources: container.Resources{ - OomKillDisable: &falseBool, - }, - NetworkMode: "b-moby-name", - }), gomock.Eq( - &network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - "b-moby-name": { - IPAMConfig: &network.EndpointIPAMConfig{}, - Aliases: []string{"bork-test-0"}, - }, - }, - }), gomock.Any(), gomock.Any()).Times(1).Return( - container.CreateResponse{ - ID: "an-id", - }, nil) - - apiClient.EXPECT().ContainerInspect(gomock.Any(), gomock.Eq("an-id")).Times(1).Return( - container.InspectResponse{ - ContainerJSONBase: &container.ContainerJSONBase{ - ID: "an-id", - Name: "a-name", - }, - Config: &container.Config{}, - NetworkSettings: &container.NetworkSettings{}, - }, nil) - - apiClient.EXPECT().NetworkConnect(gomock.Any(), "a-moby-name", "an-id", gomock.Eq( - &network.EndpointSettings{ - IPAMConfig: &network.EndpointIPAMConfig{}, - Aliases: []string{"bork-test-0"}, - })) - - _, err := tested.createMobyContainer(context.Background(), &project, service, "test", 0, nil, createOptions{ - Labels: make(types.Labels), - }, progress.ContextWriter(context.TODO())) - assert.NilError(t, err) - }) - - t.Run("includes all container networks in ContainerCreate call if API >=1.44", func(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - apiClient := mocks.NewMockAPIClient(mockCtrl) - cli := mocks.NewMockCli(mockCtrl) - tested := composeService{ - dockerCli: cli, - } - cli.EXPECT().Client().Return(apiClient).AnyTimes() - cli.EXPECT().ConfigFile().Return(&configfile.ConfigFile{}).AnyTimes() - apiClient.EXPECT().DaemonHost().Return("").AnyTimes() - apiClient.EXPECT().ImageInspect(gomock.Any(), gomock.Any()).Return(image.InspectResponse{}, nil).AnyTimes() - // force `RuntimeVersion` to fetch fresh version - runtimeVersion = runtimeVersionCache{} - apiClient.EXPECT().ServerVersion(gomock.Any()).Return(moby.Version{ - APIVersion: "1.44", - }, nil).AnyTimes() - - service := types.ServiceConfig{ - Name: "test", - Networks: map[string]*types.ServiceNetworkConfig{ - "a": { - Priority: 10, - }, - "b": { - Priority: 100, - }, + "b": types.NetworkConfig{ + Name: "b-moby-name", }, - } - project := types.Project{ - Name: "bork", - Services: types.Services{ - "test": service, + }, + } + + var falseBool bool + apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any(), gomock.Eq( + &container.HostConfig{ + PortBindings: network.PortMap{}, + ExtraHosts: []string{}, + Tmpfs: map[string]string{}, + Resources: container.Resources{ + OomKillDisable: &falseBool, }, - Networks: types.Networks{ - "a": types.NetworkConfig{ - Name: "a-moby-name", + NetworkMode: "b-moby-name", + }), gomock.Eq( + &network.NetworkingConfig{ + EndpointsConfig: map[string]*network.EndpointSettings{ + "a-moby-name": { + IPAMConfig: &network.EndpointIPAMConfig{}, + Aliases: []string{"bork-test-0"}, }, - "b": types.NetworkConfig{ - Name: "b-moby-name", + "b-moby-name": { + IPAMConfig: &network.EndpointIPAMConfig{}, + Aliases: []string{"bork-test-0"}, }, }, - } - - var falseBool bool - apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any(), gomock.Eq( - &container.HostConfig{ - PortBindings: nat.PortMap{}, - ExtraHosts: []string{}, - Tmpfs: map[string]string{}, - Resources: container.Resources{ - OomKillDisable: &falseBool, - }, - NetworkMode: "b-moby-name", - }), gomock.Eq( - &network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - "a-moby-name": { - IPAMConfig: &network.EndpointIPAMConfig{}, - Aliases: []string{"bork-test-0"}, - }, - "b-moby-name": { - IPAMConfig: &network.EndpointIPAMConfig{}, - Aliases: []string{"bork-test-0"}, - }, - }, - }), gomock.Any(), gomock.Any()).Times(1).Return( - container.CreateResponse{ - ID: "an-id", - }, nil) - - apiClient.EXPECT().ContainerInspect(gomock.Any(), gomock.Eq("an-id")).Times(1).Return( - container.InspectResponse{ - ContainerJSONBase: &container.ContainerJSONBase{ - ID: "an-id", - Name: "a-name", - }, - Config: &container.Config{}, - NetworkSettings: &container.NetworkSettings{}, - }, nil) - - _, err := tested.createMobyContainer(context.Background(), &project, service, "test", 0, nil, createOptions{ - Labels: make(types.Labels), - }, progress.ContextWriter(context.TODO())) - assert.NilError(t, err) - }) + }), gomock.Any(), gomock.Any()).Times(1).Return( + container.CreateResponse{ + ID: "an-id", + }, nil) + + apiClient.EXPECT().ContainerInspect(gomock.Any(), gomock.Eq("an-id")).Times(1).Return( + container.InspectResponse{ + ID: "an-id", + Name: "a-name", + Config: &container.Config{}, + NetworkSettings: &container.NetworkSettings{}, + }, nil) + + _, err := tested.createMobyContainer(context.Background(), &project, service, "test", 0, nil, createOptions{ + Labels: make(types.Labels), + }, progress.ContextWriter(context.TODO())) + assert.NilError(t, err) } diff --git a/pkg/compose/convert.go b/pkg/compose/convert.go index 17d5a90186..a854564f63 100644 --- a/pkg/compose/convert.go +++ b/pkg/compose/convert.go @@ -23,8 +23,7 @@ import ( "time" compose "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/versions" + "github.com/moby/moby/api/types/container" ) // ToMobyEnv convert into []string @@ -69,15 +68,7 @@ func (s *composeService) ToMobyHealthCheck(ctx context.Context, check *compose.H } var startInterval time.Duration if check.StartInterval != nil { - version, err := s.RuntimeVersion(ctx) - if err != nil { - return nil, err - } - if versions.LessThan(version, "1.44") { - return nil, errors.New("can't set healthcheck.start_interval as feature require Docker Engine v25 or later") - } else { - startInterval = time.Duration(*check.StartInterval) - } + startInterval = time.Duration(*check.StartInterval) if check.StartPeriod == nil { // see https://github.com/moby/moby/issues/48874 return nil, errors.New("healthcheck.start_interval requires healthcheck.start_period to be set") diff --git a/pkg/compose/cp.go b/pkg/compose/cp.go index b7db329698..94acce7d19 100644 --- a/pkg/compose/cp.go +++ b/pkg/compose/cp.go @@ -26,11 +26,11 @@ import ( "strings" "github.com/docker/compose/v2/pkg/progress" + "github.com/moby/moby/client" "golang.org/x/sync/errgroup" "github.com/docker/cli/cli/command" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" "github.com/moby/go-archive" ) @@ -234,7 +234,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string } } - options := container.CopyToContainerOptions{ + options := client.CopyToContainerOptions{ AllowOverwriteDirWithFile: false, CopyUIDGID: opts.CopyUIDGID, } diff --git a/pkg/compose/create.go b/pkg/compose/create.go index 5ff84f395b..29657271eb 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "net/netip" "os" "path/filepath" "slices" @@ -31,14 +32,13 @@ import ( "github.com/compose-spec/compose-go/v2/paths" "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/errdefs" - "github.com/docker/docker/api/types/blkiodev" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/versions" - volumetypes "github.com/docker/docker/api/types/volume" - "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/blkiodev" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/api/types/versions" + volumetypes "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" cdi "tags.cncf.io/container-device-interface/pkg/parser" @@ -203,8 +203,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context, mainNw = service.Networks[mainNwName] } - macAddress, err := s.prepareContainerMACAddress(ctx, service, mainNw, mainNwName) - if err != nil { + if err := s.prepareContainerMACAddress(service, mainNw, mainNwName); err != nil { return createConfigs{}, err } @@ -212,11 +211,15 @@ func (s *composeService) getCreateConfigs(ctx context.Context, if err != nil { return createConfigs{}, err } + exposedPorts, err := buildContainerPorts(service) + if err != nil { + return createConfigs{}, err + } containerConfig := container.Config{ Hostname: service.Hostname, Domainname: service.DomainName, User: service.User, - ExposedPorts: buildContainerPorts(service), + ExposedPorts: exposedPorts, Tty: tty, OpenStdin: stdinOpen, StdinOnce: opts.AttachStdin && stdinOpen, @@ -228,7 +231,6 @@ func (s *composeService) getCreateConfigs(ctx context.Context, WorkingDir: service.WorkingDir, Entrypoint: entrypoint, NetworkDisabled: service.NetworkMode == "disabled", - MacAddress: macAddress, // Field is deprecated since API v1.44, but kept for compatibility with older API versions. Labels: labels, StopSignal: service.StopSignal, Env: ToMobyEnv(env), @@ -261,7 +263,10 @@ func (s *composeService) getCreateConfigs(ctx context.Context, if err != nil { return createConfigs{}, err } - portBindings := buildContainerPortBindingOptions(service) + portBindings, err := buildContainerPortBindingOptions(service) + if err != nil { + return createConfigs{}, err + } // MISC resources := getDeployResources(service) @@ -277,6 +282,15 @@ func (s *composeService) getCreateConfigs(ctx context.Context, return createConfigs{}, err } + var dnsIPs []netip.Addr + for _, d := range service.DNS { + dnsIP, err := netip.ParseAddr(d) + if err != nil { + return createConfigs{}, fmt.Errorf("invalid DNS address: %w", err) + } + dnsIPs = append(dnsIPs, dnsIP) + } + hostConfig := container.HostConfig{ AutoRemove: opts.AutoRemove, Annotations: service.Annotations, @@ -296,7 +310,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context, Resources: resources, VolumeDriver: service.VolumeDriver, VolumesFrom: service.VolumesFrom, - DNS: service.DNS, + DNS: dnsIPs, DNSSearch: service.DNSSearch, DNSOptions: service.DNSOpts, ExtraHosts: service.ExtraHosts.AsList(":"), @@ -335,12 +349,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context, // passed mainNw to provide backward-compatibility whenever possible. // // It returns the container-wide MAC address, but this value will be kept empty for newer API versions. -func (s *composeService) prepareContainerMACAddress(ctx context.Context, service types.ServiceConfig, mainNw *types.ServiceNetworkConfig, nwName string) (string, error) { - version, err := s.RuntimeVersion(ctx) - if err != nil { - return "", err - } - +func (s *composeService) prepareContainerMACAddress(service types.ServiceConfig, mainNw *types.ServiceNetworkConfig, nwName string) error { // Engine API 1.44 added support for endpoint-specific MAC address and now returns a warning when a MAC address is // set in container.Config. Thus, we have to jump through a number of hoops: // @@ -354,31 +363,12 @@ func (s *composeService) prepareContainerMACAddress(ctx context.Context, service // there's no need to check for API version in defaultNetworkSettings. macAddress := service.MacAddress if macAddress != "" && mainNw != nil && mainNw.MacAddress != "" && mainNw.MacAddress != macAddress { - return "", fmt.Errorf("the service-level mac_address should have the same value as network %s", nwName) - } - if versions.GreaterThanOrEqualTo(version, "1.44") { - if mainNw != nil && mainNw.MacAddress == "" { - mainNw.MacAddress = macAddress - } - macAddress = "" - } else if len(service.Networks) > 0 { - var withMacAddress []string - for nwName, nw := range service.Networks { - if nw != nil && nw.MacAddress != "" { - withMacAddress = append(withMacAddress, nwName) - } - } - - if len(withMacAddress) > 1 { - return "", fmt.Errorf("a MAC address is specified for multiple networks (%s), but this feature requires Docker Engine v25 or later", strings.Join(withMacAddress, ", ")) - } - - if mainNw != nil && mainNw.MacAddress != "" { - macAddress = mainNw.MacAddress - } + return fmt.Errorf("the service-level mac_address should have the same value as network %s", nwName) } - - return macAddress, nil + if mainNw != nil && mainNw.MacAddress == "" { + mainNw.MacAddress = macAddress + } + return nil } func getAliases(project *types.Project, service types.ServiceConfig, serviceIndex int, cfg *types.ServiceNetworkConfig, useNetworkAliases bool) []string { @@ -392,25 +382,48 @@ func getAliases(project *types.Project, service types.ServiceConfig, serviceInde return aliases } -func createEndpointSettings(p *types.Project, service types.ServiceConfig, serviceIndex int, networkKey string, links []string, useNetworkAliases bool) *network.EndpointSettings { +func createEndpointSettings(p *types.Project, service types.ServiceConfig, serviceIndex int, networkKey string, links []string, useNetworkAliases bool) (*network.EndpointSettings, error) { const ifname = "com.docker.network.endpoint.ifname" config := service.Networks[networkKey] var ipam *network.EndpointIPAMConfig var ( - ipv4Address string - ipv6Address string + ipv4Address netip.Addr + ipv6Address netip.Addr macAddress string driverOpts types.Options gwPriority int ) if config != nil { - ipv4Address = config.Ipv4Address - ipv6Address = config.Ipv6Address + var err error + if config.Ipv4Address != "" { + ipv4Address, err = netip.ParseAddr(config.Ipv4Address) + if err != nil { + return nil, fmt.Errorf("invalid IPv4 address: %w", err) + } + } + if config.Ipv6Address != "" { + ipv6Address, err = netip.ParseAddr(config.Ipv6Address) + if err != nil { + return nil, fmt.Errorf("invalid IPv6 address: %w", err) + } + } + var linkLocalIPs []netip.Addr + for _, link := range config.LinkLocalIPs { + if link == "" { + continue + } + llIP, err := netip.ParseAddr(link) + if err != nil { + return nil, fmt.Errorf("invalid link-local IP: %w", err) + } + linkLocalIPs = append(linkLocalIPs, llIP) + } + ipam = &network.EndpointIPAMConfig{ - IPv4Address: ipv4Address, + IPv4Address: ipv4Address.Unmap(), IPv6Address: ipv6Address, - LinkLocalIPs: config.LinkLocalIPs, + LinkLocalIPs: linkLocalIPs, } macAddress = config.MacAddress driverOpts = config.DriverOpts @@ -434,7 +447,7 @@ func createEndpointSettings(p *types.Project, service types.ServiceConfig, servi MacAddress: macAddress, DriverOpts: driverOpts, GwPriority: gwPriority, - } + }, nil } // copy/pasted from https://github.com/docker/cli/blob/9de1b162f/cli/command/container/opts.go#L673-L697 + RelativePath @@ -516,26 +529,31 @@ func defaultNetworkSettings(project *types.Project, primaryNetworkKey = "default" } primaryNetworkMobyNetworkName := project.Networks[primaryNetworkKey].Name - primaryNetworkEndpoint := createEndpointSettings(project, service, serviceIndex, primaryNetworkKey, links, useNetworkAliases) + primaryNetworkEndpoint, err := createEndpointSettings(project, service, serviceIndex, primaryNetworkKey, links, useNetworkAliases) + if err != nil { + return "", nil, err + } + endpointsConfig := map[string]*network.EndpointSettings{} // Starting from API version 1.44, the Engine will take several EndpointsConfigs // so we can pass all the extra networks we want the container to be connected to // in the network configuration instead of connecting the container to each extra // network individually after creation. - if versions.GreaterThanOrEqualTo(version, "1.44") { - if len(service.Networks) > 1 { - serviceNetworks := service.NetworksByPriority() - for _, networkKey := range serviceNetworks[1:] { - mobyNetworkName := project.Networks[networkKey].Name - epSettings := createEndpointSettings(project, service, serviceIndex, networkKey, links, useNetworkAliases) - endpointsConfig[mobyNetworkName] = epSettings + if len(service.Networks) > 1 { + serviceNetworks := service.NetworksByPriority() + for _, networkKey := range serviceNetworks[1:] { + mobyNetworkName := project.Networks[networkKey].Name + epSettings, err := createEndpointSettings(project, service, serviceIndex, networkKey, links, useNetworkAliases) + if err != nil { + return "", nil, err } - } - if primaryNetworkEndpoint.MacAddress == "" { - primaryNetworkEndpoint.MacAddress = service.MacAddress + endpointsConfig[mobyNetworkName] = epSettings } } + if primaryNetworkEndpoint.MacAddress == "" { + primaryNetworkEndpoint.MacAddress = service.MacAddress + } if versions.LessThan(version, "1.49") { for _, config := range service.Networks { @@ -765,30 +783,46 @@ func setBlkio(blkio *types.BlkioConfig, resources *container.Resources) { } } -func buildContainerPorts(s types.ServiceConfig) nat.PortSet { - ports := nat.PortSet{} +func buildContainerPorts(s types.ServiceConfig) (network.PortSet, error) { + ports := network.PortSet{} for _, s := range s.Expose { - p := nat.Port(s) + p, err := network.ParsePort(s) + if err != nil { + return nil, err + } ports[p] = struct{}{} } for _, p := range s.Ports { - p := nat.Port(fmt.Sprintf("%d/%s", p.Target, p.Protocol)) - ports[p] = struct{}{} + np, err := network.ParsePort(fmt.Sprintf("%d/%s", p.Target, p.Protocol)) + if err != nil { + return nil, err + } + ports[np] = struct{}{} } - return ports + return ports, nil } -func buildContainerPortBindingOptions(s types.ServiceConfig) nat.PortMap { - bindings := nat.PortMap{} +func buildContainerPortBindingOptions(s types.ServiceConfig) (network.PortMap, error) { + bindings := network.PortMap{} for _, port := range s.Ports { - p := nat.Port(fmt.Sprintf("%d/%s", port.Target, port.Protocol)) - binding := nat.PortBinding{ - HostIP: port.HostIP, - HostPort: port.Published, + var err error + p, err := network.ParsePort(fmt.Sprintf("%d/%s", port.Target, port.Protocol)) + if err != nil { + return nil, err } - bindings[p] = append(bindings[p], binding) + var hostIP netip.Addr + if port.HostIP != "" { + hostIP, err = netip.ParseAddr(port.HostIP) + if err != nil { + return nil, err + } + } + bindings[p] = append(bindings[p], network.PortBinding{ + HostIP: hostIP, + HostPort: port.Published, + }) } - return bindings + return bindings, nil } func getDependentServiceFromMode(mode string) string { @@ -1275,7 +1309,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty var dangledContainers Containers // First, try to find a unique network matching by name or ID - inspect, err := s.apiClient().NetworkInspect(ctx, n.Name, network.InspectOptions{}) + inspect, err := s.apiClient().NetworkInspect(ctx, n.Name, client.NetworkInspectOptions{}) if err == nil { // NetworkInspect will match on ID prefix, so double check we get the expected one // as looking for network named `db` we could erroneously match network ID `db9086999caf` @@ -1316,8 +1350,8 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty // ignore other errors. Typically, an ambiguous request by name results in some generic `invalidParameter` error // Either not found, or name is ambiguous - use NetworkList to list by name - networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{ - Filters: filters.NewArgs(filters.Arg("name", n.Name)), + networks, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{ + Filters: make(client.Filters).Add("name", n.Name), }) if err != nil { return "", err @@ -1348,12 +1382,11 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty if n.Ipam.Config != nil { var config []network.IPAMConfig for _, pool := range n.Ipam.Config { - config = append(config, network.IPAMConfig{ - Subnet: pool.Subnet, - IPRange: pool.IPRange, - Gateway: pool.Gateway, - AuxAddress: pool.AuxiliaryAddresses, - }) + c, err := parseIPAMPool(pool) + if err != nil { + return "", err + } + config = append(config, c) } ipam = &network.IPAM{ Driver: n.Ipam.Driver, @@ -1365,7 +1398,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty return "", err } n.CustomLabels = n.CustomLabels.Add(api.ConfigHashLabel, hash) - createOpts := network.CreateOptions{ + createOpts := client.NetworkCreateOptions{ Labels: mergeLabels(n.Labels, n.CustomLabels), Driver: n.Driver, Options: n.DriverOpts, @@ -1385,13 +1418,11 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty } for _, ipamConfig := range n.Ipam.Config { - config := network.IPAMConfig{ - Subnet: ipamConfig.Subnet, - IPRange: ipamConfig.IPRange, - Gateway: ipamConfig.Gateway, - AuxAddress: ipamConfig.AuxiliaryAddresses, + c, err := parseIPAMPool(ipamConfig) + if err != nil { + return "", err } - createOpts.IPAM.Config = append(createOpts.IPAM.Config, config) + createOpts.IPAM.Config = append(createOpts.IPAM.Config, c) } networkEventName := fmt.Sprintf("Network %s", n.Name) @@ -1451,11 +1482,11 @@ func (s *composeService) removeDivergedNetwork(ctx context.Context, project *typ func (s *composeService) disconnectNetwork( ctx context.Context, - network string, + networkID string, containers Containers, ) error { for _, c := range containers { - err := s.apiClient().NetworkDisconnect(ctx, network, c.ID, true) + err := s.apiClient().NetworkDisconnect(ctx, networkID, c.ID, true) if err != nil { return err } @@ -1466,12 +1497,12 @@ func (s *composeService) disconnectNetwork( func (s *composeService) connectNetwork( ctx context.Context, - network string, + networkID string, containers Containers, config *network.EndpointSettings, ) error { for _, c := range containers { - err := s.apiClient().NetworkConnect(ctx, network, c.ID, config) + err := s.apiClient().NetworkConnect(ctx, networkID, c.ID, config) if err != nil { return err } @@ -1485,8 +1516,8 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne // filter is used to look for an exact match to prevent e.g. a network // named `db` from getting erroneously matched to a network with an ID // like `db9086999caf` - networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{ - Filters: filters.NewArgs(filters.Arg("name", n.Name)), + networks, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{ + Filters: make(client.Filters).Add("name", n.Name), }) if err != nil { return "", err @@ -1494,9 +1525,9 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne if len(networks) == 0 { // in this instance, n.Name is really an ID - sn, err := s.apiClient().NetworkInspect(ctx, n.Name, network.InspectOptions{}) + sn, err := s.apiClient().NetworkInspect(ctx, n.Name, client.NetworkInspectOptions{}) if err == nil { - networks = append(networks, sn) + networks = append(networks, network.Summary{Network: sn.Network}) } else if !errdefs.IsNotFound(err) { return "", err } @@ -1504,7 +1535,7 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne } // NetworkList API doesn't return the exact name match, so we can retrieve more than one network with a request - networks = slices.DeleteFunc(networks, func(net network.Inspect) bool { + networks = slices.DeleteFunc(networks, func(net network.Summary) bool { // this function is called during the rebuild stage of `compose watch`. // we still require just one network back, but we need to run the search on the ID return net.Name != n.Name && net.ID != n.Name @@ -1644,3 +1675,48 @@ func (s *composeService) createVolume(ctx context.Context, volume types.VolumeCo w.Event(progress.CreatedEvent(eventName)) return nil } + +func parseIPAMPool(pool *types.IPAMPool) (network.IPAMConfig, error) { + var ( + err error + subNet netip.Prefix + ipRange netip.Prefix + gateway netip.Addr + auxAddress map[string]netip.Addr + ) + if pool.Subnet != "" { + subNet, err = netip.ParsePrefix(pool.Subnet) + if err != nil { + return network.IPAMConfig{}, fmt.Errorf("invalid subnet: %w", err) + } + } + if pool.IPRange != "" { + ipRange, err = netip.ParsePrefix(pool.IPRange) + if err != nil { + return network.IPAMConfig{}, fmt.Errorf("invalid ip-range: %w", err) + } + } + if pool.Gateway != "" { + gateway, err = netip.ParseAddr(pool.Gateway) + if err != nil { + return network.IPAMConfig{}, fmt.Errorf("invalid gateway address: %w", err) + } + } + if len(pool.AuxiliaryAddresses) > 0 { + auxAddress = make(map[string]netip.Addr, len(pool.AuxiliaryAddresses)) + for auxName, addr := range pool.AuxiliaryAddresses { + auxAddr, err := netip.ParseAddr(addr) + if err != nil { + return network.IPAMConfig{}, fmt.Errorf("invalid auxiliary address: %w", err) + } + auxAddress[auxName] = auxAddr + } + + } + return network.IPAMConfig{ + Subnet: subNet, + IPRange: ipRange, + Gateway: gateway, + AuxAddress: auxAddress, + }, nil +} diff --git a/pkg/compose/create_test.go b/pkg/compose/create_test.go index 3394bf3c93..4ce011db0a 100644 --- a/pkg/compose/create_test.go +++ b/pkg/compose/create_test.go @@ -18,22 +18,24 @@ package compose import ( "context" + "net/netip" "os" "path/filepath" "sort" "testing" composeloader "github.com/compose-spec/compose-go/v2/loader" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" "go.uber.org/mock/gomock" "gotest.tools/v3/assert/cmp" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/network" + "github.com/moby/moby/api/types/network" composetypes "github.com/compose-spec/compose-go/v2/types" - mountTypes "github.com/docker/docker/api/types/mount" + mountTypes "github.com/moby/moby/api/types/mount" "gotest.tools/v3/assert" ) @@ -295,7 +297,7 @@ func TestDefaultNetworkSettings(t *testing.T) { } func TestCreateEndpointSettings(t *testing.T) { - eps := createEndpointSettings(&composetypes.Project{ + eps, err := createEndpointSettings(&composetypes.Project{ Name: "projName", }, composetypes.ServiceConfig{ Name: "serviceName", @@ -315,11 +317,12 @@ func TestCreateEndpointSettings(t *testing.T) { }, }, }, 0, "netName", []string{"link1", "link2"}, true) + assert.NilError(t, err) assert.Check(t, cmp.DeepEqual(eps, &network.EndpointSettings{ IPAMConfig: &network.EndpointIPAMConfig{ - IPv4Address: "10.16.17.18", - IPv6Address: "fdb4:7a7f:373a:3f0c::42", - LinkLocalIPs: []string{"169.254.10.20"}, + IPv4Address: netip.MustParseAddr("10.16.17.18").Unmap(), + IPv6Address: netip.MustParseAddr("fdb4:7a7f:373a:3f0c::42"), + LinkLocalIPs: []netip.Addr{netip.MustParseAddr("169.254.10.20").Unmap()}, }, Links: []string{"link1", "link2"}, Aliases: []string{"containerName", "serviceName", "alias1", "alias2"}, @@ -333,9 +336,9 @@ func TestCreateEndpointSettings(t *testing.T) { // - The IPv6 address here is the container's address, not the gateway. // - Both fields will be cleared by the daemon, but they could be removed from // the request. - IPAddress: "10.16.17.18", - IPv6Gateway: "fdb4:7a7f:373a:3f0c::42", - })) + IPAddress: netip.MustParseAddr("10.16.17.18").Unmap(), + IPv6Gateway: netip.MustParseAddr("fdb4:7a7f:373a:3f0c::42"), + }, cmpopts.EquateComparable(netip.Addr{}))) } func Test_buildContainerVolumes(t *testing.T) { diff --git a/pkg/compose/down.go b/pkg/compose/down.go index e9619fbe65..9f2bd6d828 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -27,10 +27,8 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" "github.com/docker/compose/v2/pkg/utils" - containerType "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - imageapi "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" + containerType "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -197,10 +195,8 @@ func (s *composeService) ensureNetworksDown(ctx context.Context, project *types. } func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName string, projectName string, name string, w progress.Writer) error { - networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{ - Filters: filters.NewArgs( - projectFilter(projectName), - networkFilter(composeNetworkName)), + networks, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{ + Filters: projectFilter(projectName).Add("label", networkFilter(composeNetworkName)), }) if err != nil { return fmt.Errorf("failed to list networks: %w", err) @@ -218,7 +214,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s if net.Name != name { continue } - nw, err := s.apiClient().NetworkInspect(ctx, net.ID, network.InspectOptions{}) + nw, err := s.apiClient().NetworkInspect(ctx, net.ID, client.NetworkInspectOptions{}) if errdefs.IsNotFound(err) { w.Event(progress.NewEvent(eventName, progress.Warning, "No resource found to remove")) return nil @@ -256,7 +252,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s func (s *composeService) removeImage(ctx context.Context, image string, w progress.Writer) error { id := fmt.Sprintf("Image %s", image) w.Event(progress.NewEvent(id, progress.Working, "Removing")) - _, err := s.apiClient().ImageRemove(ctx, image, imageapi.RemoveOptions{}) + _, err := s.apiClient().ImageRemove(ctx, image, client.ImageRemoveOptions{}) if err == nil { w.Event(progress.NewEvent(id, progress.Done, "Removed")) return nil @@ -320,7 +316,7 @@ func (s *composeService) stopContainer( } timeoutInSecond := utils.DurationSecondToInt(timeout) - err := s.apiClient().ContainerStop(ctx, ctr.ID, containerType.StopOptions{Timeout: timeoutInSecond}) + err := s.apiClient().ContainerStop(ctx, ctr.ID, client.ContainerStopOptions{Timeout: timeoutInSecond}) if err != nil { w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping")) return err @@ -365,7 +361,7 @@ func (s *composeService) stopAndRemoveContainer(ctx context.Context, ctr contain return err } w.Event(progress.RemovingEvent(eventName)) - err = s.apiClient().ContainerRemove(ctx, ctr.ID, containerType.RemoveOptions{ + err = s.apiClient().ContainerRemove(ctx, ctr.ID, client.ContainerRemoveOptions{ Force: true, RemoveVolumes: volumes, }) diff --git a/pkg/compose/down_test.go b/pkg/compose/down_test.go index 58c1ec0b14..13ca871758 100644 --- a/pkg/compose/down_test.go +++ b/pkg/compose/down_test.go @@ -26,11 +26,11 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/errdefs" "github.com/docker/cli/cli/streams" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -56,38 +56,36 @@ func TestDown(t *testing.T) { }, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) // network names are not guaranteed to be unique, ensure Compose handles // cleanup properly if duplicates are inadvertently created - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return([]network.Summary{ - {ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, - {ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, + {Network: network.Network{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, + {Network: network.Network{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, }, nil) - stopOptions := container.StopOptions{} + stopOptions := client.ContainerStopOptions{} api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "456", stopOptions).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "789", stopOptions).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "456", container.RemoveOptions{Force: true}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "789", container.RemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "123", client.ContainerRemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "456", client.ContainerRemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "789", client.ContainerRemoveOptions{Force: true}).Return(nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{ - Filters: filters.NewArgs( - projectFilter(strings.ToLower(testProject)), - networkFilter("default")), + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("label", networkFilter("default")), }).Return([]network.Summary{ - {ID: "abc123", Name: "myProject_default"}, - {ID: "def456", Name: "myProject_default"}, + {Network: network.Network{ID: "abc123", Name: "myProject_default"}}, + {Network: network.Network{ID: "def456", Name: "myProject_default"}}, }, nil) - api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil) - api.EXPECT().NetworkInspect(gomock.Any(), "def456", gomock.Any()).Return(network.Inspect{ID: "def456"}, nil) + api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{Network: network.Network{ID: "abc123"}}, nil) + api.EXPECT().NetworkInspect(gomock.Any(), "def456", gomock.Any()).Return(network.Inspect{Network: network.Network{ID: "def456"}}, nil) api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil) api.EXPECT().NetworkRemove(gomock.Any(), "def456").Return(nil) @@ -113,32 +111,30 @@ func TestDownWithGivenServices(t *testing.T) { }, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) // network names are not guaranteed to be unique, ensure Compose handles // cleanup properly if duplicates are inadvertently created - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return([]network.Summary{ - {ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, - {ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, + {Network: network.Network{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, + {Network: network.Network{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, }, nil) - stopOptions := container.StopOptions{} + stopOptions := client.ContainerStopOptions{} api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "123", client.ContainerRemoveOptions{Force: true}).Return(nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{ - Filters: filters.NewArgs( - projectFilter(strings.ToLower(testProject)), - networkFilter("default")), + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("label", networkFilter("default")), }).Return([]network.Summary{ - {ID: "abc123", Name: "myProject_default"}, + {Network: network.Network{ID: "abc123", Name: "myProject_default"}}, }, nil) - api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil) + api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{Network: network.Network{ID: "abc123"}}, nil) api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil) err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{ @@ -165,17 +161,17 @@ func TestDownWithSpecifiedServiceButTheServicesAreNotRunning(t *testing.T) { }, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) // network names are not guaranteed to be unique, ensure Compose handles // cleanup properly if duplicates are inadvertently created - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return([]network.Summary{ - {ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, - {ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}, + {Network: network.Network{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, + {Network: network.Network{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}}}, }, nil) err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{ @@ -201,34 +197,31 @@ func TestDownRemoveOrphans(t *testing.T) { }, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). - Return([]network.Summary{ - { + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). + Return([]network.Summary{{ + Network: network.Network{ Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}, }, - }, nil) + }}, nil) - stopOptions := container.StopOptions{} + stopOptions := client.ContainerStopOptions{} api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "789", stopOptions).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "321", stopOptions).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "789", container.RemoveOptions{Force: true}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "321", container.RemoveOptions{Force: true}).Return(nil) - - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{ - Filters: filters.NewArgs( - networkFilter("default"), - projectFilter(strings.ToLower(testProject)), - ), - }).Return([]network.Summary{{ID: "abc123", Name: "myProject_default"}}, nil) - api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil) + api.EXPECT().ContainerRemove(gomock.Any(), "123", client.ContainerRemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "789", client.ContainerRemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "321", client.ContainerRemoveOptions{Force: true}).Return(nil) + + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("label", networkFilter("default")), + }).Return([]network.Summary{{Network: network.Network{ID: "abc123", Name: "myProject_default"}}}, nil) + api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{Network: network.Network{ID: "abc123"}}, nil) api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil) err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{RemoveOrphans: true}) @@ -248,19 +241,19 @@ func TestDownRemoveVolumes(t *testing.T) { []container.Summary{testContainer("service1", "123", false)}, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{ Volumes: []*volume.Volume{{Name: "myProject_volume"}}, }, nil) api.EXPECT().VolumeInspect(gomock.Any(), "myProject_volume"). Return(volume.Volume{}, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return(nil, nil) - api.EXPECT().ContainerStop(gomock.Any(), "123", container.StopOptions{}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true, RemoveVolumes: true}).Return(nil) + api.EXPECT().ContainerStop(gomock.Any(), "123", client.ContainerStopOptions{}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "123", client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).Return(nil) api.EXPECT().VolumeRemove(gomock.Any(), "myProject_volume", true).Return(nil) @@ -297,11 +290,8 @@ func TestDownRemoveImages(t *testing.T) { }, nil). AnyTimes() - api.EXPECT().ImageList(gomock.Any(), image.ListOptions{ - Filters: filters.NewArgs( - projectFilter(strings.ToLower(testProject)), - filters.Arg("dangling", "false"), - ), + api.EXPECT().ImageList(gomock.Any(), client.ImageListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("dangling", "false"), }).Return([]image.Summary{ { Labels: types.Labels{compose.ServiceLabel: "local-anonymous"}, @@ -345,7 +335,7 @@ func TestDownRemoveImages(t *testing.T) { for _, img := range localImagesToBeRemoved { // test calls down --rmi=local then down --rmi=all, so local images // get "removed" 2x, while other images are only 1x - api.EXPECT().ImageRemove(gomock.Any(), img, image.RemoveOptions{}). + api.EXPECT().ImageRemove(gomock.Any(), img, client.ImageRemoveOptions{}). Return(nil, nil). Times(2) } @@ -360,7 +350,7 @@ func TestDownRemoveImages(t *testing.T) { "registry.example.com/remote-image-tagged:v1.0", } for _, img := range otherImagesToBeRemoved { - api.EXPECT().ImageRemove(gomock.Any(), img, image.RemoveOptions{}). + api.EXPECT().ImageRemove(gomock.Any(), img, client.ImageRemoveOptions{}). Return(nil, nil). Times(1) } @@ -387,31 +377,28 @@ func TestDownRemoveImages_NoLabel(t *testing.T) { api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{ Volumes: []*volume.Volume{{Name: "myProject_volume"}}, }, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return(nil, nil) // ImageList returns no images for the project since they were unlabeled // (created by an older version of Compose) - api.EXPECT().ImageList(gomock.Any(), image.ListOptions{ - Filters: filters.NewArgs( - projectFilter(strings.ToLower(testProject)), - filters.Arg("dangling", "false"), - ), + api.EXPECT().ImageList(gomock.Any(), client.ImageListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("dangling", "false"), }).Return(nil, nil) api.EXPECT().ImageInspect(gomock.Any(), "testproject-service1"). Return(image.InspectResponse{}, nil) - api.EXPECT().ContainerStop(gomock.Any(), "123", container.StopOptions{}).Return(nil) - api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil) + api.EXPECT().ContainerStop(gomock.Any(), "123", client.ContainerStopOptions{}).Return(nil) + api.EXPECT().ContainerRemove(gomock.Any(), "123", client.ContainerRemoveOptions{Force: true}).Return(nil) - api.EXPECT().ImageRemove(gomock.Any(), "testproject-service1:latest", image.RemoveOptions{}).Return(nil, nil) + api.EXPECT().ImageRemove(gomock.Any(), "testproject-service1:latest", client.ImageRemoveOptions{}).Return(nil, nil) err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Images: "local"}) assert.NilError(t, err) diff --git a/pkg/compose/events.go b/pkg/compose/events.go index 7ea8dc3265..58a1a3f69e 100644 --- a/pkg/compose/events.go +++ b/pkg/compose/events.go @@ -22,16 +22,15 @@ import ( "strings" "time" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/client" "github.com/docker/compose/v2/pkg/api" ) func (s *composeService) Events(ctx context.Context, projectName string, options api.EventsOptions) error { projectName = strings.ToLower(projectName) - evts, errors := s.apiClient().Events(ctx, events.ListOptions{ - Filters: filters.NewArgs(projectFilter(projectName)), + evts, errors := s.apiClient().Events(ctx, client.EventsListOptions{ + Filters: projectFilter(projectName), Since: options.Since, Until: options.Until, }) diff --git a/pkg/compose/exec.go b/pkg/compose/exec.go index a57e29e4ec..7fb7691246 100644 --- a/pkg/compose/exec.go +++ b/pkg/compose/exec.go @@ -24,7 +24,7 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command/container" "github.com/docker/compose/v2/pkg/api" - containerType "github.com/docker/docker/api/types/container" + containerType "github.com/moby/moby/api/types/container" ) func (s *composeService) Exec(ctx context.Context, projectName string, options api.RunOptions) (int, error) { diff --git a/pkg/compose/filters.go b/pkg/compose/filters.go index d6c814977e..cbe4a17748 100644 --- a/pkg/compose/filters.go +++ b/pkg/compose/filters.go @@ -20,37 +20,33 @@ import ( "fmt" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/client" ) -func projectFilter(projectName string) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, projectName)) +func projectFilter(projectName string) client.Filters { + return make(client.Filters).Add("label", fmt.Sprintf("%s=%s", api.ProjectLabel, projectName)) } -func serviceFilter(serviceName string) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%s", api.ServiceLabel, serviceName)) +func serviceFilter(serviceName string) string { + return fmt.Sprintf("%s=%s", api.ServiceLabel, serviceName) } -func networkFilter(name string) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%s", api.NetworkLabel, name)) +func networkFilter(name string) string { + return fmt.Sprintf("%s=%s", api.NetworkLabel, name) } -func oneOffFilter(b bool) filters.KeyValuePair { +func oneOffFilter(b bool) string { v := "False" if b { v = "True" } - return filters.Arg("label", fmt.Sprintf("%s=%s", api.OneoffLabel, v)) + return fmt.Sprintf("%s=%s", api.OneoffLabel, v) } -func containerNumberFilter(index int) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%d", api.ContainerNumberLabel, index)) +func containerNumberFilter(index int) string { + return fmt.Sprintf("%s=%d", api.ContainerNumberLabel, index) } -func hasProjectLabelFilter() filters.KeyValuePair { - return filters.Arg("label", api.ProjectLabel) -} - -func hasConfigHashLabel() filters.KeyValuePair { - return filters.Arg("label", api.ConfigHashLabel) +func hasConfigHashLabel() string { + return api.ConfigHashLabel } diff --git a/pkg/compose/generate.go b/pkg/compose/generate.go index 025d5093d5..9813e90ef6 100644 --- a/pkg/compose/generate.go +++ b/pkg/compose/generate.go @@ -25,29 +25,23 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" ) func (s *composeService) Generate(ctx context.Context, options api.GenerateOptions) (*types.Project, error) { - filtersListNames := filters.NewArgs() - filtersListIDs := filters.NewArgs() - for _, containerName := range options.Containers { - filtersListNames.Add("name", containerName) - filtersListIDs.Add("id", containerName) - } - containers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filtersListNames, + containers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: make(client.Filters).Add("name", options.Containers...), All: true, }) if err != nil { return nil, err } - containersByIds, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filtersListIDs, + containersByIds, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: make(client.Filters).Add("id", options.Containers...), All: true, }) if err != nil { @@ -135,10 +129,10 @@ func (s *composeService) extractComposeConfiguration(service *types.ServiceConfi for key, portBindings := range inspect.HostConfig.PortBindings { for _, portBinding := range portBindings { service.Ports = append(service.Ports, types.ServicePortConfig{ - Target: uint32(key.Int()), + Target: uint32(key.Num()), Published: portBinding.HostPort, - Protocol: key.Proto(), - HostIP: portBinding.HostIP, + Protocol: string(key.Proto()), + HostIP: portBinding.HostIP.String(), }) } } @@ -221,7 +215,7 @@ func (s *composeService) toComposeNetwork(networks map[string]*network.EndpointS serviceNetworkConfigs := make(map[string]*types.ServiceNetworkConfig) for name, net := range networks { - inspect, err := s.apiClient().NetworkInspect(context.Background(), name, network.InspectOptions{}) + inspect, err := s.apiClient().NetworkInspect(context.Background(), name, client.NetworkInspectOptions{}) if err != nil { networkConfigs[name] = types.NetworkConfig{} } else { diff --git a/pkg/compose/hook.go b/pkg/compose/hook.go index dd02de640a..acfb7818e5 100644 --- a/pkg/compose/hook.go +++ b/pkg/compose/hook.go @@ -25,8 +25,9 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/utils" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/stdcopy" + "github.com/moby/moby/api/pkg/stdcopy" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) func (s composeService) runHook(ctx context.Context, ctr container.Summary, service types.ServiceConfig, hook types.ServiceHook, listener api.ContainerEventListener) error { @@ -42,7 +43,7 @@ func (s composeService) runHook(ctx context.Context, ctr container.Summary, serv defer wOut.Close() //nolint:errcheck detached := listener == nil - exec, err := s.apiClient().ContainerExecCreate(ctx, ctr.ID, container.ExecOptions{ + exec, err := s.apiClient().ContainerExecCreate(ctx, ctr.ID, client.ExecCreateOptions{ User: hook.User, Privileged: hook.Privileged, Env: ToMobyEnv(hook.Environment), @@ -61,7 +62,7 @@ func (s composeService) runHook(ctx context.Context, ctr container.Summary, serv height, width := s.stdout().GetTtySize() consoleSize := &[2]uint{height, width} - attach, err := s.apiClient().ContainerExecAttach(ctx, exec.ID, container.ExecAttachOptions{ + attach, err := s.apiClient().ContainerExecAttach(ctx, exec.ID, client.ExecAttachOptions{ Tty: service.Tty, ConsoleSize: consoleSize, }) @@ -90,7 +91,7 @@ func (s composeService) runHook(ctx context.Context, ctr container.Summary, serv } func (s composeService) runWaitExec(ctx context.Context, execID string, service types.ServiceConfig, listener api.ContainerEventListener) error { - err := s.apiClient().ContainerExecStart(ctx, execID, container.ExecStartOptions{ + err := s.apiClient().ContainerExecStart(ctx, execID, client.ExecStartOptions{ Detach: listener == nil, Tty: service.Tty, }) diff --git a/pkg/compose/image_pruner.go b/pkg/compose/image_pruner.go index bb4d0bc47d..fe5c80724f 100644 --- a/pkg/compose/image_pruner.go +++ b/pkg/compose/image_pruner.go @@ -25,9 +25,8 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/errdefs" "github.com/distribution/reference" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/client" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/api" @@ -150,23 +149,15 @@ func (p *ImagePruner) namedImages(ctx context.Context) ([]string, error) { // The image name could either have been defined by the user or implicitly // created from the project + service name. func (p *ImagePruner) labeledLocalImages(ctx context.Context) ([]image.Summary, error) { - imageListOpts := image.ListOptions{ - Filters: filters.NewArgs( - projectFilter(p.project.Name), - // TODO(milas): we should really clean up the dangling images as - // well (historically we have NOT); need to refactor this to handle - // it gracefully without producing confusing CLI output, i.e. we - // do not want to print out a bunch of untagged/dangling image IDs, - // they should be grouped into a logical operation for the relevant - // service - filters.Arg("dangling", "false"), - ), - } - projectImages, err := p.client.ImageList(ctx, imageListOpts) - if err != nil { - return nil, err - } - return projectImages, nil + return p.client.ImageList(ctx, client.ImageListOptions{ + // TODO(milas): we should really clean up the dangling images as + // well (historically we have NOT); need to refactor this to handle + // it gracefully without producing confusing CLI output, i.e. we + // do not want to print out a bunch of untagged/dangling image IDs, + // they should be grouped into a logical operation for the relevant + // service + Filters: projectFilter(p.project.Name).Add("dangling", "false"), + }) } // unlabeledLocalImages are images that match the implicit naming convention diff --git a/pkg/compose/images.go b/pkg/compose/images.go index d49e92c658..680974a41d 100644 --- a/pkg/compose/images.go +++ b/pkg/compose/images.go @@ -27,10 +27,9 @@ import ( "github.com/containerd/errdefs" "github.com/containerd/platforms" "github.com/distribution/reference" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/client" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/api" @@ -38,9 +37,9 @@ import ( func (s *composeService) Images(ctx context.Context, projectName string, options api.ImagesOptions) (map[string]api.ImageSummary, error) { projectName = strings.ToLower(projectName) - allContainers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ + allContainers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ All: true, - Filters: filters.NewArgs(projectFilter(projectName)), + Filters: projectFilter(projectName), }) if err != nil { return nil, err diff --git a/pkg/compose/images_test.go b/pkg/compose/images_test.go index 85a2b57700..ab62b42e90 100644 --- a/pkg/compose/images_test.go +++ b/pkg/compose/images_test.go @@ -18,14 +18,15 @@ package compose import ( "context" + "net/netip" "strings" "testing" "time" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" + "github.com/moby/moby/api/types" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -42,8 +43,8 @@ func TestImages(t *testing.T) { } ctx := context.Background() - args := filters.NewArgs(projectFilter(strings.ToLower(testProject))) - listOpts := container.ListOptions{All: true, Filters: args} + args := projectFilter(strings.ToLower(testProject)) + listOpts := client.ContainerListOptions{All: true, Filters: args} api.EXPECT().ServerVersion(gomock.Any()).Return(types.Version{APIVersion: "1.96"}, nil).AnyTimes() timeStr1 := "2025-06-06T06:06:06.000000000Z" created1, _ := time.Parse(time.RFC3339Nano, timeStr1) @@ -55,7 +56,7 @@ func TestImages(t *testing.T) { api.EXPECT().ImageInspect(anyCancellableContext(), "bar:2").Return(image2, nil) c1 := containerDetail("service1", "123", "running", "foo:1") c2 := containerDetail("service1", "456", "running", "bar:2") - c2.Ports = []container.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}} + c2.Ports = []container.PortSummary{{PublicPort: 80, PrivatePort: 90, IP: netip.MustParseAddr("127.0.0.1")}} c3 := containerDetail("service2", "789", "exited", "foo:1") api.EXPECT().ContainerList(ctx, listOpts).Return([]container.Summary{c1, c2, c3}, nil) diff --git a/pkg/compose/kill.go b/pkg/compose/kill.go index badf90e03e..9ddc5c6506 100644 --- a/pkg/compose/kill.go +++ b/pkg/compose/kill.go @@ -21,7 +21,7 @@ import ( "fmt" "strings" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/api" diff --git a/pkg/compose/kill_test.go b/pkg/compose/kill_test.go index 5877f5ea65..b166cf7270 100644 --- a/pkg/compose/kill_test.go +++ b/pkg/compose/kill_test.go @@ -18,15 +18,14 @@ package compose import ( "context" - "fmt" "path/filepath" "strings" "testing" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -47,20 +46,20 @@ func TestKillAll(t *testing.T) { name := strings.ToLower(testProject) ctx := context.Background() - api.EXPECT().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs(projectFilter(name), hasConfigHashLabel()), + api.EXPECT().ContainerList(ctx, client.ContainerListOptions{ + Filters: projectFilter(name).Add("label", hasConfigHashLabel()), }).Return( []container.Summary{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). - Return([]network.Summary{ - {ID: "abc123", Name: "testProject_default"}, - }, nil) + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). + Return([]network.Summary{{ + Network: network.Network{ID: "abc123", Name: "testProject_default"}, + }}, nil) api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil) api.EXPECT().ContainerKill(anyCancellableContext(), "456", "").Return(nil) api.EXPECT().ContainerKill(anyCancellableContext(), "789", "").Return(nil) @@ -80,22 +79,22 @@ func TestKillSignal(t *testing.T) { } name := strings.ToLower(testProject) - listOptions := container.ListOptions{ - Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName), hasConfigHashLabel()), + listOptions := client.ContainerListOptions{ + Filters: projectFilter(name).Add("label", serviceFilter(serviceName), hasConfigHashLabel()), } ctx := context.Background() api.EXPECT().ContainerList(ctx, listOptions).Return([]container.Summary{testContainer(serviceName, "123", false)}, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). - Return([]network.Summary{ - {ID: "abc123", Name: "testProject_default"}, - }, nil) + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). + Return([]network.Summary{{ + Network: network.Network{ID: "abc123", Name: "testProject_default"}, + }}, nil) api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil) err := tested.kill(ctx, name, compose.KillOptions{Services: []string{serviceName}, Signal: "SIGTERM"}) @@ -136,15 +135,12 @@ func anyCancellableContext() gomock.Matcher { return gomock.AssignableToTypeOf(ctxWithCancel) } -func projectFilterListOpt(withOneOff bool) container.ListOptions { - filter := filters.NewArgs( - projectFilter(strings.ToLower(testProject)), - hasConfigHashLabel(), - ) +func projectFilterListOpt(withOneOff bool) client.ContainerListOptions { + filter := projectFilter(strings.ToLower(testProject)).Add("label", hasConfigHashLabel()) if !withOneOff { - filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel)) + filter.Add("label", oneOffFilter(false)) } - return container.ListOptions{ + return client.ContainerListOptions{ Filters: filter, All: true, } diff --git a/pkg/compose/logs.go b/pkg/compose/logs.go index b4479d7585..46cda6856e 100644 --- a/pkg/compose/logs.go +++ b/pkg/compose/logs.go @@ -21,8 +21,9 @@ import ( "io" "github.com/containerd/errdefs" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/stdcopy" + "github.com/moby/moby/api/pkg/stdcopy" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" @@ -122,7 +123,7 @@ func (s *composeService) logContainer(ctx context.Context, consumer api.LogConsu } func (s *composeService) doLogContainer(ctx context.Context, consumer api.LogConsumer, name string, ctr container.InspectResponse, options api.LogOptions) error { - r, err := s.apiClient().ContainerLogs(ctx, ctr.ID, container.LogsOptions{ + r, err := s.apiClient().ContainerLogs(ctx, ctr.ID, client.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Follow: options.Follow, diff --git a/pkg/compose/logs_test.go b/pkg/compose/logs_test.go index 955b5e770d..9469f39c5b 100644 --- a/pkg/compose/logs_test.go +++ b/pkg/compose/logs_test.go @@ -24,79 +24,79 @@ import ( "testing" "github.com/compose-spec/compose-go/v2/types" - containerType "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/pkg/stdcopy" - "github.com/stretchr/testify/assert" + containerType "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" compose "github.com/docker/compose/v2/pkg/api" ) -func TestComposeService_Logs_Demux(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - api, cli := prepareMocks(mockCtrl) - tested := composeService{ - dockerCli: cli, - } - - name := strings.ToLower(testProject) - - ctx := context.Background() - api.EXPECT().ContainerList(ctx, containerType.ListOptions{ - All: true, - Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()), - }).Return( - []containerType.Summary{ - testContainer("service", "c", false), - }, - nil, - ) - - api.EXPECT(). - ContainerInspect(anyCancellableContext(), "c"). - Return(containerType.InspectResponse{ - ContainerJSONBase: &containerType.ContainerJSONBase{ID: "c"}, - Config: &containerType.Config{Tty: false}, - }, nil) - c1Reader, c1Writer := io.Pipe() - t.Cleanup(func() { - _ = c1Reader.Close() - _ = c1Writer.Close() - }) - c1Stdout := stdcopy.NewStdWriter(c1Writer, stdcopy.Stdout) - c1Stderr := stdcopy.NewStdWriter(c1Writer, stdcopy.Stderr) - go func() { - _, err := c1Stdout.Write([]byte("hello stdout\n")) - assert.NoError(t, err, "Writing to fake stdout") - _, err = c1Stderr.Write([]byte("hello stderr\n")) - assert.NoError(t, err, "Writing to fake stderr") - _ = c1Writer.Close() - }() - api.EXPECT().ContainerLogs(anyCancellableContext(), "c", gomock.Any()). - Return(c1Reader, nil) - - opts := compose.LogOptions{ - Project: &types.Project{ - Services: types.Services{ - "service": {Name: "service"}, - }, - }, - } - - consumer := &testLogConsumer{} - err := tested.Logs(ctx, name, consumer, opts) - require.NoError(t, err) - - require.Equal( - t, - []string{"hello stdout", "hello stderr"}, - consumer.LogsForContainer("c"), - ) -} +// FIXME(thaJeztah): stdcopy.NewStdWriter was moved internal to the daemon, so can no longer be mocked. +// +// func TestComposeService_Logs_Demux(t *testing.T) { +// mockCtrl := gomock.NewController(t) +// defer mockCtrl.Finish() +// +// api, cli := prepareMocks(mockCtrl) +// tested := composeService{ +// dockerCli: cli, +// } +// +// name := strings.ToLower(testProject) +// +// ctx := context.Background() +// api.EXPECT().ContainerList(ctx, client.ContainerListOptions{ +// All: true, +// Filters: projectFilter(name).Add("label", oneOffFilter(false), hasConfigHashLabel()), +// }).Return( +// []containerType.Summary{ +// testContainer("service", "c", false), +// }, +// nil, +// ) +// +// api.EXPECT(). +// ContainerInspect(anyCancellableContext(), "c"). +// Return(containerType.InspectResponse{ +// ID: "c", +// Config: &containerType.Config{Tty: false}, +// }, nil) +// c1Reader, c1Writer := io.Pipe() +// t.Cleanup(func() { +// _ = c1Reader.Close() +// _ = c1Writer.Close() +// }) +// c1Stdout := stdcopy.NewStdWriter(c1Writer, stdcopy.Stdout) +// c1Stderr := stdcopy.NewStdWriter(c1Writer, stdcopy.Stderr) +// go func() { +// _, err := c1Stdout.Write([]byte("hello stdout\n")) +// assert.NoError(t, err, "Writing to fake stdout") +// _, err = c1Stderr.Write([]byte("hello stderr\n")) +// assert.NoError(t, err, "Writing to fake stderr") +// _ = c1Writer.Close() +// }() +// api.EXPECT().ContainerLogs(anyCancellableContext(), "c", gomock.Any()). +// Return(c1Reader, nil) +// +// opts := compose.LogOptions{ +// Project: &types.Project{ +// Services: types.Services{ +// "service": {Name: "service"}, +// }, +// }, +// } +// +// consumer := &testLogConsumer{} +// err := tested.Logs(ctx, name, consumer, opts) +// require.NoError(t, err) +// +// require.Equal( +// t, +// []string{"hello stdout", "hello stderr"}, +// consumer.LogsForContainer("c"), +// ) +// } // TestComposeService_Logs_ServiceFiltering ensures that we do not include // logs from out-of-scope services based on the Compose file vs actual state. @@ -117,9 +117,9 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) { name := strings.ToLower(testProject) ctx := context.Background() - api.EXPECT().ContainerList(ctx, containerType.ListOptions{ + api.EXPECT().ContainerList(ctx, client.ContainerListOptions{ All: true, - Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()), + Filters: projectFilter(name).Add("label", oneOffFilter(false), hasConfigHashLabel()), }).Return( []containerType.Summary{ testContainer("serviceA", "c1", false), @@ -137,8 +137,8 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) { ContainerInspect(anyCancellableContext(), id). Return( containerType.InspectResponse{ - ContainerJSONBase: &containerType.ContainerJSONBase{ID: id}, - Config: &containerType.Config{Tty: true}, + ID: id, + Config: &containerType.Config{Tty: true}, }, nil, ) diff --git a/pkg/compose/ls.go b/pkg/compose/ls.go index 403b061a8a..cc9890ddd6 100644 --- a/pkg/compose/ls.go +++ b/pkg/compose/ls.go @@ -24,14 +24,14 @@ import ( "strings" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" ) func (s *composeService) List(ctx context.Context, opts api.ListOptions) ([]api.Stack, error) { - list, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs(hasProjectLabelFilter(), hasConfigHashLabel()), + list, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: make(client.Filters).Add("label", api.ProjectLabel).Add("label", api.ConfigHashLabel), All: opts.All, }) if err != nil { diff --git a/pkg/compose/ls_test.go b/pkg/compose/ls_test.go index 847814c6f6..e30d0841bc 100644 --- a/pkg/compose/ls_test.go +++ b/pkg/compose/ls_test.go @@ -21,7 +21,7 @@ import ( "testing" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" "gotest.tools/v3/assert" ) diff --git a/pkg/compose/monitor.go b/pkg/compose/monitor.go index 983eced9ed..3850356036 100644 --- a/pkg/compose/monitor.go +++ b/pkg/compose/monitor.go @@ -21,10 +21,8 @@ import ( "strconv" "github.com/containerd/errdefs" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" + "github.com/moby/moby/api/types/events" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" "github.com/docker/compose/v2/pkg/api" @@ -39,9 +37,9 @@ type monitor struct { listeners []api.ContainerEventListener } -func newMonitor(api client.APIClient, project string) *monitor { +func newMonitor(apiClient client.APIClient, project string) *monitor { return &monitor{ - api: api, + api: apiClient, project: project, services: map[string]bool{}, } @@ -58,10 +56,9 @@ func (c *monitor) withServices(services []string) { //nolint:gocyclo func (c *monitor) Start(ctx context.Context) error { // collect initial application container - initialState, err := c.api.ContainerList(ctx, container.ListOptions{ + initialState, err := c.api.ContainerList(ctx, client.ContainerListOptions{ All: true, - Filters: filters.NewArgs( - projectFilter(c.project), + Filters: projectFilter(c.project).Add("label", oneOffFilter(false), hasConfigHashLabel(), ), @@ -79,10 +76,8 @@ func (c *monitor) Start(ctx context.Context) error { } restarting := utils.Set[string]{} - evtCh, errCh := c.api.Events(ctx, events.ListOptions{ - Filters: filters.NewArgs( - filters.Arg("type", "container"), - projectFilter(c.project)), + evtCh, errCh := c.api.Events(ctx, client.EventsListOptions{ + Filters: projectFilter(c.project).Add("type", "container"), }) for { if len(containers) == 0 { diff --git a/pkg/compose/pause.go b/pkg/compose/pause.go index 4f86d0e092..2de227c36d 100644 --- a/pkg/compose/pause.go +++ b/pkg/compose/pause.go @@ -20,7 +20,7 @@ import ( "context" "strings" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/api" diff --git a/pkg/compose/port.go b/pkg/compose/port.go index 35c2832ac2..379231fa88 100644 --- a/pkg/compose/port.go +++ b/pkg/compose/port.go @@ -22,7 +22,7 @@ import ( "strings" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" ) func (s *composeService) Port(ctx context.Context, projectName string, service string, port uint16, options api.PortOptions) (string, int, error) { @@ -33,7 +33,7 @@ func (s *composeService) Port(ctx context.Context, projectName string, service s } for _, p := range ctr.Ports { if p.PrivatePort == port && p.Type == options.Protocol { - return p.IP, int(p.PublicPort), nil + return p.IP.String(), int(p.PublicPort), nil } } return "", 0, portNotFoundError(options.Protocol, port, ctr) diff --git a/pkg/compose/ps.go b/pkg/compose/ps.go index 42dfd272b0..eaf93855d8 100644 --- a/pkg/compose/ps.go +++ b/pkg/compose/ps.go @@ -21,7 +21,7 @@ import ( "sort" "strings" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/api" @@ -51,7 +51,7 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api }) for i, p := range ctr.Ports { publishers[i] = api.PortPublisher{ - URL: p.IP, + URL: p.IP.String(), TargetPort: int(p.PrivatePort), PublishedPort: int(p.PublicPort), Protocol: p.Type, diff --git a/pkg/compose/ps_test.go b/pkg/compose/ps_test.go index ac2230e4dd..d98f582e61 100644 --- a/pkg/compose/ps_test.go +++ b/pkg/compose/ps_test.go @@ -18,11 +18,12 @@ package compose import ( "context" + "net/netip" "strings" "testing" - containerType "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" + containerType "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -39,12 +40,13 @@ func TestPs(t *testing.T) { } ctx := context.Background() - args := filters.NewArgs(projectFilter(strings.ToLower(testProject)), hasConfigHashLabel()) - args.Add("label", "com.docker.compose.oneoff=False") - listOpts := containerType.ListOptions{Filters: args, All: false} + listOpts := client.ContainerListOptions{ + Filters: projectFilter(strings.ToLower(testProject)).Add("label", hasConfigHashLabel(), oneOffFilter(false)), + All: false, + } c1, inspect1 := containerDetails("service1", "123", containerType.StateRunning, containerType.Healthy, 0) c2, inspect2 := containerDetails("service1", "456", containerType.StateRunning, "", 0) - c2.Ports = []containerType.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}} + c2.Ports = []containerType.PortSummary{{PublicPort: 80, PrivatePort: 90, IP: netip.MustParseAddr("127.0.0.1")}} c3, inspect3 := containerDetails("service2", "789", containerType.StateExited, "", 130) api.EXPECT().ContainerList(ctx, listOpts).Return([]containerType.Summary{c1, c2, c3}, nil) api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil) @@ -70,7 +72,7 @@ func TestPs(t *testing.T) { ID: "456", Name: "456", Names: []string{"/456"}, Image: "foo", Project: strings.ToLower(testProject), Service: "service1", State: containerType.StateRunning, Health: "", - Publishers: []compose.PortPublisher{{URL: "localhost", TargetPort: 90, PublishedPort: 80}}, + Publishers: []compose.PortPublisher{{URL: "127.0.0.1", TargetPort: 90, PublishedPort: 80}}, Labels: map[string]string{ compose.ProjectLabel: strings.ToLower(testProject), compose.ConfigFilesLabel: "/src/pkg/compose/testdata/compose.yaml", @@ -105,12 +107,10 @@ func containerDetails(service string, id string, status containerType.ContainerS State: status, } inspect := containerType.InspectResponse{ - ContainerJSONBase: &containerType.ContainerJSONBase{ - State: &containerType.State{ - Status: status, - Health: &containerType.Health{Status: health}, - ExitCode: exitCode, - }, + State: &containerType.State{ + Status: status, + Health: &containerType.Health{Status: health}, + ExitCode: exitCode, }, } return ctr, inspect diff --git a/pkg/compose/pull.go b/pkg/compose/pull.go index 684e6635f2..8b6ecf9138 100644 --- a/pkg/compose/pull.go +++ b/pkg/compose/pull.go @@ -31,9 +31,8 @@ import ( "github.com/distribution/reference" "github.com/docker/buildx/driver" "github.com/docker/cli/cli/config/configfile" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/jsonmessage" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" "github.com/opencontainers/go-digest" "golang.org/x/sync/errgroup" @@ -198,7 +197,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser platform = defaultPlatform } - stream, err := s.apiClient().ImagePull(ctx, service.Image, image.PullOptions{ + stream, err := s.apiClient().ImagePull(ctx, service.Image, client.ImagePullOptions{ RegistryAuth: encodedAuth, Platform: platform, }) diff --git a/pkg/compose/push.go b/pkg/compose/push.go index 8d8b3691b0..ad8de61ca1 100644 --- a/pkg/compose/push.go +++ b/pkg/compose/push.go @@ -28,8 +28,8 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/distribution/reference" "github.com/docker/buildx/driver" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/pkg/jsonmessage" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/internal/registry" @@ -100,7 +100,7 @@ func (s *composeService) pushServiceImage(ctx context.Context, tag string, confi return err } - stream, err := s.apiClient().ImagePush(ctx, tag, image.PushOptions{ + stream, err := s.apiClient().ImagePush(ctx, tag, client.ImagePushOptions{ RegistryAuth: base64.URLEncoding.EncodeToString(buf), }) if err != nil { diff --git a/pkg/compose/remove.go b/pkg/compose/remove.go index e8515a79a7..a5d8098745 100644 --- a/pkg/compose/remove.go +++ b/pkg/compose/remove.go @@ -22,7 +22,8 @@ import ( "strings" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/progress" @@ -105,7 +106,7 @@ func (s *composeService) remove(ctx context.Context, containers Containers, opti eg.Go(func() error { eventName := getContainerProgressName(ctr) w.Event(progress.RemovingEvent(eventName)) - err := s.apiClient().ContainerRemove(ctx, ctr.ID, container.RemoveOptions{ + err := s.apiClient().ContainerRemove(ctx, ctr.ID, client.ContainerRemoveOptions{ RemoveVolumes: options.Volumes, Force: options.Force, }) diff --git a/pkg/compose/restart.go b/pkg/compose/restart.go index 4de9622310..c937abf332 100644 --- a/pkg/compose/restart.go +++ b/pkg/compose/restart.go @@ -24,7 +24,7 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" "github.com/docker/compose/v2/pkg/utils" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/client" "golang.org/x/sync/errgroup" ) @@ -89,7 +89,7 @@ func (s *composeService) restart(ctx context.Context, projectName string, option eventName := getContainerProgressName(ctr) w.Event(progress.RestartingEvent(eventName)) timeout := utils.DurationSecondToInt(options.Timeout) - err = s.apiClient().ContainerRestart(ctx, ctr.ID, container.StopOptions{Timeout: timeout}) + err = s.apiClient().ContainerRestart(ctx, ctr.ID, client.ContainerStopOptions{Timeout: timeout}) if err != nil { return err } diff --git a/pkg/compose/run.go b/pkg/compose/run.go index 242f2fc1cc..7ed8b5a174 100644 --- a/pkg/compose/run.go +++ b/pkg/compose/run.go @@ -29,7 +29,7 @@ import ( cmd "github.com/docker/cli/cli/command/container" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" - "github.com/docker/docker/pkg/stringid" + "github.com/moby/moby/client/pkg/stringid" ) func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts api.RunOptions) (int, error) { diff --git a/pkg/compose/secrets.go b/pkg/compose/secrets.go index e8064cca8b..ca32bfad12 100644 --- a/pkg/compose/secrets.go +++ b/pkg/compose/secrets.go @@ -25,7 +25,7 @@ import ( "time" "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/docker/api/types/container" + "github.com/moby/moby/client" ) func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error { @@ -58,7 +58,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje return err } - err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{ + err = s.apiClient().CopyToContainer(ctx, id, "/", &b, client.CopyToContainerOptions{ CopyUIDGID: config.UID != "" || config.GID != "", }) if err != nil { @@ -96,7 +96,7 @@ func (s *composeService) injectConfigs(ctx context.Context, project *types.Proje return err } - err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{ + err = s.apiClient().CopyToContainer(ctx, id, "/", &b, client.CopyToContainerOptions{ CopyUIDGID: config.UID != "" || config.GID != "", }) if err != nil { diff --git a/pkg/compose/start.go b/pkg/compose/start.go index b0bde1f688..5761007798 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -24,10 +24,9 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" - containerType "github.com/docker/docker/api/types/container" + "github.com/moby/moby/client" "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/docker/api/types/filters" ) func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error { @@ -52,12 +51,9 @@ func (s *composeService) start(ctx context.Context, projectName string, options } var containers Containers - containers, err := s.apiClient().ContainerList(ctx, containerType.ListOptions{ - Filters: filters.NewArgs( - projectFilter(project.Name), - oneOffFilter(false), - ), - All: true, + containers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: projectFilter(project.Name).Add("label", oneOffFilter(false)), + All: true, }) if err != nil { return err diff --git a/pkg/compose/stop_test.go b/pkg/compose/stop_test.go index 9c5d79ef7e..7b8f3a433f 100644 --- a/pkg/compose/stop_test.go +++ b/pkg/compose/stop_test.go @@ -22,10 +22,10 @@ import ( "testing" "time" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -51,15 +51,15 @@ func TestStopTimeout(t *testing.T) { }, nil) api.EXPECT().VolumeList( gomock.Any(), - volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + client.VolumeListOptions{ + Filters: projectFilter(strings.ToLower(testProject)), }). Return(volume.ListResponse{}, nil) - api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + api.EXPECT().NetworkList(gomock.Any(), client.NetworkListOptions{Filters: projectFilter(strings.ToLower(testProject))}). Return([]network.Summary{}, nil) timeout := 2 * time.Second - stopConfig := container.StopOptions{Timeout: utils.DurationSecondToInt(&timeout)} + stopConfig := client.ContainerStopOptions{Timeout: utils.DurationSecondToInt(&timeout)} api.EXPECT().ContainerStop(gomock.Any(), "123", stopConfig).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "456", stopConfig).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "789", stopConfig).Return(nil) diff --git a/pkg/compose/volumes.go b/pkg/compose/volumes.go index 0967a719db..d66527d997 100644 --- a/pkg/compose/volumes.go +++ b/pkg/compose/volumes.go @@ -21,14 +21,13 @@ import ( "slices" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) func (s *composeService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) { - allContainers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs(projectFilter(project)), + allContainers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + Filters: projectFilter(project), }) if err != nil { return nil, err @@ -47,8 +46,8 @@ func (s *composeService) Volumes(ctx context.Context, project string, options ap containers = allContainers } - volumesResponse, err := s.apiClient().VolumeList(ctx, volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(project)), + volumesResponse, err := s.apiClient().VolumeList(ctx, client.VolumeListOptions{ + Filters: projectFilter(project), }) if err != nil { return nil, err @@ -65,8 +64,8 @@ func (s *composeService) Volumes(ctx context.Context, project string, options ap // create a name lookup of volumes used by containers serviceVolumes := make(map[string]bool) - for _, container := range containers { - for _, mount := range container.Mounts { + for _, ctr := range containers { + for _, mount := range ctr.Mounts { serviceVolumes[mount.Name] = true } } diff --git a/pkg/compose/volumes_test.go b/pkg/compose/volumes_test.go index ab0fbcc792..48b8a5d09a 100644 --- a/pkg/compose/volumes_test.go +++ b/pkg/compose/volumes_test.go @@ -21,9 +21,9 @@ import ( "testing" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/volume" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/volume" + "github.com/moby/moby/client" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" ) @@ -58,10 +58,8 @@ func TestVolumes(t *testing.T) { } ctx := context.Background() - args := filters.NewArgs(projectFilter(testProject)) - listOpts := container.ListOptions{Filters: args} - volumeListArgs := filters.NewArgs(projectFilter(testProject)) - volumeListOpts := volume.ListOptions{Filters: volumeListArgs} + listOpts := client.ContainerListOptions{Filters: projectFilter(testProject)} + volumeListOpts := client.VolumeListOptions{Filters: projectFilter(testProject)} volumeReturn := volume.ListResponse{ Volumes: []*volume.Volume{vol1, vol2, vol3}, } diff --git a/pkg/compose/watch.go b/pkg/compose/watch.go index 644a4dced9..de3e26b690 100644 --- a/pkg/compose/watch.go +++ b/pkg/compose/watch.go @@ -40,10 +40,9 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/compose-spec/compose-go/v2/utils" ccli "github.com/docker/cli/cli/command/container" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" "github.com/go-viper/mapstructure/v2" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -442,7 +441,7 @@ func (t tarDockerClient) ContainersForService(ctx context.Context, projectName s } func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []string, in io.Reader) error { - execCfg := container.ExecOptions{ + execCfg := client.ExecCreateOptions{ Cmd: cmd, AttachStdout: false, AttachStderr: true, @@ -454,7 +453,7 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str return err } - startCheck := container.ExecStartOptions{Tty: false, Detach: false} + startCheck := client.ExecStartOptions{Tty: false, Detach: false} conn, err := t.s.apiClient().ContainerExecAttach(ctx, execCreateResp.ID, startCheck) if err != nil { return err @@ -502,7 +501,7 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str } func (t tarDockerClient) Untar(ctx context.Context, id string, archive io.ReadCloser) error { - return t.s.apiClient().CopyToContainer(ctx, id, "/", archive, container.CopyToContainerOptions{ + return t.s.apiClient().CopyToContainer(ctx, id, "/", archive, client.CopyToContainerOptions{ CopyUIDGID: true, }) } @@ -687,11 +686,8 @@ func writeWatchSyncMessage(log api.LogConsumer, serviceName string, pathMappings } func (s *composeService) pruneDanglingImagesOnRebuild(ctx context.Context, projectName string, imageNameToIdMap map[string]string) { - images, err := s.apiClient().ImageList(ctx, image.ListOptions{ - Filters: filters.NewArgs( - filters.Arg("dangling", "true"), - filters.Arg("label", api.ProjectLabel+"="+projectName), - ), + images, err := s.apiClient().ImageList(ctx, client.ImageListOptions{ + Filters: projectFilter(projectName).Add("dangling", "true"), }) if err != nil { logrus.Debugf("Failed to list images: %v", err) @@ -700,7 +696,7 @@ func (s *composeService) pruneDanglingImagesOnRebuild(ctx context.Context, proje for _, img := range images { if _, ok := imageNameToIdMap[img.ID]; !ok { - _, err := s.apiClient().ImageRemove(ctx, img.ID, image.RemoveOptions{}) + _, err := s.apiClient().ImageRemove(ctx, img.ID, client.ImageRemoveOptions{}) if err != nil { logrus.Debugf("Failed to remove image %s: %v", img.ID, err) } @@ -814,11 +810,9 @@ func shouldIgnore(name string, ignore watch.PathMatcher) bool { // gets the image creation time for a service func (s *composeService) imageCreatedTime(ctx context.Context, project *types.Project, serviceName string) (time.Time, error) { - containers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - All: true, - Filters: filters.NewArgs( - filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, project.Name)), - filters.Arg("label", fmt.Sprintf("%s=%s", api.ServiceLabel, serviceName))), + containers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{ + All: true, + Filters: projectFilter(project.Name).Add("label", serviceFilter(serviceName)), }) if err != nil { return time.Now(), err diff --git a/pkg/compose/watch_test.go b/pkg/compose/watch_test.go index c009fdfc04..cb9841d453 100644 --- a/pkg/compose/watch_test.go +++ b/pkg/compose/watch_test.go @@ -27,10 +27,10 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/mocks" "github.com/docker/compose/v2/pkg/watch" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" "github.com/jonboulle/clockwork" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/client" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" @@ -80,17 +80,16 @@ func TestWatch_Sync(t *testing.T) { testContainer("test", "123", false), }, nil).AnyTimes() // we expect the image to be pruned - apiClient.EXPECT().ImageList(gomock.Any(), image.ListOptions{ - Filters: filters.NewArgs( - filters.Arg("dangling", "true"), - filters.Arg("label", api.ProjectLabel+"=myProjectName"), - ), + apiClient.EXPECT().ImageList(gomock.Any(), client.ImageListOptions{ + Filters: make(client.Filters). + Add("dangling", "true"). + Add("label", api.ProjectLabel+"=myProjectName"), }).Return([]image.Summary{ {ID: "123"}, {ID: "456"}, }, nil).Times(1) - apiClient.EXPECT().ImageRemove(gomock.Any(), "123", image.RemoveOptions{}).Times(1) - apiClient.EXPECT().ImageRemove(gomock.Any(), "456", image.RemoveOptions{}).Times(1) + apiClient.EXPECT().ImageRemove(gomock.Any(), "123", client.ImageRemoveOptions{}).Times(1) + apiClient.EXPECT().ImageRemove(gomock.Any(), "456", client.ImageRemoveOptions{}).Times(1) // cli.EXPECT().Client().Return(apiClient).AnyTimes() diff --git a/pkg/mocks/mock_docker_api.go b/pkg/mocks/mock_docker_api.go index 4a6ebaaccf..0e0e50a9cf 100644 --- a/pkg/mocks/mock_docker_api.go +++ b/pkg/mocks/mock_docker_api.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/docker/docker/client (interfaces: APIClient) +// Source: github.com/moby/moby/client (interfaces: APIClient) // // Generated by this command: // -// mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/docker/docker/client APIClient +// mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/moby/moby/client APIClient // // Package mocks is a generated GoMock package. @@ -13,23 +13,20 @@ import ( context "context" io "io" net "net" - http "net/http" reflect "reflect" - types "github.com/docker/docker/api/types" - build "github.com/docker/docker/api/types/build" - checkpoint "github.com/docker/docker/api/types/checkpoint" - common "github.com/docker/docker/api/types/common" - container "github.com/docker/docker/api/types/container" - events "github.com/docker/docker/api/types/events" - filters "github.com/docker/docker/api/types/filters" - image "github.com/docker/docker/api/types/image" - network "github.com/docker/docker/api/types/network" - registry "github.com/docker/docker/api/types/registry" - swarm "github.com/docker/docker/api/types/swarm" - system "github.com/docker/docker/api/types/system" - volume "github.com/docker/docker/api/types/volume" - client "github.com/docker/docker/client" + types "github.com/moby/moby/api/types" + common "github.com/moby/moby/api/types/common" + container "github.com/moby/moby/api/types/container" + events "github.com/moby/moby/api/types/events" + image "github.com/moby/moby/api/types/image" + network "github.com/moby/moby/api/types/network" + plugin "github.com/moby/moby/api/types/plugin" + registry "github.com/moby/moby/api/types/registry" + swarm "github.com/moby/moby/api/types/swarm" + system "github.com/moby/moby/api/types/system" + volume "github.com/moby/moby/api/types/volume" + client "github.com/moby/moby/client" v1 "github.com/opencontainers/image-spec/specs-go/v1" gomock "go.uber.org/mock/gomock" ) @@ -58,10 +55,10 @@ func (m *MockAPIClient) EXPECT() *MockAPIClientMockRecorder { } // BuildCachePrune mocks base method. -func (m *MockAPIClient) BuildCachePrune(arg0 context.Context, arg1 build.CachePruneOptions) (*build.CachePruneReport, error) { +func (m *MockAPIClient) BuildCachePrune(arg0 context.Context, arg1 client.BuildCachePruneOptions) (client.BuildCachePruneResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BuildCachePrune", arg0, arg1) - ret0, _ := ret[0].(*build.CachePruneReport) + ret0, _ := ret[0].(client.BuildCachePruneResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -73,21 +70,21 @@ func (mr *MockAPIClientMockRecorder) BuildCachePrune(arg0, arg1 any) *gomock.Cal } // BuildCancel mocks base method. -func (m *MockAPIClient) BuildCancel(arg0 context.Context, arg1 string) error { +func (m *MockAPIClient) BuildCancel(arg0 context.Context, arg1 string, arg2 client.BuildCancelOptions) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BuildCancel", arg0, arg1) + ret := m.ctrl.Call(m, "BuildCancel", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // BuildCancel indicates an expected call of BuildCancel. -func (mr *MockAPIClientMockRecorder) BuildCancel(arg0, arg1 any) *gomock.Call { +func (mr *MockAPIClientMockRecorder) BuildCancel(arg0, arg1, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildCancel", reflect.TypeOf((*MockAPIClient)(nil).BuildCancel), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildCancel", reflect.TypeOf((*MockAPIClient)(nil).BuildCancel), arg0, arg1, arg2) } // CheckpointCreate mocks base method. -func (m *MockAPIClient) CheckpointCreate(arg0 context.Context, arg1 string, arg2 checkpoint.CreateOptions) error { +func (m *MockAPIClient) CheckpointCreate(arg0 context.Context, arg1 string, arg2 client.CheckpointCreateOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CheckpointCreate", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -101,7 +98,7 @@ func (mr *MockAPIClientMockRecorder) CheckpointCreate(arg0, arg1, arg2 any) *gom } // CheckpointDelete mocks base method. -func (m *MockAPIClient) CheckpointDelete(arg0 context.Context, arg1 string, arg2 checkpoint.DeleteOptions) error { +func (m *MockAPIClient) CheckpointDelete(arg0 context.Context, arg1 string, arg2 client.CheckpointDeleteOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CheckpointDelete", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -115,10 +112,10 @@ func (mr *MockAPIClientMockRecorder) CheckpointDelete(arg0, arg1, arg2 any) *gom } // CheckpointList mocks base method. -func (m *MockAPIClient) CheckpointList(arg0 context.Context, arg1 string, arg2 checkpoint.ListOptions) ([]checkpoint.Summary, error) { +func (m *MockAPIClient) CheckpointList(arg0 context.Context, arg1 string, arg2 client.CheckpointListOptions) (client.CheckpointListResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CheckpointList", arg0, arg1, arg2) - ret0, _ := ret[0].([]checkpoint.Summary) + ret0, _ := ret[0].(client.CheckpointListResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -189,7 +186,7 @@ func (mr *MockAPIClientMockRecorder) ConfigInspectWithRaw(arg0, arg1 any) *gomoc } // ConfigList mocks base method. -func (m *MockAPIClient) ConfigList(arg0 context.Context, arg1 swarm.ConfigListOptions) ([]swarm.Config, error) { +func (m *MockAPIClient) ConfigList(arg0 context.Context, arg1 client.ConfigListOptions) ([]swarm.Config, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ConfigList", arg0, arg1) ret0, _ := ret[0].([]swarm.Config) @@ -232,10 +229,10 @@ func (mr *MockAPIClientMockRecorder) ConfigUpdate(arg0, arg1, arg2, arg3 any) *g } // ContainerAttach mocks base method. -func (m *MockAPIClient) ContainerAttach(arg0 context.Context, arg1 string, arg2 container.AttachOptions) (types.HijackedResponse, error) { +func (m *MockAPIClient) ContainerAttach(arg0 context.Context, arg1 string, arg2 client.ContainerAttachOptions) (client.HijackedResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerAttach", arg0, arg1, arg2) - ret0, _ := ret[0].(types.HijackedResponse) + ret0, _ := ret[0].(client.HijackedResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -247,7 +244,7 @@ func (mr *MockAPIClientMockRecorder) ContainerAttach(arg0, arg1, arg2 any) *gomo } // ContainerCommit mocks base method. -func (m *MockAPIClient) ContainerCommit(arg0 context.Context, arg1 string, arg2 container.CommitOptions) (common.IDResponse, error) { +func (m *MockAPIClient) ContainerCommit(arg0 context.Context, arg1 string, arg2 client.ContainerCommitOptions) (common.IDResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerCommit", arg0, arg1, arg2) ret0, _ := ret[0].(common.IDResponse) @@ -292,10 +289,10 @@ func (mr *MockAPIClientMockRecorder) ContainerDiff(arg0, arg1 any) *gomock.Call } // ContainerExecAttach mocks base method. -func (m *MockAPIClient) ContainerExecAttach(arg0 context.Context, arg1 string, arg2 container.ExecStartOptions) (types.HijackedResponse, error) { +func (m *MockAPIClient) ContainerExecAttach(arg0 context.Context, arg1 string, arg2 client.ExecStartOptions) (client.HijackedResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerExecAttach", arg0, arg1, arg2) - ret0, _ := ret[0].(types.HijackedResponse) + ret0, _ := ret[0].(client.HijackedResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -307,7 +304,7 @@ func (mr *MockAPIClientMockRecorder) ContainerExecAttach(arg0, arg1, arg2 any) * } // ContainerExecCreate mocks base method. -func (m *MockAPIClient) ContainerExecCreate(arg0 context.Context, arg1 string, arg2 container.ExecOptions) (common.IDResponse, error) { +func (m *MockAPIClient) ContainerExecCreate(arg0 context.Context, arg1 string, arg2 client.ExecCreateOptions) (common.IDResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerExecCreate", arg0, arg1, arg2) ret0, _ := ret[0].(common.IDResponse) @@ -322,10 +319,10 @@ func (mr *MockAPIClientMockRecorder) ContainerExecCreate(arg0, arg1, arg2 any) * } // ContainerExecInspect mocks base method. -func (m *MockAPIClient) ContainerExecInspect(arg0 context.Context, arg1 string) (container.ExecInspect, error) { +func (m *MockAPIClient) ContainerExecInspect(arg0 context.Context, arg1 string) (client.ExecInspect, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerExecInspect", arg0, arg1) - ret0, _ := ret[0].(container.ExecInspect) + ret0, _ := ret[0].(client.ExecInspect) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -337,7 +334,7 @@ func (mr *MockAPIClientMockRecorder) ContainerExecInspect(arg0, arg1 any) *gomoc } // ContainerExecResize mocks base method. -func (m *MockAPIClient) ContainerExecResize(arg0 context.Context, arg1 string, arg2 container.ResizeOptions) error { +func (m *MockAPIClient) ContainerExecResize(arg0 context.Context, arg1 string, arg2 client.ContainerResizeOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerExecResize", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -351,7 +348,7 @@ func (mr *MockAPIClientMockRecorder) ContainerExecResize(arg0, arg1, arg2 any) * } // ContainerExecStart mocks base method. -func (m *MockAPIClient) ContainerExecStart(arg0 context.Context, arg1 string, arg2 container.ExecStartOptions) error { +func (m *MockAPIClient) ContainerExecStart(arg0 context.Context, arg1 string, arg2 client.ExecStartOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerExecStart", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -425,7 +422,7 @@ func (mr *MockAPIClientMockRecorder) ContainerKill(arg0, arg1, arg2 any) *gomock } // ContainerList mocks base method. -func (m *MockAPIClient) ContainerList(arg0 context.Context, arg1 container.ListOptions) ([]container.Summary, error) { +func (m *MockAPIClient) ContainerList(arg0 context.Context, arg1 client.ContainerListOptions) ([]container.Summary, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerList", arg0, arg1) ret0, _ := ret[0].([]container.Summary) @@ -440,7 +437,7 @@ func (mr *MockAPIClientMockRecorder) ContainerList(arg0, arg1 any) *gomock.Call } // ContainerLogs mocks base method. -func (m *MockAPIClient) ContainerLogs(arg0 context.Context, arg1 string, arg2 container.LogsOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ContainerLogs(arg0 context.Context, arg1 string, arg2 client.ContainerLogsOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerLogs", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -469,7 +466,7 @@ func (mr *MockAPIClientMockRecorder) ContainerPause(arg0, arg1 any) *gomock.Call } // ContainerRemove mocks base method. -func (m *MockAPIClient) ContainerRemove(arg0 context.Context, arg1 string, arg2 container.RemoveOptions) error { +func (m *MockAPIClient) ContainerRemove(arg0 context.Context, arg1 string, arg2 client.ContainerRemoveOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerRemove", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -497,7 +494,7 @@ func (mr *MockAPIClientMockRecorder) ContainerRename(arg0, arg1, arg2 any) *gomo } // ContainerResize mocks base method. -func (m *MockAPIClient) ContainerResize(arg0 context.Context, arg1 string, arg2 container.ResizeOptions) error { +func (m *MockAPIClient) ContainerResize(arg0 context.Context, arg1 string, arg2 client.ContainerResizeOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerResize", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -511,7 +508,7 @@ func (mr *MockAPIClientMockRecorder) ContainerResize(arg0, arg1, arg2 any) *gomo } // ContainerRestart mocks base method. -func (m *MockAPIClient) ContainerRestart(arg0 context.Context, arg1 string, arg2 container.StopOptions) error { +func (m *MockAPIClient) ContainerRestart(arg0 context.Context, arg1 string, arg2 client.ContainerStopOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerRestart", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -525,7 +522,7 @@ func (mr *MockAPIClientMockRecorder) ContainerRestart(arg0, arg1, arg2 any) *gom } // ContainerStart mocks base method. -func (m *MockAPIClient) ContainerStart(arg0 context.Context, arg1 string, arg2 container.StartOptions) error { +func (m *MockAPIClient) ContainerStart(arg0 context.Context, arg1 string, arg2 client.ContainerStartOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerStart", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -554,10 +551,10 @@ func (mr *MockAPIClientMockRecorder) ContainerStatPath(arg0, arg1, arg2 any) *go } // ContainerStats mocks base method. -func (m *MockAPIClient) ContainerStats(arg0 context.Context, arg1 string, arg2 bool) (container.StatsResponseReader, error) { +func (m *MockAPIClient) ContainerStats(arg0 context.Context, arg1 string, arg2 bool) (client.StatsResponseReader, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerStats", arg0, arg1, arg2) - ret0, _ := ret[0].(container.StatsResponseReader) + ret0, _ := ret[0].(client.StatsResponseReader) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -569,10 +566,10 @@ func (mr *MockAPIClientMockRecorder) ContainerStats(arg0, arg1, arg2 any) *gomoc } // ContainerStatsOneShot mocks base method. -func (m *MockAPIClient) ContainerStatsOneShot(arg0 context.Context, arg1 string) (container.StatsResponseReader, error) { +func (m *MockAPIClient) ContainerStatsOneShot(arg0 context.Context, arg1 string) (client.StatsResponseReader, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerStatsOneShot", arg0, arg1) - ret0, _ := ret[0].(container.StatsResponseReader) + ret0, _ := ret[0].(client.StatsResponseReader) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -584,7 +581,7 @@ func (mr *MockAPIClientMockRecorder) ContainerStatsOneShot(arg0, arg1 any) *gomo } // ContainerStop mocks base method. -func (m *MockAPIClient) ContainerStop(arg0 context.Context, arg1 string, arg2 container.StopOptions) error { +func (m *MockAPIClient) ContainerStop(arg0 context.Context, arg1 string, arg2 client.ContainerStopOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainerStop", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -657,7 +654,7 @@ func (mr *MockAPIClientMockRecorder) ContainerWait(arg0, arg1, arg2 any) *gomock } // ContainersPrune mocks base method. -func (m *MockAPIClient) ContainersPrune(arg0 context.Context, arg1 filters.Args) (container.PruneReport, error) { +func (m *MockAPIClient) ContainersPrune(arg0 context.Context, arg1 client.Filters) (container.PruneReport, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ContainersPrune", arg0, arg1) ret0, _ := ret[0].(container.PruneReport) @@ -688,7 +685,7 @@ func (mr *MockAPIClientMockRecorder) CopyFromContainer(arg0, arg1, arg2 any) *go } // CopyToContainer mocks base method. -func (m *MockAPIClient) CopyToContainer(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 container.CopyToContainerOptions) error { +func (m *MockAPIClient) CopyToContainer(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 client.CopyToContainerOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CopyToContainer", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(error) @@ -745,10 +742,10 @@ func (mr *MockAPIClientMockRecorder) Dialer() *gomock.Call { } // DiskUsage mocks base method. -func (m *MockAPIClient) DiskUsage(arg0 context.Context, arg1 types.DiskUsageOptions) (types.DiskUsage, error) { +func (m *MockAPIClient) DiskUsage(arg0 context.Context, arg1 client.DiskUsageOptions) (system.DiskUsage, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DiskUsage", arg0, arg1) - ret0, _ := ret[0].(types.DiskUsage) + ret0, _ := ret[0].(system.DiskUsage) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -775,7 +772,7 @@ func (mr *MockAPIClientMockRecorder) DistributionInspect(arg0, arg1, arg2 any) * } // Events mocks base method. -func (m *MockAPIClient) Events(arg0 context.Context, arg1 events.ListOptions) (<-chan events.Message, <-chan error) { +func (m *MockAPIClient) Events(arg0 context.Context, arg1 client.EventsListOptions) (<-chan events.Message, <-chan error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Events", arg0, arg1) ret0, _ := ret[0].(<-chan events.Message) @@ -789,25 +786,11 @@ func (mr *MockAPIClientMockRecorder) Events(arg0, arg1 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Events", reflect.TypeOf((*MockAPIClient)(nil).Events), arg0, arg1) } -// HTTPClient mocks base method. -func (m *MockAPIClient) HTTPClient() *http.Client { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HTTPClient") - ret0, _ := ret[0].(*http.Client) - return ret0 -} - -// HTTPClient indicates an expected call of HTTPClient. -func (mr *MockAPIClientMockRecorder) HTTPClient() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HTTPClient", reflect.TypeOf((*MockAPIClient)(nil).HTTPClient)) -} - // ImageBuild mocks base method. -func (m *MockAPIClient) ImageBuild(arg0 context.Context, arg1 io.Reader, arg2 build.ImageBuildOptions) (build.ImageBuildResponse, error) { +func (m *MockAPIClient) ImageBuild(arg0 context.Context, arg1 io.Reader, arg2 client.ImageBuildOptions) (client.ImageBuildResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageBuild", arg0, arg1, arg2) - ret0, _ := ret[0].(build.ImageBuildResponse) + ret0, _ := ret[0].(client.ImageBuildResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -819,7 +802,7 @@ func (mr *MockAPIClientMockRecorder) ImageBuild(arg0, arg1, arg2 any) *gomock.Ca } // ImageCreate mocks base method. -func (m *MockAPIClient) ImageCreate(arg0 context.Context, arg1 string, arg2 image.CreateOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ImageCreate(arg0 context.Context, arg1 string, arg2 client.ImageCreateOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageCreate", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -854,7 +837,7 @@ func (mr *MockAPIClientMockRecorder) ImageHistory(arg0, arg1 any, arg2 ...any) * } // ImageImport mocks base method. -func (m *MockAPIClient) ImageImport(arg0 context.Context, arg1 image.ImportSource, arg2 string, arg3 image.ImportOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ImageImport(arg0 context.Context, arg1 client.ImageImportSource, arg2 string, arg3 client.ImageImportOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageImport", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(io.ReadCloser) @@ -888,24 +871,8 @@ func (mr *MockAPIClientMockRecorder) ImageInspect(arg0, arg1 any, arg2 ...any) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageInspect", reflect.TypeOf((*MockAPIClient)(nil).ImageInspect), varargs...) } -// ImageInspectWithRaw mocks base method. -func (m *MockAPIClient) ImageInspectWithRaw(arg0 context.Context, arg1 string) (image.InspectResponse, []byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ImageInspectWithRaw", arg0, arg1) - ret0, _ := ret[0].(image.InspectResponse) - ret1, _ := ret[1].([]byte) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// ImageInspectWithRaw indicates an expected call of ImageInspectWithRaw. -func (mr *MockAPIClientMockRecorder) ImageInspectWithRaw(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageInspectWithRaw", reflect.TypeOf((*MockAPIClient)(nil).ImageInspectWithRaw), arg0, arg1) -} - // ImageList mocks base method. -func (m *MockAPIClient) ImageList(arg0 context.Context, arg1 image.ListOptions) ([]image.Summary, error) { +func (m *MockAPIClient) ImageList(arg0 context.Context, arg1 client.ImageListOptions) ([]image.Summary, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageList", arg0, arg1) ret0, _ := ret[0].([]image.Summary) @@ -920,14 +887,14 @@ func (mr *MockAPIClientMockRecorder) ImageList(arg0, arg1 any) *gomock.Call { } // ImageLoad mocks base method. -func (m *MockAPIClient) ImageLoad(arg0 context.Context, arg1 io.Reader, arg2 ...client.ImageLoadOption) (image.LoadResponse, error) { +func (m *MockAPIClient) ImageLoad(arg0 context.Context, arg1 io.Reader, arg2 ...client.ImageLoadOption) (client.LoadResponse, error) { m.ctrl.T.Helper() varargs := []any{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "ImageLoad", varargs...) - ret0, _ := ret[0].(image.LoadResponse) + ret0, _ := ret[0].(client.LoadResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -940,10 +907,10 @@ func (mr *MockAPIClientMockRecorder) ImageLoad(arg0, arg1 any, arg2 ...any) *gom } // ImagePull mocks base method. -func (m *MockAPIClient) ImagePull(arg0 context.Context, arg1 string, arg2 image.PullOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ImagePull(arg0 context.Context, arg1 string, arg2 client.ImagePullOptions) (client.ImagePullResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImagePull", arg0, arg1, arg2) - ret0, _ := ret[0].(io.ReadCloser) + ret0, _ := ret[0].(client.ImagePullResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -955,7 +922,7 @@ func (mr *MockAPIClientMockRecorder) ImagePull(arg0, arg1, arg2 any) *gomock.Cal } // ImagePush mocks base method. -func (m *MockAPIClient) ImagePush(arg0 context.Context, arg1 string, arg2 image.PushOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ImagePush(arg0 context.Context, arg1 string, arg2 client.ImagePushOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImagePush", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -970,7 +937,7 @@ func (mr *MockAPIClientMockRecorder) ImagePush(arg0, arg1, arg2 any) *gomock.Cal } // ImageRemove mocks base method. -func (m *MockAPIClient) ImageRemove(arg0 context.Context, arg1 string, arg2 image.RemoveOptions) ([]image.DeleteResponse, error) { +func (m *MockAPIClient) ImageRemove(arg0 context.Context, arg1 string, arg2 client.ImageRemoveOptions) ([]image.DeleteResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageRemove", arg0, arg1, arg2) ret0, _ := ret[0].([]image.DeleteResponse) @@ -1005,7 +972,7 @@ func (mr *MockAPIClientMockRecorder) ImageSave(arg0, arg1 any, arg2 ...any) *gom } // ImageSearch mocks base method. -func (m *MockAPIClient) ImageSearch(arg0 context.Context, arg1 string, arg2 registry.SearchOptions) ([]registry.SearchResult, error) { +func (m *MockAPIClient) ImageSearch(arg0 context.Context, arg1 string, arg2 client.ImageSearchOptions) ([]registry.SearchResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImageSearch", arg0, arg1, arg2) ret0, _ := ret[0].([]registry.SearchResult) @@ -1034,7 +1001,7 @@ func (mr *MockAPIClientMockRecorder) ImageTag(arg0, arg1, arg2 any) *gomock.Call } // ImagesPrune mocks base method. -func (m *MockAPIClient) ImagesPrune(arg0 context.Context, arg1 filters.Args) (image.PruneReport, error) { +func (m *MockAPIClient) ImagesPrune(arg0 context.Context, arg1 client.Filters) (image.PruneReport, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ImagesPrune", arg0, arg1) ret0, _ := ret[0].(image.PruneReport) @@ -1102,7 +1069,7 @@ func (mr *MockAPIClientMockRecorder) NetworkConnect(arg0, arg1, arg2, arg3 any) } // NetworkCreate mocks base method. -func (m *MockAPIClient) NetworkCreate(arg0 context.Context, arg1 string, arg2 network.CreateOptions) (network.CreateResponse, error) { +func (m *MockAPIClient) NetworkCreate(arg0 context.Context, arg1 string, arg2 client.NetworkCreateOptions) (network.CreateResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkCreate", arg0, arg1, arg2) ret0, _ := ret[0].(network.CreateResponse) @@ -1131,7 +1098,7 @@ func (mr *MockAPIClientMockRecorder) NetworkDisconnect(arg0, arg1, arg2, arg3 an } // NetworkInspect mocks base method. -func (m *MockAPIClient) NetworkInspect(arg0 context.Context, arg1 string, arg2 network.InspectOptions) (network.Inspect, error) { +func (m *MockAPIClient) NetworkInspect(arg0 context.Context, arg1 string, arg2 client.NetworkInspectOptions) (network.Inspect, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkInspect", arg0, arg1, arg2) ret0, _ := ret[0].(network.Inspect) @@ -1146,7 +1113,7 @@ func (mr *MockAPIClientMockRecorder) NetworkInspect(arg0, arg1, arg2 any) *gomoc } // NetworkInspectWithRaw mocks base method. -func (m *MockAPIClient) NetworkInspectWithRaw(arg0 context.Context, arg1 string, arg2 network.InspectOptions) (network.Inspect, []byte, error) { +func (m *MockAPIClient) NetworkInspectWithRaw(arg0 context.Context, arg1 string, arg2 client.NetworkInspectOptions) (network.Inspect, []byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkInspectWithRaw", arg0, arg1, arg2) ret0, _ := ret[0].(network.Inspect) @@ -1162,10 +1129,10 @@ func (mr *MockAPIClientMockRecorder) NetworkInspectWithRaw(arg0, arg1, arg2 any) } // NetworkList mocks base method. -func (m *MockAPIClient) NetworkList(arg0 context.Context, arg1 network.ListOptions) ([]network.Inspect, error) { +func (m *MockAPIClient) NetworkList(arg0 context.Context, arg1 client.NetworkListOptions) ([]network.Summary, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkList", arg0, arg1) - ret0, _ := ret[0].([]network.Inspect) + ret0, _ := ret[0].([]network.Summary) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1191,7 +1158,7 @@ func (mr *MockAPIClientMockRecorder) NetworkRemove(arg0, arg1 any) *gomock.Call } // NetworksPrune mocks base method. -func (m *MockAPIClient) NetworksPrune(arg0 context.Context, arg1 filters.Args) (network.PruneReport, error) { +func (m *MockAPIClient) NetworksPrune(arg0 context.Context, arg1 client.Filters) (network.PruneReport, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworksPrune", arg0, arg1) ret0, _ := ret[0].(network.PruneReport) @@ -1222,7 +1189,7 @@ func (mr *MockAPIClientMockRecorder) NodeInspectWithRaw(arg0, arg1 any) *gomock. } // NodeList mocks base method. -func (m *MockAPIClient) NodeList(arg0 context.Context, arg1 swarm.NodeListOptions) ([]swarm.Node, error) { +func (m *MockAPIClient) NodeList(arg0 context.Context, arg1 client.NodeListOptions) ([]swarm.Node, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NodeList", arg0, arg1) ret0, _ := ret[0].([]swarm.Node) @@ -1237,7 +1204,7 @@ func (mr *MockAPIClientMockRecorder) NodeList(arg0, arg1 any) *gomock.Call { } // NodeRemove mocks base method. -func (m *MockAPIClient) NodeRemove(arg0 context.Context, arg1 string, arg2 swarm.NodeRemoveOptions) error { +func (m *MockAPIClient) NodeRemove(arg0 context.Context, arg1 string, arg2 client.NodeRemoveOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NodeRemove", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -1280,7 +1247,7 @@ func (mr *MockAPIClientMockRecorder) Ping(arg0 any) *gomock.Call { } // PluginCreate mocks base method. -func (m *MockAPIClient) PluginCreate(arg0 context.Context, arg1 io.Reader, arg2 types.PluginCreateOptions) error { +func (m *MockAPIClient) PluginCreate(arg0 context.Context, arg1 io.Reader, arg2 client.PluginCreateOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginCreate", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -1294,7 +1261,7 @@ func (mr *MockAPIClientMockRecorder) PluginCreate(arg0, arg1, arg2 any) *gomock. } // PluginDisable mocks base method. -func (m *MockAPIClient) PluginDisable(arg0 context.Context, arg1 string, arg2 types.PluginDisableOptions) error { +func (m *MockAPIClient) PluginDisable(arg0 context.Context, arg1 string, arg2 client.PluginDisableOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginDisable", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -1308,7 +1275,7 @@ func (mr *MockAPIClientMockRecorder) PluginDisable(arg0, arg1, arg2 any) *gomock } // PluginEnable mocks base method. -func (m *MockAPIClient) PluginEnable(arg0 context.Context, arg1 string, arg2 types.PluginEnableOptions) error { +func (m *MockAPIClient) PluginEnable(arg0 context.Context, arg1 string, arg2 client.PluginEnableOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginEnable", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -1322,10 +1289,10 @@ func (mr *MockAPIClientMockRecorder) PluginEnable(arg0, arg1, arg2 any) *gomock. } // PluginInspectWithRaw mocks base method. -func (m *MockAPIClient) PluginInspectWithRaw(arg0 context.Context, arg1 string) (*types.Plugin, []byte, error) { +func (m *MockAPIClient) PluginInspectWithRaw(arg0 context.Context, arg1 string) (*plugin.Plugin, []byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginInspectWithRaw", arg0, arg1) - ret0, _ := ret[0].(*types.Plugin) + ret0, _ := ret[0].(*plugin.Plugin) ret1, _ := ret[1].([]byte) ret2, _ := ret[2].(error) return ret0, ret1, ret2 @@ -1338,7 +1305,7 @@ func (mr *MockAPIClientMockRecorder) PluginInspectWithRaw(arg0, arg1 any) *gomoc } // PluginInstall mocks base method. -func (m *MockAPIClient) PluginInstall(arg0 context.Context, arg1 string, arg2 types.PluginInstallOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) PluginInstall(arg0 context.Context, arg1 string, arg2 client.PluginInstallOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginInstall", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -1353,10 +1320,10 @@ func (mr *MockAPIClientMockRecorder) PluginInstall(arg0, arg1, arg2 any) *gomock } // PluginList mocks base method. -func (m *MockAPIClient) PluginList(arg0 context.Context, arg1 filters.Args) (types.PluginsListResponse, error) { +func (m *MockAPIClient) PluginList(arg0 context.Context, arg1 client.Filters) (plugin.ListResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginList", arg0, arg1) - ret0, _ := ret[0].(types.PluginsListResponse) + ret0, _ := ret[0].(plugin.ListResponse) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1383,7 +1350,7 @@ func (mr *MockAPIClientMockRecorder) PluginPush(arg0, arg1, arg2 any) *gomock.Ca } // PluginRemove mocks base method. -func (m *MockAPIClient) PluginRemove(arg0 context.Context, arg1 string, arg2 types.PluginRemoveOptions) error { +func (m *MockAPIClient) PluginRemove(arg0 context.Context, arg1 string, arg2 client.PluginRemoveOptions) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginRemove", arg0, arg1, arg2) ret0, _ := ret[0].(error) @@ -1411,7 +1378,7 @@ func (mr *MockAPIClientMockRecorder) PluginSet(arg0, arg1, arg2 any) *gomock.Cal } // PluginUpgrade mocks base method. -func (m *MockAPIClient) PluginUpgrade(arg0 context.Context, arg1 string, arg2 types.PluginInstallOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) PluginUpgrade(arg0 context.Context, arg1 string, arg2 client.PluginInstallOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PluginUpgrade", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -1472,7 +1439,7 @@ func (mr *MockAPIClientMockRecorder) SecretInspectWithRaw(arg0, arg1 any) *gomoc } // SecretList mocks base method. -func (m *MockAPIClient) SecretList(arg0 context.Context, arg1 swarm.SecretListOptions) ([]swarm.Secret, error) { +func (m *MockAPIClient) SecretList(arg0 context.Context, arg1 client.SecretListOptions) ([]swarm.Secret, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecretList", arg0, arg1) ret0, _ := ret[0].([]swarm.Secret) @@ -1530,7 +1497,7 @@ func (mr *MockAPIClientMockRecorder) ServerVersion(arg0 any) *gomock.Call { } // ServiceCreate mocks base method. -func (m *MockAPIClient) ServiceCreate(arg0 context.Context, arg1 swarm.ServiceSpec, arg2 swarm.ServiceCreateOptions) (swarm.ServiceCreateResponse, error) { +func (m *MockAPIClient) ServiceCreate(arg0 context.Context, arg1 swarm.ServiceSpec, arg2 client.ServiceCreateOptions) (swarm.ServiceCreateResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServiceCreate", arg0, arg1, arg2) ret0, _ := ret[0].(swarm.ServiceCreateResponse) @@ -1545,7 +1512,7 @@ func (mr *MockAPIClientMockRecorder) ServiceCreate(arg0, arg1, arg2 any) *gomock } // ServiceInspectWithRaw mocks base method. -func (m *MockAPIClient) ServiceInspectWithRaw(arg0 context.Context, arg1 string, arg2 swarm.ServiceInspectOptions) (swarm.Service, []byte, error) { +func (m *MockAPIClient) ServiceInspectWithRaw(arg0 context.Context, arg1 string, arg2 client.ServiceInspectOptions) (swarm.Service, []byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServiceInspectWithRaw", arg0, arg1, arg2) ret0, _ := ret[0].(swarm.Service) @@ -1561,7 +1528,7 @@ func (mr *MockAPIClientMockRecorder) ServiceInspectWithRaw(arg0, arg1, arg2 any) } // ServiceList mocks base method. -func (m *MockAPIClient) ServiceList(arg0 context.Context, arg1 swarm.ServiceListOptions) ([]swarm.Service, error) { +func (m *MockAPIClient) ServiceList(arg0 context.Context, arg1 client.ServiceListOptions) ([]swarm.Service, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServiceList", arg0, arg1) ret0, _ := ret[0].([]swarm.Service) @@ -1576,7 +1543,7 @@ func (mr *MockAPIClientMockRecorder) ServiceList(arg0, arg1 any) *gomock.Call { } // ServiceLogs mocks base method. -func (m *MockAPIClient) ServiceLogs(arg0 context.Context, arg1 string, arg2 container.LogsOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) ServiceLogs(arg0 context.Context, arg1 string, arg2 client.ContainerLogsOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServiceLogs", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -1605,7 +1572,7 @@ func (mr *MockAPIClientMockRecorder) ServiceRemove(arg0, arg1 any) *gomock.Call } // ServiceUpdate mocks base method. -func (m *MockAPIClient) ServiceUpdate(arg0 context.Context, arg1 string, arg2 swarm.Version, arg3 swarm.ServiceSpec, arg4 swarm.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { +func (m *MockAPIClient) ServiceUpdate(arg0 context.Context, arg1 string, arg2 swarm.Version, arg3 swarm.ServiceSpec, arg4 client.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServiceUpdate", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(swarm.ServiceUpdateResponse) @@ -1707,7 +1674,7 @@ func (mr *MockAPIClientMockRecorder) SwarmUnlock(arg0, arg1 any) *gomock.Call { } // SwarmUpdate mocks base method. -func (m *MockAPIClient) SwarmUpdate(arg0 context.Context, arg1 swarm.Version, arg2 swarm.Spec, arg3 swarm.UpdateFlags) error { +func (m *MockAPIClient) SwarmUpdate(arg0 context.Context, arg1 swarm.Version, arg2 swarm.Spec, arg3 client.SwarmUpdateFlags) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SwarmUpdate", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) @@ -1737,7 +1704,7 @@ func (mr *MockAPIClientMockRecorder) TaskInspectWithRaw(arg0, arg1 any) *gomock. } // TaskList mocks base method. -func (m *MockAPIClient) TaskList(arg0 context.Context, arg1 swarm.TaskListOptions) ([]swarm.Task, error) { +func (m *MockAPIClient) TaskList(arg0 context.Context, arg1 client.TaskListOptions) ([]swarm.Task, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TaskList", arg0, arg1) ret0, _ := ret[0].([]swarm.Task) @@ -1752,7 +1719,7 @@ func (mr *MockAPIClientMockRecorder) TaskList(arg0, arg1 any) *gomock.Call { } // TaskLogs mocks base method. -func (m *MockAPIClient) TaskLogs(arg0 context.Context, arg1 string, arg2 container.LogsOptions) (io.ReadCloser, error) { +func (m *MockAPIClient) TaskLogs(arg0 context.Context, arg1 string, arg2 client.ContainerLogsOptions) (io.ReadCloser, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TaskLogs", arg0, arg1, arg2) ret0, _ := ret[0].(io.ReadCloser) @@ -1813,7 +1780,7 @@ func (mr *MockAPIClientMockRecorder) VolumeInspectWithRaw(arg0, arg1 any) *gomoc } // VolumeList mocks base method. -func (m *MockAPIClient) VolumeList(arg0 context.Context, arg1 volume.ListOptions) (volume.ListResponse, error) { +func (m *MockAPIClient) VolumeList(arg0 context.Context, arg1 client.VolumeListOptions) (volume.ListResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "VolumeList", arg0, arg1) ret0, _ := ret[0].(volume.ListResponse) @@ -1856,7 +1823,7 @@ func (mr *MockAPIClientMockRecorder) VolumeUpdate(arg0, arg1, arg2, arg3 any) *g } // VolumesPrune mocks base method. -func (m *MockAPIClient) VolumesPrune(arg0 context.Context, arg1 filters.Args) (volume.PruneReport, error) { +func (m *MockAPIClient) VolumesPrune(arg0 context.Context, arg1 client.Filters) (volume.PruneReport, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "VolumesPrune", arg0, arg1) ret0, _ := ret[0].(volume.PruneReport) diff --git a/pkg/mocks/mock_docker_cli.go b/pkg/mocks/mock_docker_cli.go index 663c57ee92..b8bd7b4ec1 100644 --- a/pkg/mocks/mock_docker_cli.go +++ b/pkg/mocks/mock_docker_cli.go @@ -17,7 +17,7 @@ import ( docker "github.com/docker/cli/cli/context/docker" store "github.com/docker/cli/cli/context/store" streams "github.com/docker/cli/cli/streams" - client "github.com/docker/docker/client" + client "github.com/moby/moby/client" metric "go.opentelemetry.io/otel/metric" resource "go.opentelemetry.io/otel/sdk/resource" trace "go.opentelemetry.io/otel/trace" @@ -47,24 +47,6 @@ func (m *MockCli) EXPECT() *MockCliMockRecorder { return m.recorder } -// Apply mocks base method. -func (m *MockCli) Apply(arg0 ...command.CLIOption) error { - m.ctrl.T.Helper() - varargs := []any{} - for _, a := range arg0 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Apply", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// Apply indicates an expected call of Apply. -func (mr *MockCliMockRecorder) Apply(arg0 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockCli)(nil).Apply), arg0...) -} - // BuildKitEnabled mocks base method. func (m *MockCli) BuildKitEnabled() (bool, error) { m.ctrl.T.Helper()