Move testutils image load to integration internal

The image load is only used by integration tests but the specialimage
testutils package used by many different tests. The image load relies on
the client which creates a transitive client dependency from the daemon
packages.

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan
2025-07-16 16:15:27 -07:00
parent 7766b8a763
commit b54bde4376
8 changed files with 84 additions and 73 deletions

View File

@@ -7,6 +7,7 @@ import (
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils/specialimage"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
@@ -21,7 +22,7 @@ func TestImageInspectEmptyTagsAndDigests(t *testing.T) {
apiClient := testEnv.APIClient()
danglingID := specialimage.Load(ctx, t, apiClient, specialimage.Dangling)
danglingID := iimage.Load(ctx, t, apiClient, specialimage.Dangling)
var raw bytes.Buffer
inspect, err := apiClient.ImageInspect(ctx, danglingID, client.ImageInspectWithRawResponse(&raw))
@@ -103,7 +104,7 @@ func TestImageInspectWithPlatform(t *testing.T) {
Architecture: "amd64",
}
imageID := specialimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
imageID := iimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
i, descs, err := specialimage.MultiPlatform(dir, "multiplatform:latest", []ocispec.Platform{nativePlatform, differentPlatform})
assert.NilError(t, err)

View File

@@ -14,6 +14,7 @@ import (
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/container"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils/specialimage"
"github.com/docker/docker/testutil"
"github.com/docker/docker/testutil/daemon"
@@ -213,14 +214,14 @@ func TestAPIImagesListSizeShared(t *testing.T) {
client := daemon.NewClientT(t)
specialimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
return specialimage.MultiLayerCustom(dir, "multilayer:latest", []specialimage.SingleFileLayer{
{Name: "bar", Content: []byte("2")},
{Name: "foo", Content: []byte("1")},
})
})
specialimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
return specialimage.MultiLayerCustom(dir, "multilayer2:latest", []specialimage.SingleFileLayer{
{Name: "asdf", Content: []byte("3")},
{Name: "foo", Content: []byte("1")},
@@ -249,7 +250,7 @@ func TestAPIImagesListManifests(t *testing.T) {
{OS: "linux", Architecture: "arm", Variant: "v7"},
{OS: "darwin", Architecture: "arm64"},
}
specialimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
idx, _, err := specialimage.MultiPlatform(dir, "multiplatform:latest", testPlatforms)
return idx, err
})

View File

@@ -6,6 +6,7 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/api/types/image"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils/specialimage"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
@@ -20,7 +21,7 @@ func TestLoadDanglingImages(t *testing.T) {
client := testEnv.APIClient()
specialimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
return specialimage.MultiLayerCustom(dir, "namedimage:latest", []specialimage.SingleFileLayer{
{Name: "bar", Content: []byte("1")},
})
@@ -44,7 +45,7 @@ func TestLoadDanglingImages(t *testing.T) {
assert.NilError(t, err)
// Retain a copy of the old image and then replace it with a new one.
specialimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, client, func(dir string) (*ocispec.Index, error) {
return specialimage.MultiLayerCustom(dir, "namedimage:latest", []specialimage.SingleFileLayer{
{Name: "bar", Content: []byte("2")},
})

View File

@@ -9,6 +9,7 @@ import (
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/container"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils/specialimage"
"github.com/docker/docker/testutil"
"github.com/docker/docker/testutil/daemon"
@@ -31,7 +32,7 @@ func TestPruneDontDeleteUsedDangling(t *testing.T) {
apiClient := d.NewClientT(t)
defer apiClient.Close()
danglingID := specialimage.Load(ctx, t, apiClient, specialimage.Dangling)
danglingID := iimage.Load(ctx, t, apiClient, specialimage.Dangling)
_, err := apiClient.ImageInspect(ctx, danglingID)
assert.NilError(t, err, "Test dangling image doesn't exist")

View File

@@ -10,6 +10,7 @@ import (
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/integration/internal/container"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils/specialimage"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
@@ -115,7 +116,7 @@ func TestRemoveWithPlatform(t *testing.T) {
var imageIdx *ocispec.Index
var descs []ocispec.Descriptor
specialimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
iimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
idx, d, err := specialimage.MultiPlatform(dir, imgName, []ocispec.Platform{
platformHost,
{

View File

@@ -20,6 +20,7 @@ import (
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/build"
"github.com/docker/docker/integration/internal/container"
iimage "github.com/docker/docker/integration/internal/image"
"github.com/docker/docker/internal/testutils"
"github.com/docker/docker/internal/testutils/specialimage"
"github.com/docker/docker/testutil/fakecontext"
@@ -116,7 +117,7 @@ func TestSaveOCI(t *testing.T) {
}
if testEnv.DaemonInfo.OSType != "windows" {
multiLayerImage := specialimage.Load(ctx, t, client, specialimage.MultiLayer)
multiLayerImage := iimage.Load(ctx, t, client, specialimage.MultiLayer)
// Multi-layer image
testCases = append(testCases, testCase{image: multiLayerImage, expectedContainerdRef: "docker.io/library/multilayer:latest", expectedOCIRef: "latest"})

View File

@@ -0,0 +1,68 @@
package image
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"strings"
"testing"
"github.com/docker/docker/client"
"github.com/docker/docker/internal/testutils/specialimage"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/go-archive"
"gotest.tools/v3/assert"
)
func Load(ctx context.Context, t *testing.T, apiClient client.APIClient, imageFunc specialimage.SpecialImageFunc) string {
tempDir := t.TempDir()
_, err := imageFunc(tempDir)
assert.NilError(t, err)
rc, err := archive.TarWithOptions(tempDir, &archive.TarOptions{})
assert.NilError(t, err)
defer rc.Close()
resp, err := apiClient.ImageLoad(ctx, rc, client.ImageLoadWithQuiet(true))
assert.NilError(t, err, "Failed to load dangling image")
defer resp.Body.Close()
if !assert.Check(t, err) {
respBody, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("Failed to read response body: %v", err)
return ""
}
t.Fatalf("Failed load: %s", string(respBody))
}
all, err := io.ReadAll(resp.Body)
assert.NilError(t, err)
decoder := json.NewDecoder(bytes.NewReader(all))
for {
var msg jsonmessage.JSONMessage
err := decoder.Decode(&msg)
if errors.Is(err, io.EOF) {
break
}
assert.NilError(t, err)
msg.Stream = strings.TrimSpace(msg.Stream)
if _, imageID, hasID := strings.Cut(msg.Stream, "Loaded image ID: "); hasID {
return imageID
}
if _, imageRef, hasRef := strings.Cut(msg.Stream, "Loaded image: "); hasRef {
return imageRef
}
}
t.Fatalf("failed to read image ID\n%s", string(all))
return ""
}

View File

@@ -1,70 +1,7 @@
package specialimage
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"strings"
"testing"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/go-archive"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
)
type SpecialImageFunc func(string) (*ocispec.Index, error)
func Load(ctx context.Context, t *testing.T, apiClient client.APIClient, imageFunc SpecialImageFunc) string {
tempDir := t.TempDir()
_, err := imageFunc(tempDir)
assert.NilError(t, err)
rc, err := archive.TarWithOptions(tempDir, &archive.TarOptions{})
assert.NilError(t, err)
defer rc.Close()
resp, err := apiClient.ImageLoad(ctx, rc, client.ImageLoadWithQuiet(true))
assert.NilError(t, err, "Failed to load dangling image")
defer resp.Body.Close()
if !assert.Check(t, err) {
respBody, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("Failed to read response body: %v", err)
return ""
}
t.Fatalf("Failed load: %s", string(respBody))
}
all, err := io.ReadAll(resp.Body)
assert.NilError(t, err)
decoder := json.NewDecoder(bytes.NewReader(all))
for {
var msg jsonmessage.JSONMessage
err := decoder.Decode(&msg)
if errors.Is(err, io.EOF) {
break
}
assert.NilError(t, err)
msg.Stream = strings.TrimSpace(msg.Stream)
if _, imageID, hasID := strings.Cut(msg.Stream, "Loaded image ID: "); hasID {
return imageID
}
if _, imageRef, hasRef := strings.Cut(msg.Stream, "Loaded image: "); hasRef {
return imageRef
}
}
t.Fatalf("failed to read image ID\n%s", string(all))
return ""
}