Skip to content

Commit 535dcaf

Browse files
committed
[SRVLOGIC-1069] Migrate Docker APIs v28 to Moby v1.55.0 and Moby Client v0.5.0
Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
1 parent 91c9ef9 commit 535dcaf

13 files changed

Lines changed: 442 additions & 351 deletions

File tree

cli/go.mod

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ replace (
1010

1111
require (
1212
github.com/beevik/etree v1.5.0
13+
github.com/containerd/errdefs v1.0.0
1314
github.com/distribution/reference v0.6.0
14-
github.com/docker/docker v28.5.2+incompatible
15-
github.com/docker/go-connections v0.5.0
1615
github.com/getkin/kin-openapi v0.131.0
1716
github.com/jstemmer/go-junit-report/v2 v2.1.0
1817
github.com/kubesmarts/logic-operator/api v0.0.0
1918
github.com/kubesmarts/logic-operator/workflowproj v0.0.0
19+
github.com/moby/moby/api v1.55.0
20+
github.com/moby/moby/client v0.5.0
2021
github.com/ory/viper v1.7.5
2122
github.com/spf13/afero v1.12.0
2223
github.com/spf13/cobra v1.9.1
@@ -30,15 +31,16 @@ require (
3031
k8s.io/client-go v0.31.6
3132
)
3233

34+
replace github.com/moby/moby => github.com/moby/moby/api v1.55.0
35+
3336
require (
34-
github.com/Microsoft/go-winio v0.6.1 // indirect
37+
github.com/Microsoft/go-winio v0.6.2 // indirect
3538
github.com/beorn7/perks v1.0.1 // indirect
3639
github.com/cespare/xxhash/v2 v2.3.0 // indirect
37-
github.com/containerd/errdefs v1.0.0 // indirect
3840
github.com/containerd/errdefs/pkg v0.3.0 // indirect
39-
github.com/containerd/log v0.1.0 // indirect
4041
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
4142
github.com/dgraph-io/ristretto v0.1.1 // indirect
43+
github.com/docker/go-connections v0.7.0 // indirect
4244
github.com/docker/go-units v0.5.0 // indirect
4345
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
4446
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -76,18 +78,15 @@ require (
7678
github.com/mitchellh/mapstructure v1.5.0 // indirect
7779
github.com/moby/docker-image-spec v1.3.1 // indirect
7880
github.com/moby/spdystream v0.4.0 // indirect
79-
github.com/moby/sys/atomicwriter v0.1.0 // indirect
80-
github.com/moby/term v0.5.0 // indirect
8181
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8282
github.com/modern-go/reflect2 v1.0.2 // indirect
8383
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
84-
github.com/morikuni/aec v1.0.0 // indirect
8584
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
8685
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
8786
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
8887
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
8988
github.com/opencontainers/go-digest v1.0.0 // indirect
90-
github.com/opencontainers/image-spec v1.1.0 // indirect
89+
github.com/opencontainers/image-spec v1.1.1 // indirect
9190
github.com/pb33f/libopenapi v0.10.1 // indirect
9291
github.com/pelletier/go-toml v1.9.5 // indirect
9392
github.com/perimeterx/marshmallow v1.1.5 // indirect
@@ -110,28 +109,23 @@ require (
110109
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
111110
github.com/x448/float16 v0.8.4 // indirect
112111
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
113-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
114-
go.opentelemetry.io/otel v1.34.0 // indirect
115-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
116-
go.opentelemetry.io/otel/metric v1.34.0 // indirect
117-
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
118-
go.opentelemetry.io/otel/trace v1.34.0 // indirect
112+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
113+
go.opentelemetry.io/otel v1.35.0 // indirect
114+
go.opentelemetry.io/otel/metric v1.35.0 // indirect
115+
go.opentelemetry.io/otel/trace v1.35.0 // indirect
119116
golang.org/x/crypto v0.51.0 // indirect
120117
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
121-
golang.org/x/mod v0.35.0 // indirect
122118
golang.org/x/net v0.55.0 // indirect
123119
golang.org/x/oauth2 v0.35.0 // indirect
124120
golang.org/x/sync v0.20.0 // indirect
125121
golang.org/x/term v0.43.0 // indirect
126122
golang.org/x/text v0.37.0 // indirect
127-
golang.org/x/time v0.8.0 // indirect
128-
golang.org/x/tools v0.44.0 // indirect
123+
golang.org/x/time v0.11.0 // indirect
129124
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
130125
google.golang.org/protobuf v1.36.11 // indirect
131126
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
132127
gopkg.in/inf.v0 v0.9.1 // indirect
133128
gopkg.in/ini.v1 v1.67.0 // indirect
134-
gotest.tools/v3 v3.5.1 // indirect
135129
k8s.io/klog/v2 v2.130.1 // indirect
136130
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
137131
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect

cli/go.sum

Lines changed: 30 additions & 52 deletions
Large diffs are not rendered by default.

cli/pkg/common/checks.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ package common
2222
import (
2323
"context"
2424
"fmt"
25-
"github.com/docker/docker/api/types/container"
2625
"os"
2726
"path/filepath"
2827
"regexp"
@@ -31,7 +30,7 @@ import (
3130

3231
"github.com/kubesmarts/logic-operator/cli/pkg/metadata"
3332
apiMetadata "github.com/kubesmarts/logic-operator/api/metadata"
34-
"github.com/docker/docker/client"
33+
"github.com/moby/moby/client"
3534
)
3635

3736
func CheckJavaDependencies() error {
@@ -94,12 +93,12 @@ func checkMaven() error {
9493

9594
func CheckDocker() error {
9695
fmt.Println("✅ Checking if Docker is available...")
97-
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
96+
cli, err := client.New(client.FromEnv)
9897
if err != nil {
9998
fmt.Println("Error creating docker client")
10099
return err
101100
}
102-
_, err = cli.ContainerList(context.Background(), container.ListOptions{})
101+
_, err = cli.ContainerList(context.Background(), client.ContainerListOptions{})
103102
if err != nil {
104103
fmt.Println("ERROR: Docker not found.")
105104
fmt.Println("Download from https://docs.docker.com/get-docker/")

cli/pkg/common/containers.go

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ import (
2626
"encoding/json"
2727
"errors"
2828
"fmt"
29-
"github.com/distribution/reference"
30-
"github.com/docker/docker/api/types/image"
3129
"io"
30+
"net/netip"
3231
"os"
3332
"os/exec"
3433
"os/signal"
@@ -38,10 +37,12 @@ import (
3837
"time"
3938

4039
"github.com/kubesmarts/logic-operator/cli/pkg/metadata"
41-
"github.com/docker/docker/api/types/container"
42-
"github.com/docker/docker/client"
43-
"github.com/docker/docker/pkg/stdcopy"
44-
"github.com/docker/go-connections/nat"
40+
"github.com/distribution/reference"
41+
"github.com/containerd/errdefs"
42+
"github.com/moby/moby/api/types/container"
43+
"github.com/moby/moby/api/types/network"
44+
"github.com/moby/moby/api/pkg/stdcopy"
45+
"github.com/moby/moby/client"
4546
)
4647

4748
const (
@@ -55,11 +56,11 @@ type DockerLogMessage struct {
5556
}
5657

5758
type DockerClient interface {
58-
ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error)
59+
ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error)
5960
}
6061

6162
func getDockerClient() (*client.Client, error) {
62-
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
63+
cli, err := client.New(client.FromEnv)
6364
if err != nil {
6465
return nil, fmt.Errorf("failed to create Docker client: %s", err)
6566
}
@@ -102,12 +103,12 @@ func getDockerContainerID() (string, error) {
102103
return "", err
103104
}
104105

105-
containers, err := cli.ContainerList(context.Background(), container.ListOptions{})
106+
result, err := cli.ContainerList(context.Background(), client.ContainerListOptions{})
106107
if err != nil {
107108
return "", err
108109
}
109110

110-
for _, c := range containers {
111+
for _, c := range result.Items {
111112
// Check if the container has the expected image name or other identifying information
112113
if strings.Contains(c.Image, metadata.DevModeImage) {
113114
return c.ID, nil
@@ -130,7 +131,8 @@ func StopContainer(containerTool string, containerID string) error {
130131
fmt.Printf("unable to create client for docker")
131132
return err
132133
}
133-
if err := cli.ContainerStop(context.Background(), containerID, container.StopOptions{}); err != nil {
134+
_, err = cli.ContainerStop(context.Background(), containerID, client.ContainerStopOptions{})
135+
if err != nil {
134136
fmt.Printf("Unable to stop container %s: %s", containerID, err)
135137
return err
136138
}
@@ -257,12 +259,12 @@ func CheckImageExists(cli DockerClient, ctx context.Context, imageName string) (
257259
} else {
258260
imageName = fmt.Sprintf("%s:%s", reference.Path(named), "latest")
259261
}
260-
images, err := cli.ImageList(ctx, image.ListOptions{All: true})
262+
result, err := cli.ImageList(ctx, client.ImageListOptions{All: true})
261263
if err != nil {
262264
return false, fmt.Errorf("error listing images: %s", err)
263265
}
264266

265-
for _, i := range images {
267+
for _, i := range result.Items {
266268
for _, tag := range i.RepoTags {
267269
if strings.HasSuffix(tag, imageName) {
268270
return true, nil
@@ -297,37 +299,43 @@ func waitToImageBeReady(reader io.ReadCloser) error {
297299
return nil
298300
}
299301

300-
func createDockerContainer(cli *client.Client, ctx context.Context, portMapping string, path string) (container.CreateResponse, error) {
301-
containerConfig := &container.Config{
302-
Image: metadata.DevModeImage,
303-
}
304-
hostConfig := &container.HostConfig{
305-
AutoRemove: true,
306-
PortBindings: nat.PortMap{
307-
metadata.DockerInternalPort: []nat.PortBinding{
308-
{
309-
HostIP: "0.0.0.0",
310-
HostPort: portMapping,
302+
func createDockerContainer(cli *client.Client, ctx context.Context, portMapping string, path string) (client.ContainerCreateResult, error) {
303+
port := network.MustParsePort(string(metadata.DockerInternalPort))
304+
hostIP := netip.MustParseAddr("0.0.0.0")
305+
createOpts := client.ContainerCreateOptions{
306+
Config: &container.Config{
307+
Image: metadata.DevModeImage,
308+
ExposedPorts: network.PortSet{port: struct{}{}},
309+
},
310+
HostConfig: &container.HostConfig{
311+
AutoRemove: true,
312+
PortBindings: network.PortMap{
313+
port: []network.PortBinding{
314+
{
315+
HostIP: hostIP,
316+
HostPort: portMapping,
317+
},
311318
},
312319
},
313-
},
314-
Binds: []string{
315-
fmt.Sprintf("%s:%s", path, metadata.VolumeBindPath),
320+
Binds: []string{
321+
fmt.Sprintf("%s:%s", path, metadata.VolumeBindPath),
322+
},
316323
},
317324
}
318325

319-
resp, err := cli.ContainerCreate(ctx, containerConfig, hostConfig, nil, nil, "")
326+
resp, err := cli.ContainerCreate(ctx, createOpts)
320327
if err != nil {
321328
return resp, fmt.Errorf("\nUnable to create container %s: %s", metadata.DevModeImage, err)
322329
}
323330
return resp, nil
324331
}
325332

326-
func startDockerContainer(cli *client.Client, ctx context.Context, resp container.CreateResponse) error {
333+
func startDockerContainer(cli *client.Client, ctx context.Context, resp client.ContainerCreateResult) error {
327334
fmt.Printf("\nCreated container with ID %s", resp.ID)
328335
fmt.Println("\n⏳ Starting your container and SonataFlow project...")
329336

330-
if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
337+
_, err := cli.ContainerStart(ctx, resp.ID, client.ContainerStartOptions{})
338+
if err != nil {
331339
return fmt.Errorf("\nUnable to start container %s", resp.ID)
332340
}
333341

@@ -362,28 +370,30 @@ func runDockerContainer(portMapping string, path string) error {
362370

363371
return nil
364372
}
365-
func processOutputDuringContainerExecution(cli *client.Client, ctx context.Context, resp container.CreateResponse) error {
366-
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
373+
func processOutputDuringContainerExecution(cli *client.Client, ctx context.Context, resp client.ContainerCreateResult) error {
374+
waitResult := cli.ContainerWait(ctx, resp.ID, client.ContainerWaitOptions{
375+
Condition: container.WaitConditionNotRunning,
376+
})
367377

368378
//Print all container logs
369-
out, err := cli.ContainerLogs(ctx, resp.ID, container.LogsOptions{ShowStdout: false, ShowStderr: true, Follow: true})
379+
logsResult, err := cli.ContainerLogs(ctx, resp.ID, client.ContainerLogsOptions{ShowStdout: false, ShowStderr: true, Follow: true})
370380
if err != nil {
371381
return fmt.Errorf("\nError getting container logs: %s", err)
372382
}
373383

374384
go func() {
375-
_, err := stdcopy.StdCopy(os.Stdout, os.Stderr, out)
385+
_, err := stdcopy.StdCopy(os.Stdout, os.Stderr, logsResult)
376386
if err != nil {
377387
fmt.Errorf("\nError copying container logs to stdout: %s", err)
378388
}
379389
}()
380390

381391
select {
382-
case err := <-errCh:
392+
case err := <-waitResult.Error:
383393
if err != nil {
384394
return fmt.Errorf("\nError starting the container %s: %s", resp.ID, err)
385395
}
386-
case <-statusCh:
396+
case <-waitResult.Result:
387397
//state of the container matches the condition, in our case WaitConditionNotRunning
388398
}
389399

@@ -412,14 +422,14 @@ func IsContainerRunning(containerID string) (bool, error) {
412422
if err != nil {
413423
return false, fmt.Errorf("unable to create docker client: %w", err)
414424
}
415-
containerJSON, err := cli.ContainerInspect(context.Background(), containerID)
425+
result, err := cli.ContainerInspect(context.Background(), containerID, client.ContainerInspectOptions{})
416426
if err != nil {
417-
if client.IsErrNotFound(err) {
427+
if errdefs.IsNotFound(err) {
418428
return false, nil
419429
}
420430
return false, fmt.Errorf("unable to inspect container %s with docker: %w", containerID, err)
421431
}
422-
return containerJSON.State.Running, nil
432+
return result.Container.State.Running, nil
423433

424434
} else if errPodman := CheckPodman(); errPodman == nil {
425435
cmd := exec.Command("podman", "inspect", containerID, "--format", "{{.State.Running}}")

cli/pkg/common/containers_test.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,21 @@ package common
2121

2222
import (
2323
"context"
24-
"github.com/docker/docker/api/types/image"
24+
"testing"
25+
26+
"github.com/moby/moby/api/types/image"
27+
"github.com/moby/moby/client"
2528
"github.com/stretchr/testify/assert"
2629
"github.com/stretchr/testify/mock"
27-
28-
"testing"
2930
)
3031

3132
type MockDockerClient struct {
3233
mock.Mock
3334
}
3435

35-
func (m *MockDockerClient) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) {
36+
func (m *MockDockerClient) ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error) {
3637
args := m.Called(ctx, options)
37-
return args.Get(0).([]image.Summary), args.Error(1)
38+
return args.Get(0).(client.ImageListResult), args.Error(1)
3839
}
3940

4041
func TestCheckImageExists(t *testing.T) {
@@ -62,9 +63,11 @@ func TestCheckImageExists(t *testing.T) {
6263
ctx := context.Background()
6364
mockClient := new(MockDockerClient)
6465

65-
mockClient.On("ImageList", ctx, mock.Anything).Return([]image.Summary{
66-
{
67-
RepoTags: test.images,
66+
mockClient.On("ImageList", ctx, mock.Anything).Return(client.ImageListResult{
67+
Items: []image.Summary{
68+
{
69+
RepoTags: test.images,
70+
},
6871
},
6972
}, nil)
7073

0 commit comments

Comments
 (0)