Fix several conversions of "ocispec.Image" to "ocispec.Platform"

Several bits of code unmarshal image config JSON into an `ocispec.Image`, and then immediately create an `ocispec.Platform` out of it, but then discard the original image *and* miss several potential platform fields (most notably, `variant`).

Because `ocispec.Platform` is a strict subset of `ocispec.Image`, most of these can be updated to simply unmarshal the image config directly to `ocispec.Platform` instead, which allows these additional fields to be picked up appropriately.

We can use `tianon/raspbian` as a concrete reproducer to demonstrate.

Before:

```console
$ ctr content fetch docker.io/tianon/raspbian:bullseye-slim
...

$ ctr image ls
REF                                     TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS    LABELS
docker.io/tianon/raspbian:bullseye-slim application/vnd.docker.distribution.manifest.v2+json sha256:66e96f8af40691b335acc54e5f69711584ef7f926597b339e7d12ab90cc394ce 28.6 MiB linux/arm/v7 -
```

(Note that the `PLATFORMS` column lists `linux/arm/v7` -- the image itself is actually `linux/arm/v6`, but one of these bits of code leads to only `linux/arm` being extracted from the image config, which `platforms.Normalize` then updates to an explicit `v7`.)

After:

```console
$ ctr image ls
REF                                     TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS    LABELS
docker.io/tianon/raspbian:bullseye-slim application/vnd.docker.distribution.manifest.v2+json sha256:66e96f8af40691b335acc54e5f69711584ef7f926597b339e7d12ab90cc394ce 28.6 MiB linux/arm/v6 -
```

Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Tianon Gravi 2022-09-07 17:22:08 -07:00
parent 6d7060099b
commit 21b3318ebe
3 changed files with 16 additions and 11 deletions

View File

@ -472,11 +472,13 @@ func (i *image) getManifestPlatform(ctx context.Context, manifest ocispec.Manife
return ocispec.Platform{}, err
}
var image ocispec.Image
if err := json.Unmarshal(p, &image); err != nil {
// Technically, this should be ocispec.Image, but we only need the
// ocispec.Platform that is embedded in the image struct.
var imagePlatform ocispec.Platform
if err := json.Unmarshal(p, &imagePlatform); err != nil {
return ocispec.Platform{}, err
}
return platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}), nil
return platforms.Normalize(imagePlatform), nil
}
func (i *image) checkSnapshotterSupport(ctx context.Context, snapshotterName string, manifest ocispec.Manifest) error {

View File

@ -174,12 +174,14 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
return nil, err
}
var image ocispec.Image
if err := json.Unmarshal(p, &image); err != nil {
// Technically, this should be ocispec.Image, but we only need the
// ocispec.Platform that is embedded in the image struct.
var imagePlatform ocispec.Platform
if err := json.Unmarshal(p, &imagePlatform); err != nil {
return nil, err
}
if !platform.Match(platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture})) {
if !platform.Match(platforms.Normalize(imagePlatform)) {
return nil, nil
}
@ -279,13 +281,14 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
return nil, err
}
var image ocispec.Image
if err := json.Unmarshal(p, &image); err != nil {
// Technically, this should be ocispec.Image, but we only need the
// ocispec.Platform that is embedded in the image struct.
var imagePlatform ocispec.Platform
if err := json.Unmarshal(p, &imagePlatform); err != nil {
return nil, err
}
platformSpecs = append(platformSpecs,
platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}))
platformSpecs = append(platformSpecs, platforms.Normalize(imagePlatform))
}
return nil, nil
}), ChildrenHandler(provider)), image)

View File

@ -253,7 +253,7 @@ func (u *Unpacker) unpack(
// TODO: Support multiple unpacks rather than just first match
var unpack *Platform
imgPlatform := platforms.Normalize(ocispec.Platform{OS: i.OS, Architecture: i.Architecture})
imgPlatform := platforms.Normalize(i.Platform)
for _, up := range u.platforms {
if up.Platform.Match(imgPlatform) {
unpack = up