diff --git a/README.md b/README.md index 31a1b73..1a184e2 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,8 @@ Last updated: 2020/01/03 #### Why `dktest` is better -* Uses the [official Docker SDK](https://github.com/docker/docker) - * [docker/docker](https://github.com/docker/docker) (aka [moby/moby](https://github.com/moby/moby)) uses [import path checking](https://golang.org/cmd/go/#hdr-Import_path_checking), so needs to be imported as `github.com/docker/docker` +* Uses the [official Docker SDK](https://github.com/moby/moby) + * [moby/moby](https://github.com/moby/moby) uses [import path checking](https://golang.org/cmd/go/#hdr-Import_path_checking), so needs to be imported as `github.com/moby/moby` * Designed to run in the Go testing environment * Smaller API surface * Running Docker containers are automatically cleaned up diff --git a/container_info.go b/container_info.go index 2bb52e9..1d842eb 100644 --- a/container_info.go +++ b/container_info.go @@ -3,10 +3,9 @@ package dktest import ( "fmt" "strconv" -) -import ( "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/network" ) func mapHost(h string) string { @@ -98,6 +97,31 @@ func portMapToStrings(portMap nat.PortMap) []string { return portBindingStrs } +// toNatPortMap converts a [network.PortMap] to a [nat.PortMap]. This is used to convert the Docker API +// response back to nat types so the public [ContainerInfo] API remains stable. +func toNatPortMap(m network.PortMap) nat.PortMap { + if len(m) == 0 { + return nil + } + out := make(nat.PortMap, len(m)) + for p, bindings := range m { + natPort := nat.Port(p.String()) + natBindings := make([]nat.PortBinding, len(bindings)) + for i, b := range bindings { + hostIP := "" + if b.HostIP.IsValid() { + hostIP = b.HostIP.String() + } + natBindings[i] = nat.PortBinding{ + HostIP: hostIP, + HostPort: b.HostPort, + } + } + out[natPort] = natBindings + } + return out +} + // ContainerInfo holds information about a running Docker container type ContainerInfo struct { ID string diff --git a/container_info_internal_test.go b/container_info_internal_test.go index 51ece80..5830df2 100644 --- a/container_info_internal_test.go +++ b/container_info_internal_test.go @@ -1,10 +1,12 @@ package dktest import ( + "net/netip" "strconv" "testing" "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/network" "github.com/stretchr/testify/assert" ) @@ -150,3 +152,56 @@ func TestPortMapToStrings(t *testing.T) { }) } } + +func TestToNatPortMap(t *testing.T) { + testCases := []struct { + name string + input network.PortMap + expected nat.PortMap + }{ + {name: "nil", input: nil, expected: nil}, + {name: "empty", input: network.PortMap{}, expected: nil}, + {name: "single port", input: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostPort: "8080"}}, + }, expected: nat.PortMap{ + "80/tcp": {{HostIP: "", HostPort: "8080"}}, + }}, + {name: "with host ip", input: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostIP: netip.MustParseAddr("10.0.0.1"), HostPort: "8080"}}, + }, expected: nat.PortMap{ + "80/tcp": {{HostIP: "10.0.0.1", HostPort: "8080"}}, + }}, + {name: "with zero ip", input: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostIP: netip.MustParseAddr("0.0.0.0"), HostPort: "8080"}}, + }, expected: nat.PortMap{ + "80/tcp": {{HostIP: "0.0.0.0", HostPort: "8080"}}, + }}, + {name: "multiple ports", input: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostPort: "8080"}}, + network.MustParsePort("443/tcp"): {{HostPort: "8443"}}, + network.MustParsePort("53/udp"): {{HostPort: "5353"}}, + }, expected: nat.PortMap{ + "80/tcp": {{HostIP: "", HostPort: "8080"}}, + "443/tcp": {{HostIP: "", HostPort: "8443"}}, + "53/udp": {{HostIP: "", HostPort: "5353"}}, + }}, + {name: "multiple bindings per port", input: network.PortMap{ + network.MustParsePort("80/tcp"): { + {HostPort: "8080"}, + {HostIP: netip.MustParseAddr("192.168.1.1"), HostPort: "9090"}, + }, + }, expected: nat.PortMap{ + "80/tcp": { + {HostIP: "", HostPort: "8080"}, + {HostIP: "192.168.1.1", HostPort: "9090"}, + }, + }}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := toNatPortMap(tc.input) + assert.Equal(t, tc.expected, result) + }) + } +} diff --git a/container_info_test.go b/container_info_test.go index c454c48..4860f52 100644 --- a/container_info_test.go +++ b/container_info_test.go @@ -2,14 +2,9 @@ package dktest_test import ( "testing" -) -import ( - "github.com/docker/go-connections/nat" -) - -import ( "github.com/dhui/dktest" + "github.com/docker/go-connections/nat" ) func getTestContainerInfo(t *testing.T) dktest.ContainerInfo { diff --git a/dktest.go b/dktest.go index 4fbabb1..27edc31 100644 --- a/dktest.go +++ b/dktest.go @@ -8,11 +8,11 @@ import ( "testing" "time" - "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/client" - "github.com/docker/docker/pkg/jsonmessage" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" + "github.com/moby/moby/client/pkg/jsonmessage" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) var ( @@ -31,12 +31,20 @@ const ( label = "dktest" ) -func pullImage(ctx context.Context, lgr Logger, dc client.ImageAPIClient, registryAuth, imgName, platform string) error { +func pullImage(ctx context.Context, lgr Logger, dc client.ImageAPIClient, registryAuth string, imgName string, platform string) error { lgr.Log("Pulling image:", imgName) // lgr.Log(dc.ImageList(ctx, types.ImageListOptions{All: true})) - resp, err := dc.ImagePull(ctx, imgName, image.PullOptions{ - Platform: platform, + var platforms []v1.Platform + if len(platform) > 0 { + p, err := parsePlatform(platform) + if err != nil { + return err + } + platforms = []v1.Platform{p} + } + resp, err := dc.ImagePull(ctx, imgName, client.ImagePullOptions{ + Platforms: platforms, RegistryAuth: registryAuth, }) if err != nil { @@ -62,7 +70,7 @@ func pullImage(ctx context.Context, lgr Logger, dc client.ImageAPIClient, regist func removeImage(ctx context.Context, lgr Logger, dc client.ImageAPIClient, imgName string) { lgr.Log("Removing image:", imgName) - if _, err := dc.ImageRemove(ctx, imgName, image.RemoveOptions{Force: true, PruneChildren: true}); err != nil { + if _, err := dc.ImageRemove(ctx, imgName, client.ImageRemoveOptions{Force: true, PruneChildren: true}); err != nil { lgr.Log("Failed to remove image: ", err.Error()) } } @@ -70,30 +78,34 @@ func removeImage(ctx context.Context, lgr Logger, dc client.ImageAPIClient, imgN func runImage(ctx context.Context, lgr Logger, dc client.ContainerAPIClient, imgName string, opts Options) (ContainerInfo, error) { c := ContainerInfo{Name: genContainerName(), ImageName: imgName} - createResp, err := dc.ContainerCreate(ctx, &container.Config{ - Image: imgName, - Labels: map[string]string{label: "true"}, - Env: opts.env(), - Entrypoint: opts.Entrypoint, - Cmd: opts.Cmd, - Volumes: opts.volumes(), - Hostname: opts.Hostname, - ExposedPorts: opts.ExposedPorts, - }, &container.HostConfig{ - PublishAllPorts: true, - PortBindings: opts.PortBindings, - ShmSize: opts.ShmSize, - Mounts: opts.Mounts, - }, &network.NetworkingConfig{}, - nil, - c.Name) + createResp, err := dc.ContainerCreate(ctx, + client.ContainerCreateOptions{ + Config: &container.Config{ + Image: imgName, + Labels: map[string]string{label: "true"}, + Env: opts.env(), + Entrypoint: opts.Entrypoint, + Cmd: opts.Cmd, + Volumes: opts.volumes(), + Hostname: opts.Hostname, + ExposedPorts: convertPortSet(opts.ExposedPorts), + }, + HostConfig: &container.HostConfig{ + PublishAllPorts: true, + PortBindings: convertPortMap(opts.PortBindings), + ShmSize: opts.ShmSize, + Mounts: opts.Mounts, + }, + NetworkingConfig: &network.NetworkingConfig{}, + Name: c.Name, + }) if err != nil { return c, err } c.ID = createResp.ID lgr.Log("Created container:", c.String()) - if err := dc.ContainerStart(ctx, createResp.ID, container.StartOptions{}); err != nil { + if _, err := dc.ContainerStart(ctx, createResp.ID, client.ContainerStartOptions{}); err != nil { return c, err } lgr.Log("Started container:", c.String()) @@ -102,16 +114,16 @@ func runImage(ctx context.Context, lgr Logger, dc client.ContainerAPIClient, img return c, nil } - inspectResp, err := dc.ContainerInspect(ctx, c.ID) + inspectResp, err := dc.ContainerInspect(ctx, c.ID, client.ContainerInspectOptions{}) if err != nil { return c, err } lgr.Log("Inspected container:", c.String()) - if inspectResp.NetworkSettings == nil { + if inspectResp.Container.NetworkSettings == nil { return c, errNoNetworkSettings } - c.Ports = inspectResp.NetworkSettings.Ports + c.Ports = toNatPortMap(inspectResp.Container.NetworkSettings.Ports) return c, nil } @@ -119,7 +131,7 @@ func runImage(ctx context.Context, lgr Logger, dc client.ContainerAPIClient, img func stopContainer(ctx context.Context, lgr Logger, dc client.ContainerAPIClient, c ContainerInfo, logStdout, logStderr bool) { if logStdout || logStderr { - if logs, err := dc.ContainerLogs(ctx, c.ID, container.LogsOptions{ + if logs, err := dc.ContainerLogs(ctx, c.ID, client.ContainerLogsOptions{ Timestamps: true, ShowStdout: logStdout, ShowStderr: logStderr, }); err == nil { b, err := io.ReadAll(logs) @@ -138,13 +150,13 @@ func stopContainer(ctx context.Context, lgr Logger, dc client.ContainerAPIClient } } - if err := dc.ContainerStop(ctx, c.ID, container.StopOptions{}); err != nil { + if _, err := dc.ContainerStop(ctx, c.ID, client.ContainerStopOptions{}); err != nil { lgr.Log("Error stopping container:", c.String(), "error:", err) } lgr.Log("Stopped container:", c.String()) - if err := dc.ContainerRemove(ctx, c.ID, - container.RemoveOptions{RemoveVolumes: true, Force: true}); err != nil { + if _, err := dc.ContainerRemove(ctx, c.ID, + client.ContainerRemoveOptions{RemoveVolumes: true, Force: true}); err != nil { lgr.Log("Error removing container:", c.String(), "error:", err) } lgr.Log("Removed container:", c.String()) @@ -191,7 +203,7 @@ func Run(t *testing.T, imgName string, opts Options, testFunc func(*testing.T, C // RunContext is similar to Run, but takes a parent context and returns an error and doesn't rely on a testing.T. func RunContext(ctx context.Context, logger Logger, imgName string, opts Options, testFunc func(ContainerInfo) error) (retErr error) { - dc, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.41")) + dc, err := client.New(client.FromEnv) if err != nil { return fmt.Errorf("error getting Docker client: %w", err) } diff --git a/dktest_internal_test.go b/dktest_internal_test.go index 9a28c63..28a56a0 100644 --- a/dktest_internal_test.go +++ b/dktest_internal_test.go @@ -3,12 +3,14 @@ package dktest import ( "context" "io" + "net/netip" "testing" "time" "github.com/dhui/dktest/mockdockerclient" - "github.com/docker/docker/api/types/container" - "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" ) const ( @@ -42,57 +44,54 @@ func TestPullImage(t *testing.T) { expectErr bool }{ {name: "success", client: mockdockerclient.ImageAPIClient{ - PullResp: mockdockerclient.MockReadCloser{MockReader: successReader}}, expectErr: false}, + PullResp: &mockdockerclient.MockImagePullResponse{ReadCloser: mockdockerclient.MockReadCloser{MockReader: successReader}}}, expectErr: false}, {name: "with specific platform", client: mockdockerclient.ImageAPIClient{ - PullResp: mockdockerclient.MockReadCloser{MockReader: successReader}}, - platform: "linux/x86_64", expectErr: false}, + PullResp: &mockdockerclient.MockImagePullResponse{ReadCloser: mockdockerclient.MockReadCloser{MockReader: successReader}}}, + platform: "linux/amd64", expectErr: false}, {name: "pull error", client: mockdockerclient.ImageAPIClient{}, expectErr: true}, {name: "read error", client: mockdockerclient.ImageAPIClient{ - PullResp: mockdockerclient.MockReadCloser{ + PullResp: &mockdockerclient.MockImagePullResponse{ReadCloser: mockdockerclient.MockReadCloser{ MockReader: mockdockerclient.MockReader{Err: mockdockerclient.Err}, - }}, expectErr: false}, + }}}, expectErr: false}, {name: "close error", client: mockdockerclient.ImageAPIClient{ - PullResp: mockdockerclient.MockReadCloser{ + PullResp: &mockdockerclient.MockImagePullResponse{ReadCloser: mockdockerclient.MockReadCloser{ MockReader: successReader, MockCloser: mockdockerclient.MockCloser{Err: mockdockerclient.Err}, - }}, expectErr: false}, + }}}, expectErr: false}, } ctx := context.Background() for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - client := tc.client - err := pullImage(ctx, t, &client, "", imageName, tc.platform) + c := tc.client + err := pullImage(ctx, t, &c, "", imageName, tc.platform) testErr(t, err, tc.expectErr) }) } } func TestRunImage(t *testing.T) { - _, portBindingsNoIP, err := nat.ParsePortSpecs([]string{"8181:80"}) - if err != nil { - t.Fatal("Error parsing port bindings:", err) + portBindingsNoIP := network.PortMap{ + network.MustParsePort("80/tcp"): []network.PortBinding{{HostPort: "8181"}}, } - _, portBindingsIPZeros, err := nat.ParsePortSpecs([]string{"0.0.0.0:8181:80"}) - if err != nil { - t.Fatal("Error parsing port bindings:", err) + portBindingsIPZeros := network.PortMap{ + network.MustParsePort("80/tcp"): []network.PortBinding{{HostIP: netip.MustParseAddr("0.0.0.0"), HostPort: "8181"}}, } - _, portBindingsDiffIP, err := nat.ParsePortSpecs([]string{"10.0.0.1:8181:80"}) - if err != nil { - t.Fatal("Error parsing port bindings:", err) + portBindingsDiffIP := network.PortMap{ + network.MustParsePort("80/tcp"): []network.PortBinding{{HostIP: netip.MustParseAddr("10.0.0.1"), HostPort: "8181"}}, } - successCreateResp := &container.CreateResponse{} - successInspectResp := &container.InspectResponse{} - successInspectRespWithPortBindingNoIP := &container.InspectResponse{NetworkSettings: &container.NetworkSettings{ - NetworkSettingsBase: container.NetworkSettingsBase{Ports: portBindingsNoIP}, - }} - successInspectRespWithPortBindingIPZeros := &container.InspectResponse{NetworkSettings: &container.NetworkSettings{ - NetworkSettingsBase: container.NetworkSettingsBase{Ports: portBindingsIPZeros}, - }} - successInspectRespWithPortBindingDiffIP := &container.InspectResponse{NetworkSettings: &container.NetworkSettings{ - NetworkSettingsBase: container.NetworkSettingsBase{Ports: portBindingsDiffIP}, - }} + successCreateResp := &client.ContainerCreateResult{} + successInspectResp := &client.ContainerInspectResult{} + successInspectRespWithPortBindingNoIP := &client.ContainerInspectResult{Container: container.InspectResponse{NetworkSettings: &container.NetworkSettings{ + Ports: portBindingsNoIP, + }}} + successInspectRespWithPortBindingIPZeros := &client.ContainerInspectResult{Container: container.InspectResponse{NetworkSettings: &container.NetworkSettings{ + Ports: portBindingsIPZeros, + }}} + successInspectRespWithPortBindingDiffIP := &client.ContainerInspectResult{Container: container.InspectResponse{NetworkSettings: &container.NetworkSettings{ + Ports: portBindingsDiffIP, + }}} testCases := []struct { name string diff --git a/go.mod b/go.mod index 2700e39..f7fe095 100644 --- a/go.mod +++ b/go.mod @@ -1,45 +1,38 @@ module github.com/dhui/dktest require ( - github.com/docker/docker v28.3.3+incompatible - github.com/docker/go-connections v0.4.0 + github.com/docker/go-connections v0.7.0 github.com/lib/pq v1.8.0 - github.com/opencontainers/image-spec v1.0.2 + github.com/moby/moby/api v1.54.2 + github.com/moby/moby/client v0.4.1 + github.com/opencontainers/image-spec v1.1.1 github.com/stretchr/testify v1.10.0 ) require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/go-units v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/sys/atomicwriter v0.1.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect - github.com/morikuni/aec v1.0.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + golang.org/x/sys v0.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gotest.tools/v3 v3.1.0 // indirect ) -go 1.23.0 +go 1.24 + +toolchain go1.24.2 diff --git a/go.sum b/go.sum index 0ecf5ea..32cc6cb 100644 --- a/go.sum +++ b/go.sum @@ -1,27 +1,21 @@ -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= -github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= +github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -29,17 +23,10 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -48,105 +35,45 @@ github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg= +github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY= +github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= -gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/mockdockerclient/container_api_client.go b/mockdockerclient/container_api_client.go index 7c07029..098e120 100644 --- a/mockdockerclient/container_api_client.go +++ b/mockdockerclient/container_api_client.go @@ -4,22 +4,17 @@ import ( "context" "io" - "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/network" - "github.com/docker/docker/client" - - v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) // ContainerAPIClient is a mock implementation of the Docker's client.ContainerAPIClient interface type ContainerAPIClient struct { - CreateResp *container.CreateResponse + CreateResp *client.ContainerCreateResult StartErr error StopErr error RemoveErr error - InspectResp *container.InspectResponse + InspectResp *client.ContainerInspectResult Logs io.ReadCloser } @@ -28,24 +23,22 @@ var _ client.ContainerAPIClient = (*ContainerAPIClient)(nil) // ContainerAttach is a mock implementation of Docker's client.ContainerAPIClient.ContainerAttach() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerAttach(context.Context, string, - container.AttachOptions) (types.HijackedResponse, error) { - return types.HijackedResponse{}, nil +func (c *ContainerAPIClient) ContainerAttach(context.Context, string, client.ContainerAttachOptions) (client.ContainerAttachResult, error) { + return client.ContainerAttachResult{}, nil } // ContainerCommit is a mock implementation of Docker's client.ContainerAPIClient.ContainerCommit() // // TODO: properly implement func (c *ContainerAPIClient) ContainerCommit(context.Context, string, - container.CommitOptions) (container.CommitResponse, error) { - return container.CommitResponse{}, nil + client.ContainerCommitOptions) (client.ContainerCommitResult, error) { + return client.ContainerCommitResult{}, nil } // ContainerCreate is a mock implementation of Docker's client.ContainerAPIClient.ContainerCreate() -func (c *ContainerAPIClient) ContainerCreate(context.Context, *container.Config, *container.HostConfig, - *network.NetworkingConfig, *v1.Platform, string) (container.CreateResponse, error) { +func (c *ContainerAPIClient) ContainerCreate(context.Context, client.ContainerCreateOptions) (client.ContainerCreateResult, error) { if c.CreateResp == nil { - return container.CreateResponse{}, Err + return client.ContainerCreateResult{}, Err } return *c.CreateResp, nil } @@ -54,61 +47,56 @@ func (c *ContainerAPIClient) ContainerCreate(context.Context, *container.Config, // // TODO: properly implement func (c *ContainerAPIClient) ContainerDiff(context.Context, - string) ([]container.FilesystemChange, error) { - return nil, nil + string, client.ContainerDiffOptions) (client.ContainerDiffResult, error) { + return client.ContainerDiffResult{}, nil } // ContainerExecAttach is a mock implementation of Docker's client.ContainerAPIClient.ContainerExecAttach() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExecAttach(context.Context, string, - container.ExecStartOptions) (types.HijackedResponse, error) { - return types.HijackedResponse{}, nil +func (c *ContainerAPIClient) ContainerExecAttach(context.Context, string, client.ExecAttachOptions) (client.ExecAttachResult, error) { + return client.ExecAttachResult{}, nil } // ContainerExecCreate is a mock implementation of Docker's client.ContainerAPIClient.ContainerExecCreate() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExecCreate(context.Context, string, - container.ExecOptions) (container.ExecCreateResponse, error) { - return container.ExecCreateResponse{}, nil +func (c *ContainerAPIClient) ContainerExecCreate(context.Context, string, client.ExecCreateOptions) (client.ExecCreateResult, error) { + return client.ExecCreateResult{}, nil } // ContainerExecInspect is a mock implementation of Docker's client.ContainerAPIClient.ContainerExecInspect() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExecInspect(context.Context, - string) (container.ExecInspect, error) { - return container.ExecInspect{}, nil +func (c *ContainerAPIClient) ContainerExecInspect(context.Context, string, client.ExecInspectOptions) (client.ExecInspectResult, error) { + return client.ExecInspectResult{}, nil } // ContainerExecResize is a mock implementation of Docker's client.ContainerAPIClient.ContainerExecResize() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExecResize(context.Context, string, - container.ResizeOptions) error { - return nil +func (c *ContainerAPIClient) ContainerExecResize(context.Context, string, client.ExecResizeOptions) (client.ExecResizeResult, error) { + return client.ExecResizeResult{}, nil } // ContainerExecStart is a mock implementation of Docker's client.ContainerAPIClient.ContainerExecStart() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExecStart(context.Context, string, - container.ExecStartOptions) error { - return nil +func (c *ContainerAPIClient) ContainerExecStart(context.Context, string, client.ExecStartOptions) (client.ExecStartResult, error) { + return client.ExecStartResult{}, nil } // ContainerExport is a mock implementation of Docker's client.ContainerAPIClient.ContainerExport() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerExport(context.Context, string) (io.ReadCloser, error) { +func (c *ContainerAPIClient) ContainerExport(context.Context, string, client.ContainerExportOptions) (client.ContainerExportResult, error) { return nil, nil } // ContainerInspect is a mock implementation of Docker's client.ContainerAPIClient.ContainerInspect() -func (c *ContainerAPIClient) ContainerInspect(context.Context, string) (container.InspectResponse, error) { +func (c *ContainerAPIClient) ContainerInspect(context.Context, string, client.ContainerInspectOptions) (client.ContainerInspectResult, error) { if c.InspectResp == nil { - return container.InspectResponse{}, Err + return client.ContainerInspectResult{}, Err } return *c.InspectResp, nil } @@ -124,21 +112,19 @@ func (c *ContainerAPIClient) ContainerInspectWithRaw(context.Context, string, // ContainerKill is a mock implementation of Docker's client.ContainerAPIClient.ContainerKill() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerKill(context.Context, string, string) error { - return nil +func (c *ContainerAPIClient) ContainerKill(context.Context, string, client.ContainerKillOptions) (client.ContainerKillResult, error) { + return client.ContainerKillResult{}, nil } // ContainerList is a mock implementation of Docker's client.ContainerAPIClient.ContainerList() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerList(context.Context, - container.ListOptions) ([]container.Summary, error) { - return nil, nil +func (c *ContainerAPIClient) ContainerList(context.Context, client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{}, nil } // ContainerLogs is a mock implementation of Docker's client.ContainerAPIClient.ContainerLogs() -func (c *ContainerAPIClient) ContainerLogs(context.Context, string, - container.LogsOptions) (io.ReadCloser, error) { +func (c *ContainerAPIClient) ContainerLogs(context.Context, string, client.ContainerLogsOptions) (client.ContainerLogsResult, error) { if c.Logs == nil { return nil, Err } @@ -148,119 +134,105 @@ func (c *ContainerAPIClient) ContainerLogs(context.Context, string, // ContainerPause is a mock implementation of Docker's client.ContainerAPIClient.ContainerPause() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerPause(context.Context, string) error { return nil } +func (c *ContainerAPIClient) ContainerPause(context.Context, string, client.ContainerPauseOptions) (client.ContainerPauseResult, error) { + return client.ContainerPauseResult{}, nil +} // ContainerRemove is a mock implementation of Docker's client.ContainerAPIClient.ContainerRemove() -func (c *ContainerAPIClient) ContainerRemove(context.Context, string, - container.RemoveOptions) error { - return c.RemoveErr +func (c *ContainerAPIClient) ContainerRemove(context.Context, string, client.ContainerRemoveOptions) (client.ContainerRemoveResult, error) { + return client.ContainerRemoveResult{}, c.RemoveErr } // ContainerRename is a mock implementation of Docker's client.ContainerAPIClient.ContainerRename() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerRename(context.Context, string, string) error { - return nil +func (c *ContainerAPIClient) ContainerRename(context.Context, string, client.ContainerRenameOptions) (client.ContainerRenameResult, error) { + return client.ContainerRenameResult{}, nil } // ContainerResize is a mock implementation of Docker's client.ContainerAPIClient.ContainerResize() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerResize(context.Context, string, container.ResizeOptions) error { - return nil +func (c *ContainerAPIClient) ContainerResize(context.Context, string, client.ContainerResizeOptions) (client.ContainerResizeResult, error) { + return client.ContainerResizeResult{}, nil } // ContainerRestart is a mock implementation of Docker's client.ContainerAPIClient.ContainerRestart() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerRestart(context.Context, string, container.StopOptions) error { - return nil +func (c *ContainerAPIClient) ContainerRestart(context.Context, string, client.ContainerRestartOptions) (client.ContainerRestartResult, error) { + return client.ContainerRestartResult{}, nil } // ContainerStatPath is a mock implementation of Docker's client.ContainerAPIClient.ContainerStatPath() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerStatPath(context.Context, string, - string) (container.PathStat, error) { - return container.PathStat{}, nil +func (c *ContainerAPIClient) ContainerStatPath(context.Context, string, client.ContainerStatPathOptions) (client.ContainerStatPathResult, error) { + return client.ContainerStatPathResult{}, nil } // ContainerStats is a mock implementation of Docker's client.ContainerAPIClient.ContainerStats() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerStats(context.Context, string, - bool) (container.StatsResponseReader, error) { - return container.StatsResponseReader{}, nil -} - -// ContainerStatsOneShot is a mock implementation of Docker's client.ContainerAPIClient.ContainerStatsOneShot() -// -// TODO: properly implement -func (c *ContainerAPIClient) ContainerStatsOneShot(context.Context, string) (container.StatsResponseReader, error) { - return container.StatsResponseReader{}, nil +func (c *ContainerAPIClient) ContainerStats(context.Context, string, client.ContainerStatsOptions) (client.ContainerStatsResult, error) { + return client.ContainerStatsResult{}, nil } // ContainerStart is a mock implementation of Docker's client.ContainerAPIClient.ContainerStart() -func (c *ContainerAPIClient) ContainerStart(context.Context, string, - container.StartOptions) error { - return c.StartErr +func (c *ContainerAPIClient) ContainerStart(context.Context, string, client.ContainerStartOptions) (client.ContainerStartResult, error) { + return client.ContainerStartResult{}, c.StartErr } // ContainerStop is a mock implementation of Docker's client.ContainerAPIClient.ContainerStop() -func (c *ContainerAPIClient) ContainerStop(context.Context, string, container.StopOptions) error { - return c.StopErr +func (c *ContainerAPIClient) ContainerStop(context.Context, string, client.ContainerStopOptions) (client.ContainerStopResult, error) { + return client.ContainerStopResult{}, c.StopErr } // ContainerTop is a mock implementation of Docker's client.ContainerAPIClient.ContainerTop() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerTop(context.Context, string, - []string) (container.TopResponse, error) { - return container.TopResponse{}, nil +func (c *ContainerAPIClient) ContainerTop(context.Context, string, client.ContainerTopOptions) (client.ContainerTopResult, error) { + return client.ContainerTopResult{}, nil } // ContainerUnpause is a mock implementation of Docker's client.ContainerAPIClient.ContainerUnpause() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerUnpause(context.Context, string) error { - return nil +func (c *ContainerAPIClient) ContainerUnpause(context.Context, string, client.ContainerUnpauseOptions) (client.ContainerUnpauseResult, error) { + return client.ContainerUnpauseResult{}, nil } // ContainerUpdate is a mock implementation of Docker's client.ContainerAPIClient.ContainerUpdate() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerUpdate(context.Context, string, - container.UpdateConfig) (container.UpdateResponse, error) { - return container.UpdateResponse{}, nil +func (c *ContainerAPIClient) ContainerUpdate(context.Context, string, client.ContainerUpdateOptions) (client.ContainerUpdateResult, error) { + return client.ContainerUpdateResult{}, nil } // ContainerWait is a mock implementation of Docker's client.ContainerAPIClient.ContainerWait() // // TODO: properly implement -func (c *ContainerAPIClient) ContainerWait(context.Context, string, - container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { - return nil, nil +func (c *ContainerAPIClient) ContainerWait(context.Context, string, client.ContainerWaitOptions) client.ContainerWaitResult { + return client.ContainerWaitResult{} } // CopyFromContainer is a mock implementation of Docker's client.ContainerAPIClient.CopyFromContainer() // // TODO: properly implement -func (c *ContainerAPIClient) CopyFromContainer(context.Context, string, string) (io.ReadCloser, - container.PathStat, error) { - return nil, container.PathStat{}, nil +func (c *ContainerAPIClient) CopyFromContainer(context.Context, string, client.CopyFromContainerOptions) (client.CopyFromContainerResult, error) { + return client.CopyFromContainerResult{}, nil } // CopyToContainer is a mock implementation of Docker's client.ContainerAPIClient.CopyToContainer() // // TODO: properly implement -func (c *ContainerAPIClient) CopyToContainer(context.Context, string, string, io.Reader, - container.CopyToContainerOptions) error { - return nil +func (c *ContainerAPIClient) CopyToContainer(context.Context, string, client.CopyToContainerOptions) (client.CopyToContainerResult, error) { + return client.CopyToContainerResult{}, nil } -// ContainersPrune is a mock implementation of Docker's client.ContainerAPIClient.ContainersPrune() +// ContainerPrune is a mock implementation of Docker's client.ContainerAPIClient.ContainersPrune() // // TODO: properly implement -func (c *ContainerAPIClient) ContainersPrune(context.Context, filters.Args) (container.PruneReport, error) { - return container.PruneReport{}, nil +func (c *ContainerAPIClient) ContainerPrune(context.Context, client.ContainerPruneOptions) (client.ContainerPruneResult, error) { + return client.ContainerPruneResult{}, nil } diff --git a/mockdockerclient/doc.go b/mockdockerclient/doc.go index f71c91c..6d0cf3b 100644 --- a/mockdockerclient/doc.go +++ b/mockdockerclient/doc.go @@ -1,3 +1,3 @@ // Package mockdockerclient provides mocks for the Docker client -// [github.com/docker/docker/client] +// [github.com/moby/moby/client] package mockdockerclient diff --git a/mockdockerclient/image_api_client.go b/mockdockerclient/image_api_client.go index 04b0b8f..aeef2d3 100644 --- a/mockdockerclient/image_api_client.go +++ b/mockdockerclient/image_api_client.go @@ -3,34 +3,48 @@ package mockdockerclient import ( "context" "io" + "iter" - "github.com/docker/docker/api/types/build" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/client" + "github.com/moby/moby/api/types/build" + "github.com/moby/moby/api/types/jsonstream" + "github.com/moby/moby/client" ) var _ client.ImageAPIClient = (*ImageAPIClient)(nil) // ImageAPIClient is a mock implementation of the Docker's client.ImageAPIClient interface type ImageAPIClient struct { - PullResp io.ReadCloser + PullResp *MockImagePullResponse +} + +// MockImagePullResponse is a mock implementation of the client.ImagePullResponse interface +type MockImagePullResponse struct { + io.ReadCloser +} + +// Wait implement interface +func (ip *MockImagePullResponse) Wait(context.Context) error { + return nil +} + +// JSONMessages implement interface +func (ip *MockImagePullResponse) JSONMessages(context.Context) iter.Seq2[jsonstream.Message, error] { + return nil } // ImageBuild is a mock implementation of Docker's client.ImageAPIClient.ImageBuild() // // TODO: properly implement func (c *ImageAPIClient) ImageBuild(context.Context, io.Reader, - build.ImageBuildOptions) (build.ImageBuildResponse, error) { - return build.ImageBuildResponse{}, nil + client.ImageBuildOptions) (client.ImageBuildResult, error) { + return client.ImageBuildResult{}, nil } // BuildCachePrune is a mock implementation of Docker's client.ImageAPIClient.BuildCachePrune() // // TODO: properly implement func (c *ImageAPIClient) BuildCachePrune(context.Context, - build.CachePruneOptions) (*build.CachePruneReport, error) { + client.BuildCachePruneOptions) (*build.CachePruneReport, error) { return nil, nil } @@ -39,52 +53,44 @@ func (c *ImageAPIClient) BuildCachePrune(context.Context, // TODO: properly implement func (c *ImageAPIClient) BuildCancel(context.Context, string) error { return nil } -// ImageCreate is a mock implementation of Docker's client.ImageAPIClient.ImageCreate() -// -// TODO: properly implement -func (c *ImageAPIClient) ImageCreate(context.Context, string, - image.CreateOptions) (io.ReadCloser, error) { - return nil, nil -} - // ImageHistory is a mock implementation of Docker's client.ImageAPIClient.ImageHistory() // // TODO: properly implement -func (c *ImageAPIClient) ImageHistory(context.Context, string, ...client.ImageHistoryOption) ([]image.HistoryResponseItem, error) { - return nil, nil +func (c *ImageAPIClient) ImageHistory(context.Context, string, ...client.ImageHistoryOption) (client.ImageHistoryResult, error) { + return client.ImageHistoryResult{}, nil } // ImageImport is a mock implementation of Docker's client.ImageAPIClient.ImageImport() // // TODO: properly implement -func (c *ImageAPIClient) ImageImport(context.Context, image.ImportSource, string, - image.ImportOptions) (io.ReadCloser, error) { +func (c *ImageAPIClient) ImageImport(context.Context, client.ImageImportSource, string, + client.ImageImportOptions) (client.ImageImportResult, error) { return nil, nil } // ImageInspectWithRaw is a mock implementation of Docker's client.ImageAPIClient.ImageInspectWithRaw() // // TODO: properly implement -func (c *ImageAPIClient) ImageInspectWithRaw(context.Context, string) (image.InspectResponse, []byte, error) { - return image.InspectResponse{}, nil, nil +func (c *ImageAPIClient) ImageInspectWithRaw(context.Context, string) (client.ImageInspectResult, []byte, error) { + return client.ImageInspectResult{}, nil, nil } // ImageList is a mock implementation of Docker's client.ImageAPIClient.ImageList() // // TODO: properly implement -func (c *ImageAPIClient) ImageList(context.Context, image.ListOptions) ([]image.Summary, error) { - return nil, nil +func (c *ImageAPIClient) ImageList(context.Context, client.ImageListOptions) (client.ImageListResult, error) { + return client.ImageListResult{}, nil } // ImageLoad is a mock implementation of Docker's client.ImageAPIClient.ImageLoad() // // TODO: properly implement -func (c *ImageAPIClient) ImageLoad(context.Context, io.Reader, ...client.ImageLoadOption) (image.LoadResponse, error) { - return image.LoadResponse{}, nil +func (c *ImageAPIClient) ImageLoad(context.Context, io.Reader, ...client.ImageLoadOption) (client.ImageLoadResult, error) { + return nil, nil } // ImagePull is a mock implementation of Docker's client.ImageAPIClient.ImagePull() -func (c *ImageAPIClient) ImagePull(context.Context, string, image.PullOptions) (io.ReadCloser, error) { +func (c *ImageAPIClient) ImagePull(context.Context, string, client.ImagePullOptions) (client.ImagePullResponse, error) { if c.PullResp == nil { return nil, Err } @@ -94,7 +100,7 @@ func (c *ImageAPIClient) ImagePull(context.Context, string, image.PullOptions) ( // ImagePush is a mock implementation of Docker's client.ImageAPIClient.ImagePush() // // TODO: properly implement -func (c *ImageAPIClient) ImagePush(context.Context, string, image.PushOptions) (io.ReadCloser, error) { +func (c *ImageAPIClient) ImagePush(context.Context, string, client.ImagePushOptions) (client.ImagePushResponse, error) { return nil, nil } @@ -102,40 +108,42 @@ func (c *ImageAPIClient) ImagePush(context.Context, string, image.PushOptions) ( // // TODO: properly implement func (c *ImageAPIClient) ImageRemove(context.Context, string, - image.RemoveOptions) ([]image.DeleteResponse, error) { - return nil, nil + client.ImageRemoveOptions) (client.ImageRemoveResult, error) { + return client.ImageRemoveResult{}, nil } // ImageSearch is a mock implementation of Docker's client.ImageAPIClient.ImageSearch() // // TODO: properly implement func (c *ImageAPIClient) ImageSearch(context.Context, string, - registry.SearchOptions) ([]registry.SearchResult, error) { - return nil, nil + client.ImageSearchOptions) (client.ImageSearchResult, error) { + return client.ImageSearchResult{}, nil } // ImageSave is a mock implementation of Docker's client.ImageAPIClient.ImageSave() // // TODO: properly implement -func (c *ImageAPIClient) ImageSave(context.Context, []string, ...client.ImageSaveOption) (io.ReadCloser, error) { +func (c *ImageAPIClient) ImageSave(context.Context, []string, ...client.ImageSaveOption) (client.ImageSaveResult, error) { return nil, nil } // ImageTag is a mock implementation of Docker's client.ImageAPIClient.ImageTag() // // TODO: properly implement -func (c *ImageAPIClient) ImageTag(context.Context, string, string) error { return nil } +func (c *ImageAPIClient) ImageTag(context.Context, client.ImageTagOptions) (client.ImageTagResult, error) { + return client.ImageTagResult{}, nil +} -// ImagesPrune is a mock implementation of Docker's client.ImageAPIClient.ImagesPrune() +// ImagePrune is a mock implementation of Docker's client.ImageAPIClient.ImagesPrune() // // TODO: properly implement -func (c *ImageAPIClient) ImagesPrune(context.Context, filters.Args) (image.PruneReport, error) { - return image.PruneReport{}, nil +func (c *ImageAPIClient) ImagePrune(context.Context, client.ImagePruneOptions) (client.ImagePruneResult, error) { + return client.ImagePruneResult{}, nil } // ImageInspect is a mock implementation of Docker's client.ImageAPIClient.ImageInspect() // // TODO: properly implement -func (c *ImageAPIClient) ImageInspect(context.Context, string, ...client.ImageInspectOption) (image.InspectResponse, error) { - return image.InspectResponse{}, nil +func (c *ImageAPIClient) ImageInspect(context.Context, string, ...client.ImageInspectOption) (client.ImageInspectResult, error) { + return client.ImageInspectResult{}, nil } diff --git a/options.go b/options.go index 6ff1337..e67efcf 100644 --- a/options.go +++ b/options.go @@ -2,10 +2,15 @@ package dktest import ( "context" + "fmt" + "net/netip" + "strings" "time" - "github.com/docker/docker/api/types/mount" "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/api/types/network" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // Options contains the configurable options for running tests in the docker image @@ -37,11 +42,67 @@ type Options struct { Volumes []string Mounts []mount.Mount Hostname string - // Platform specifies the platform of the docker image that is pulled. + // Platform specifies the platform of the docker image that is pulled, e.g. "linux/amd64" Platform string ExposedPorts nat.PortSet } +// parsePlatform turns a platform string into a [v1.Platform]. This was added +// during the migration to [github.com/moby/moby] as a way to keep the public [Options] api static +// platform string convention is $os/$arch/$variant +func parsePlatform(p string) (v1.Platform, error) { + splitPlat := strings.Split(p, "/") + if len(splitPlat) < 2 { + return v1.Platform{}, fmt.Errorf("invalid platform (%s): os and architecture must be provided $os/$architecture", p) + } + plat := v1.Platform{ + OS: splitPlat[0], + Architecture: splitPlat[1], + } + if len(splitPlat) == 3 { + plat.Variant = splitPlat[2] + } + return plat, nil +} + +// convertPortSet converts a [nat.PortSet] to a [network.PortSet]. This was added during the migration to +// [github.com/moby/moby] as a way to keep the public [Options] api static. +func convertPortSet(s nat.PortSet) network.PortSet { + if len(s) == 0 { + return nil + } + out := make(network.PortSet, len(s)) + for p := range s { + out[network.MustParsePort(string(p))] = struct{}{} + } + return out +} + +// convertPortMap converts a [nat.PortMap] to a [network.PortMap]. This was added during the migration to +// [github.com/moby/moby] as a way to keep the public [Options] api static. +func convertPortMap(m nat.PortMap) network.PortMap { + if len(m) == 0 { + return nil + } + out := make(network.PortMap, len(m)) + for p, bindings := range m { + networkPort := network.MustParsePort(string(p)) + networkBindings := make([]network.PortBinding, len(bindings)) + for i, b := range bindings { + var hostIP netip.Addr + if b.HostIP != "" { + hostIP, _ = netip.ParseAddr(b.HostIP) + } + networkBindings[i] = network.PortBinding{ + HostIP: hostIP, + HostPort: b.HostPort, + } + } + out[networkPort] = networkBindings + } + return out +} + func (o *Options) init() { if o.PullTimeout <= 0 { o.PullTimeout = DefaultPullTimeout diff --git a/options_internal_test.go b/options_internal_test.go index 175a398..13bf756 100644 --- a/options_internal_test.go +++ b/options_internal_test.go @@ -1,11 +1,12 @@ package dktest import ( + "net/netip" "testing" "time" -) -import ( + "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/types/network" "github.com/stretchr/testify/assert" ) @@ -71,3 +72,79 @@ func TestOptionsEnv(t *testing.T) { }) } } + +func TestConvertPortSet(t *testing.T) { + testCases := []struct { + name string + input nat.PortSet + expected network.PortSet + }{ + {name: "nil", input: nil, expected: nil}, + {name: "empty", input: nat.PortSet{}, expected: nil}, + {name: "single port", input: nat.PortSet{ + "80/tcp": {}, + }, expected: network.PortSet{ + network.MustParsePort("80/tcp"): {}, + }}, + {name: "multiple ports", input: nat.PortSet{ + "80/tcp": {}, + "53/udp": {}, + }, expected: network.PortSet{ + network.MustParsePort("80/tcp"): {}, + network.MustParsePort("53/udp"): {}, + }}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := convertPortSet(tc.input) + assert.Equal(t, tc.expected, result) + }) + } +} + +func TestConvertPortMap(t *testing.T) { + testCases := []struct { + name string + input nat.PortMap + expected network.PortMap + }{ + {name: "nil", input: nil, expected: nil}, + {name: "empty", input: nat.PortMap{}, expected: nil}, + {name: "single port no host ip", input: nat.PortMap{ + "80/tcp": {{HostPort: "8080"}}, + }, expected: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostPort: "8080"}}, + }}, + {name: "with host ip", input: nat.PortMap{ + "80/tcp": {{HostIP: "10.0.0.1", HostPort: "8080"}}, + }, expected: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostIP: netip.MustParseAddr("10.0.0.1"), HostPort: "8080"}}, + }}, + {name: "with 0.0.0.0", input: nat.PortMap{ + "80/tcp": {{HostIP: "0.0.0.0", HostPort: "8080"}}, + }, expected: network.PortMap{ + network.MustParsePort("80/tcp"): {{HostIP: netip.MustParseAddr("0.0.0.0"), HostPort: "8080"}}, + }}, + {name: "multiple ports and bindings", input: nat.PortMap{ + "80/tcp": { + {HostPort: "8080"}, + {HostIP: "192.168.1.1", HostPort: "9090"}, + }, + "53/udp": {{HostPort: "5353"}}, + }, expected: network.PortMap{ + network.MustParsePort("80/tcp"): { + {HostPort: "8080"}, + {HostIP: netip.MustParseAddr("192.168.1.1"), HostPort: "9090"}, + }, + network.MustParsePort("53/udp"): {{HostPort: "5353"}}, + }}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := convertPortMap(tc.input) + assert.Equal(t, tc.expected, result) + }) + } +}