Skip to content

Commit

Permalink
Merge pull request #47738 from vvoland/c8d-walk-image-badimagetarget
Browse files Browse the repository at this point in the history
c8d/list: Ignore unexpected image target
  • Loading branch information
cpuguy83 committed Apr 22, 2024
2 parents 801fd16 + 7d95fe8 commit c8af8eb
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
7 changes: 7 additions & 0 deletions daemon/containerd/image_list.go
Expand Up @@ -301,6 +301,13 @@ func (i *ImageService) imageSummary(ctx context.Context, img images.Image, platf
return nil
})
if err != nil {
if errors.Is(err, errNotManifestOrIndex) {
log.G(ctx).WithFields(log.Fields{
"error": err,
"image": img.Name,
}).Warn("unexpected image target (neither a manifest nor index)")
return nil, nil, nil
}
return nil, nil, err
}

Expand Down
13 changes: 13 additions & 0 deletions daemon/containerd/image_list_test.go
Expand Up @@ -101,6 +101,9 @@ func TestImageList(t *testing.T) {
emptyIndex, err := specialimage.EmptyIndex(blobsDir)
assert.NilError(t, err)

configTarget, err := specialimage.ConfigTarget(blobsDir)
assert.NilError(t, err)

cs := &blobsDirContentStore{blobs: filepath.Join(blobsDir, "blobs/sha256")}

for _, tc := range []struct {
Expand Down Expand Up @@ -150,6 +153,16 @@ func TestImageList(t *testing.T) {
assert.Check(t, is.Len(all, 2))
},
},
{
// Make sure an invalid image target doesn't break the whole operation
name: "one good image, second has config as a target",
images: imagesFromIndex(multilayer, configTarget),
check: func(t *testing.T, all []*imagetypes.Summary) {
assert.Check(t, is.Len(all, 1))

assert.Check(t, is.Equal(all[0].ID, multilayer.Manifests[0].Digest.String()))
},
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
Expand Down
33 changes: 33 additions & 0 deletions internal/testutils/specialimage/configtarget.go
@@ -0,0 +1,33 @@
package specialimage

import (
"github.com/containerd/containerd/platforms"
"github.com/distribution/reference"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// ConfigTarget creates an image index with an image config being used as an
// image target instead of a manifest or index.
func ConfigTarget(dir string) (*ocispec.Index, error) {
const imageRef = "config:latest"

ref, err := reference.ParseNormalizedNamed(imageRef)
if err != nil {
return nil, err
}

desc, err := writeJsonBlob(dir, ocispec.MediaTypeImageConfig, ocispec.Image{
Platform: platforms.MustParse("linux/amd64"),
Config: ocispec.ImageConfig{
Env: []string{"FOO=BAR"},
},
})
if err != nil {
return nil, err
}
desc.Annotations = map[string]string{
"io.containerd.image.name": ref.String(),
}

return ociImage(dir, ref, desc)
}
15 changes: 10 additions & 5 deletions internal/testutils/specialimage/multilayer.go
Expand Up @@ -102,19 +102,24 @@ func singlePlatformImage(dir string, ref reference.Named, manifest ocispec.Manif
}
}

if err := writeJson(legacyManifests, filepath.Join(dir, "manifest.json")); err != nil {
return nil, err
}

return ociImage(dir, ref, manifestDesc)
}

func ociImage(dir string, ref reference.Named, target ocispec.Descriptor) (*ocispec.Index, error) {
idx := ocispec.Index{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: ocispec.MediaTypeImageIndex,
Manifests: []ocispec.Descriptor{manifestDesc},
Manifests: []ocispec.Descriptor{target},
}
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 nil, err
}

err = 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
}
Expand Down

0 comments on commit c8af8eb

Please sign in to comment.