From 1a9e70b0ce106a69697d972593e286ec8c805c16 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Mon, 30 May 2022 13:58:24 +0200 Subject: [PATCH] libimage: pull: warn if platforms do not match Warn when the platform of a pulled image does not match the user-specified platform. The checks are only performed if the user requested a custom platform. Do not error out and warn only since there are many images in the wild that claim to be of another architecture. An error would break existing workloads; we did that once and had to revert immediately. Fixes: containers/podman/issues/14293 Signed-off-by: Valentin Rothberg --- libimage/pull.go | 8 ++++++++ libimage/runtime.go | 28 +++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/libimage/pull.go b/libimage/pull.go index d204ef1c4..21c33fb2b 100644 --- a/libimage/pull.go +++ b/libimage/pull.go @@ -160,11 +160,19 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP } localImages := []*Image{} + lookupOptions := &LookupImageOptions{Architecture: options.Architecture, OS: options.OS, Variant: options.Variant} for _, name := range pulledImages { local, _, err := r.LookupImage(name, nil) if err != nil { return nil, errors.Wrapf(err, "error locating pulled image %q name in containers storage", name) } + ref, err := local.StorageReference() + if err != nil { + return nil, fmt.Errorf("creating storage reference for pulled image %q: %w", name, err) + } + if _, err := r.imageReferenceMatchesContext(ref, name, lookupOptions, options.Writer); err != nil { + return nil, fmt.Errorf("checking platform for pulled image %q: %w", name, err) + } localImages = append(localImages, local) } diff --git a/libimage/runtime.go b/libimage/runtime.go index 472482410..7d0720438 100644 --- a/libimage/runtime.go +++ b/libimage/runtime.go @@ -3,6 +3,7 @@ package libimage import ( "context" "fmt" + "io" "os" "strings" @@ -378,7 +379,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo image = instance } - matches, err := r.imageReferenceMatchesContext(ref, options) + matches, err := r.imageReferenceMatchesContext(ref, name, options, nil) if err != nil { return nil, err } @@ -499,7 +500,7 @@ func (r *Runtime) ResolveName(name string) (string, error) { // imageReferenceMatchesContext return true if the specified reference matches // the platform (os, arch, variant) as specified by the lookup options. -func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options *LookupImageOptions) (bool, error) { +func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, name string, options *LookupImageOptions, writer io.Writer) (bool, error) { if options.Architecture+options.OS+options.Variant == "" { return true, nil } @@ -515,20 +516,29 @@ func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options return false, err } + writeMessage := func(msg string) { + if writer == nil { + logrus.Debugf("WARNING: %s", msg) + } else { + fmt.Fprintf(writer, "WARNING: %s\n", msg) + } + } + + matches := true if options.Architecture != "" && options.Architecture != data.Architecture { - logrus.Debugf("architecture %q does not match architecture %q of image %s", options.Architecture, data.Architecture, ref) - return false, nil + writeMessage(fmt.Sprintf("requested architecture %q does not match architecture %q of image %s", options.Architecture, data.Architecture, name)) + matches = false } if options.OS != "" && options.OS != data.Os { - logrus.Debugf("OS %q does not match OS %q of image %s", options.OS, data.Os, ref) - return false, nil + writeMessage(fmt.Sprintf("requested OS %q does not match OS %q of image %s", options.OS, data.Os, name)) + matches = false } if options.Variant != "" && options.Variant != data.Variant { - logrus.Debugf("variant %q does not match variant %q of image %s", options.Variant, data.Variant, ref) - return false, nil + writeMessage(fmt.Sprintf("requested variant %q does not match variant %q of image %s", options.Variant, data.Variant, name)) + matches = false } - return true, nil + return matches, nil } // IsExternalContainerFunc allows for checking whether the specified container