diff --git a/daemon/containerd/image_list.go b/daemon/containerd/image_list.go index 1de955dadd..f1d375f174 100644 --- a/daemon/containerd/image_list.go +++ b/daemon/containerd/image_list.go @@ -154,9 +154,13 @@ func (i *ImageService) Images(ctx context.Context, opts imagetypes.ListOptions) for _, img := range uniqueImages { image, allChainsIDs, err := i.imageSummary(ctx, img, platformMatcher, opts, tagsByDigest) - if err != nil || image == nil { + if err != nil { return nil, err } + // No error, but image should be skipped. + if image == nil { + continue + } summaries = append(summaries, image) diff --git a/daemon/containerd/image_list_test.go b/daemon/containerd/image_list_test.go index eddd3ca2bb..46a3df20d4 100644 --- a/daemon/containerd/image_list_test.go +++ b/daemon/containerd/image_list_test.go @@ -48,6 +48,9 @@ func TestImageList(t *testing.T) { twoplatform, err := specialimage.TwoPlatform(blobsDir) assert.NilError(t, err) + emptyIndex, err := specialimage.EmptyIndex(blobsDir) + assert.NilError(t, err) + cs := &blobsDirContentStore{blobs: filepath.Join(blobsDir, "blobs/sha256")} snapshotter := &testSnapshotterService{} @@ -92,6 +95,13 @@ func TestImageList(t *testing.T) { assert.Check(t, is.DeepEqual(all[1].RepoTags, []string{"twoplatform:latest"})) }, }, + { + name: "three images, one is an empty index", + images: imagesFromIndex(multilayer, emptyIndex, twoplatform), + check: func(t *testing.T, all []*imagetypes.Summary) { + assert.Check(t, is.Len(all, 2)) + }, + }, } { tc := tc t.Run(tc.name, func(t *testing.T) { diff --git a/internal/testutils/specialimage/emptyindex.go b/internal/testutils/specialimage/emptyindex.go new file mode 100644 index 0000000000..a7f969d61b --- /dev/null +++ b/internal/testutils/specialimage/emptyindex.go @@ -0,0 +1,25 @@ +package specialimage + +import ( + "github.com/distribution/reference" + "github.com/opencontainers/image-spec/specs-go" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// EmptyIndex creates an image index with no manifests. +// This is equivalent to `tianon/scratch:index`. +func EmptyIndex(dir string) (*ocispec.Index, error) { + const imageRef = "emptyindex:latest" + + index := ocispec.Index{ + Versioned: specs.Versioned{SchemaVersion: 2}, + MediaType: ocispec.MediaTypeImageIndex, + Manifests: []ocispec.Descriptor{}, + } + + ref, err := reference.ParseNormalizedNamed(imageRef) + if err != nil { + return nil, err + } + return multiPlatformImage(dir, ref, index) +}