diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index cb1d6b1ee4..86a41607bb 100644 --- a/integration-cli/docker_utils_test.go +++ b/integration-cli/docker_utils_test.go @@ -473,7 +473,8 @@ func loadSpecialImage(c *testing.T, imageFunc specialimage.SpecialImageFunc) str imgDir := filepath.Join(tmpDir, "image") assert.NilError(c, os.Mkdir(imgDir, 0o755)) - assert.NilError(c, imageFunc(imgDir)) + _, err := imageFunc(imgDir) + assert.NilError(c, err) rc, err := archive.TarWithOptions(imgDir, &archive.TarOptions{}) assert.NilError(c, err) diff --git a/internal/testutils/specialimage/dangling.go b/internal/testutils/specialimage/dangling.go index 039b7eee2b..c09c8a89a4 100644 --- a/internal/testutils/specialimage/dangling.go +++ b/internal/testutils/specialimage/dangling.go @@ -4,6 +4,8 @@ import ( "os" "path/filepath" "strings" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) const danglingImageManifestDigest = "sha256:16d365089e5c10e1673ee82ab5bba38ade9b763296ad918bd24b42a1156c5456" // #nosec G101 -- ignoring: Potential hardcoded credentials (gosec) @@ -12,30 +14,30 @@ const danglingImageConfigDigest = "sha256:0df1207206e5288f4a989a2f13d1f5b3c4e704 // Dangling creates an image with no layers and no tag. // It also has an extra org.mobyproject.test.specialimage=1 label set. // Layout: OCI. -func Dangling(dir string) error { +func Dangling(dir string) (*ocispec.Index, error) { if err := os.WriteFile(filepath.Join(dir, "index.json"), []byte(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.docker.distribution.manifest.v2+json","digest":"sha256:16d365089e5c10e1673ee82ab5bba38ade9b763296ad918bd24b42a1156c5456","size":264,"annotations":{"org.opencontainers.image.created":"2023-05-19T08:00:44Z"},"platform":{"architecture":"amd64","os":"linux"}}]}`), 0o644); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(dir, "manifest.json"), []byte(`[{"Config":"blobs/sha256/0df1207206e5288f4a989a2f13d1f5b3c4e70467702c1d5d21dfc9f002b7bd43","RepoTags":null,"Layers":null}]`), 0o644); err != nil { - return err + return nil, err } if err := os.Mkdir(filepath.Join(dir, "blobs"), 0o755); err != nil { - return err + return nil, err } blobsDir := filepath.Join(dir, "blobs", "sha256") if err := os.Mkdir(blobsDir, 0o755); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(blobsDir, strings.TrimPrefix(danglingImageManifestDigest, "sha256:")), []byte(`{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:0df1207206e5288f4a989a2f13d1f5b3c4e70467702c1d5d21dfc9f002b7bd43","size":390},"layers":[]}`), 0o644); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(blobsDir, strings.TrimPrefix(danglingImageConfigDigest, "sha256:")), []byte(`{"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/","Labels":{"org.mobyproject.test.specialimage":"1"},"OnBuild":null},"created":null,"history":[{"created_by":"LABEL org.mobyproject.test.specialimage=1","comment":"buildkit.dockerfile.v0","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":null}}`), 0o644); err != nil { - return err + return nil, err } - return nil + return nil, nil } diff --git a/internal/testutils/specialimage/emptyfs.go b/internal/testutils/specialimage/emptyfs.go index e488a10ee5..014bdaba8c 100644 --- a/internal/testutils/specialimage/emptyfs.go +++ b/internal/testutils/specialimage/emptyfs.go @@ -4,53 +4,55 @@ import ( "io" "os" "path/filepath" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // EmptyFS builds an image with an empty rootfs. // Layout: Legacy Docker Archive // See https://github.com/docker/docker/pull/5262 // and also https://github.com/docker/docker/issues/4242 -func EmptyFS(dir string) error { +func EmptyFS(dir string) (*ocispec.Index, error) { if err := os.WriteFile(filepath.Join(dir, "manifest.json"), []byte(`[{"Config":"11f64303f0f7ffdc71f001788132bca5346831939a956e3e975c93267d89a16d.json","RepoTags":["emptyfs:latest"],"Layers":["511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar"]}]`), 0o644); err != nil { - return err + return nil, err } if err := os.Mkdir(filepath.Join(dir, "blobs"), 0o755); err != nil { - return err + return nil, err } blobsDir := filepath.Join(dir, "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") if err := os.Mkdir(blobsDir, 0o755); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(dir, "VERSION"), []byte(`1.0`), 0o644); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(dir, "repositories"), []byte(`{"emptyfs":{"latest":"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158"}}`), 0o644); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(dir, "11f64303f0f7ffdc71f001788132bca5346831939a956e3e975c93267d89a16d.json"), []byte(`{"architecture":"x86_64","comment":"Imported from -","container_config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2013-06-13T14:03:50.821769-07:00","docker_version":"0.4.0","history":[{"created":"2013-06-13T14:03:50.821769-07:00","comment":"Imported from -"}],"rootfs":{"type":"layers","diff_ids":["sha256:84ff92691f909a05b224e1c56abb4864f01b4f8e3c854e4bb4c7baf1d3f6d652"]}}`), 0o644); err != nil { - return err + return nil, err } if err := os.WriteFile(filepath.Join(blobsDir, "json"), []byte(`{"id":"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158","comment":"Imported from -","created":"2013-06-13T14:03:50.821769-07:00","container_config":{"Hostname":"","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":null},"docker_version":"0.4.0","architecture":"x86_64","Size":0}`+"\n"), 0o644); err != nil { - return err + return nil, err } layerFile, err := os.OpenFile(filepath.Join(blobsDir, "layer.tar"), os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { - return err + return nil, err } defer layerFile.Close() // 10240 NUL bytes is a valid empty tar archive. _, err = io.Copy(layerFile, io.LimitReader(zeroReader{}, 10240)) if err != nil { - return err + return nil, err } - return nil + return nil, nil } type zeroReader struct{} diff --git a/internal/testutils/specialimage/load.go b/internal/testutils/specialimage/load.go index d03915bece..21f588e69a 100644 --- a/internal/testutils/specialimage/load.go +++ b/internal/testutils/specialimage/load.go @@ -12,15 +12,16 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/jsonmessage" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" "gotest.tools/v3/assert" ) -type SpecialImageFunc func(string) error +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) + _, err := imageFunc(tempDir) assert.NilError(t, err) rc, err := archive.TarWithOptions(tempDir, &archive.TarOptions{}) diff --git a/internal/testutils/specialimage/multilayer.go b/internal/testutils/specialimage/multilayer.go index c14f1c1b2b..ee20380084 100644 --- a/internal/testutils/specialimage/multilayer.go +++ b/internal/testutils/specialimage/multilayer.go @@ -16,20 +16,20 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) -func MultiLayer(dir string) error { +func MultiLayer(dir string) (*ocispec.Index, error) { const imageRef = "multilayer:latest" layer1Desc, err := writeLayerWithOneFile(dir, "foo", []byte("1")) if err != nil { - return err + return nil, err } layer2Desc, err := writeLayerWithOneFile(dir, "bar", []byte("2")) if err != nil { - return err + return nil, err } layer3Desc, err := writeLayerWithOneFile(dir, "hello", []byte("world")) if err != nil { - return err + return nil, err } configDesc, err := writeJsonBlob(dir, ocispec.MediaTypeImageConfig, ocispec.Image{ @@ -43,7 +43,7 @@ func MultiLayer(dir string) error { }, }) if err != nil { - return err + return nil, err } manifest := ocispec.Manifest{ @@ -53,7 +53,7 @@ func MultiLayer(dir string) error { } legacyManifests := []manifestItem{ - manifestItem{ + { Config: blobPath(configDesc), RepoTags: []string{imageRef}, Layers: []string{blobPath(layer1Desc), blobPath(layer2Desc), blobPath(layer3Desc)}, @@ -62,7 +62,7 @@ func MultiLayer(dir string) error { ref, err := reference.ParseNormalizedNamed(imageRef) if err != nil { - return err + return nil, err } return singlePlatformImage(dir, ref, manifest, legacyManifests) } @@ -74,10 +74,10 @@ type manifestItem struct { Layers []string } -func singlePlatformImage(dir string, ref reference.Named, manifest ocispec.Manifest, legacyManifests []manifestItem) error { +func singlePlatformImage(dir string, ref reference.Named, manifest ocispec.Manifest, legacyManifests []manifestItem) (*ocispec.Index, error) { manifestDesc, err := writeJsonBlob(dir, ocispec.MediaTypeImageManifest, manifest) if err != nil { - return err + return nil, err } if ref != nil { @@ -90,25 +90,24 @@ func singlePlatformImage(dir string, ref reference.Named, manifest ocispec.Manif } } - if err := writeJson(ocispec.Index{ + idx := ocispec.Index{ Versioned: specs.Versioned{SchemaVersion: 2}, MediaType: ocispec.MediaTypeImageIndex, Manifests: []ocispec.Descriptor{manifestDesc}, - }, filepath.Join(dir, "index.json")); err != nil { - return err } - if err != nil { - return err + if err := writeJson(idx, filepath.Join(dir, "index.json")); err != nil { + return nil, err } - if err := writeJson(legacyManifests, filepath.Join(dir, "manifest.json")); err != nil { - return err - } - if err != nil { - return err + return nil, err } - return os.WriteFile(filepath.Join(dir, "oci-layout"), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0o644) + err = os.WriteFile(filepath.Join(dir, "oci-layout"), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0o644) + if err != nil { + return nil, err + } + + return &idx, nil } func fileArchive(dir string, name string, content []byte) (io.ReadCloser, error) {