Use c/image/manifest.GuessMIMEType instead of a custom heuristic

Notably this will use the manifest mediaType field, instead of the
config docker_version field, to detect Docker v2s2 images; again,
docker_version is cleared by buildah itself, so it can't be relied
to decide on the image format.

Anyway, centralizing the tricky heuristic and using a single one
everywhere seems preferable for consistency.

This also allows only searching for OCI annotations on known OCI
images, and that in turn allows us not to silently ignore errors
when parsing OCI manifests.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>

Closes: #776
Approved by: rhatdan
This commit is contained in:
Miloslav Trmač 2018-06-11 23:53:45 +02:00 committed by Atomic Bot
parent 35f6558e84
commit e137d26ab9
1 changed files with 29 additions and 21 deletions

View File

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/containers/image/manifest"
digest "github.com/opencontainers/go-digest"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@ -176,21 +177,29 @@ func makeDockerV2S1Image(manifest docker.V2S1Manifest) (docker.V2Image, error) {
func (b *Builder) initConfig() error {
if len(b.Manifest) > 0 { // A pre-existing image, as opposed to a "FROM scratch" new one.
image := ociv1.Image{}
dimage := docker.V2Image{}
if len(b.Config) > 0 {
// Try to parse the image configuration. If we fail start over from scratch.
if err := json.Unmarshal(b.Config, &dimage); err == nil && dimage.DockerVersion != "" {
image = makeOCIv1Image(&dimage)
} else {
if err := json.Unmarshal(b.Config, &image); err != nil {
return errors.Wrapf(err, "error parsing config (as either Docker v2s2 or OCI)")
}
dimage = makeDockerV2S2Image(&image)
switch mt := manifest.GuessMIMEType(b.Manifest); mt {
case manifest.DockerV2Schema2MediaType:
dimage := docker.V2Image{}
if err := json.Unmarshal(b.Config, &dimage); err != nil {
return errors.Wrapf(err, "error parsing Docker v2s2 configuration")
}
b.OCIv1 = makeOCIv1Image(&dimage)
b.Docker = dimage
case ociv1.MediaTypeImageManifest:
image := ociv1.Image{}
if err := json.Unmarshal(b.Config, &image); err != nil {
return errors.Wrapf(err, "error parsing OCI configuration")
}
b.OCIv1 = image
b.Docker = dimage
} else {
b.Docker = makeDockerV2S2Image(&image)
// Attempt to recover format-specific data from the manifest.
v1Manifest := ociv1.Manifest{}
if err := json.Unmarshal(b.Manifest, &v1Manifest); err != nil {
return errors.Wrapf(err, "error parsing OCI manifest")
}
b.ImageAnnotations = v1Manifest.Annotations
case manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType:
// Try to dig out the image configuration from the manifest.
manifest := docker.V2S1Manifest{}
if err := json.Unmarshal(b.Manifest, &manifest); err != nil {
@ -199,17 +208,16 @@ func (b *Builder) initConfig() error {
if manifest.SchemaVersion != 1 {
return errors.Errorf("manifest is not v2s1, config is not available")
}
if dimage, err = makeDockerV2S1Image(manifest); err != nil {
dimage, err := makeDockerV2S1Image(manifest)
if err != nil {
return errors.Wrapf(err, "error converting v2s1 image to v2s2")
}
image = makeOCIv1Image(&dimage)
b.OCIv1 = image
b.OCIv1 = makeOCIv1Image(&dimage)
b.Docker = dimage
}
// Attempt to recover format-specific data from the manifest.
v1Manifest := ociv1.Manifest{}
if json.Unmarshal(b.Manifest, &v1Manifest) == nil {
b.ImageAnnotations = v1Manifest.Annotations
case "":
return errors.Errorf("can't work with an unrecognized manifest type")
default:
return errors.Errorf("unsupported manifest type %#v", mt)
}
}