pull: custom platform: do not use local image name

Do not use the name of the locally resolved image when pulling an image
with a custom platform.  As we recently re-discovered [1], many
multi-arch images in the wild do not adhere to the OCI image spec and
either declare custom or simply wrong platforms (arch, os, variant).

To address such wrong images, we enforce the pull-always policy whenever
a custom arch, os or variant is specified.  We have to do that since we
cannot reliably perform platform matches to any image we would find in
the local containers storage.

To complete the fix, we need to ignore any local image and not use the
locally resolved name which we usually have to do (see [2]).

Let's assume we have a local image "localhost/foo" (arch=amd64).  If we
perform a `pull --arch=arm64`, we would not attempt to be pulling
`localhost/foo` but use the ordinary short-name resolution and look for
a matching alias or walk the unqualified-search registries.

In other words: short-name resolution of multi-arch images is prone to
errors but we should continue supporting images in the wild.

[1] containers/podman/issues/10682
[2] containers/buildah/issues/2904

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2021-06-27 13:05:08 +02:00
parent b40eec5f98
commit 37f6e92ece
1 changed files with 25 additions and 14 deletions
common/libimage

View File

@ -384,18 +384,22 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
} }
} }
// Unless the pull policy is "always", we must pessimistically assume customPlatform := false
// that the local image has an invalid architecture (see if len(options.Architecture)+len(options.OS)+len(options.Variant) > 0 {
// containers/podman/issues/10682). Hence, whenever the user requests customPlatform = true
// a custom platform, set the pull policy to "always" to make sure // Unless the pull policy is "always", we must pessimistically assume
// we're pulling down the image. // that the local image has an invalid architecture (see
// // containers/podman/issues/10682). Hence, whenever the user requests
// NOTE that this is will even override --pull={false,never}. This is // a custom platform, set the pull policy to "always" to make sure
// very likely a bug but a consistent one in Podman/Buildah and should // we're pulling down the image.
// be addressed at a later point. //
if pullPolicy != config.PullPolicyAlways && len(options.Architecture)+len(options.OS)+len(options.Variant) > 0 { // NOTE that this is will even override --pull={false,never}. This is
logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "always", options.Architecture, options.OS, options.Variant) // very likely a bug but a consistent one in Podman/Buildah and should
pullPolicy = config.PullPolicyAlways // be addressed at a later point.
if pullPolicy != config.PullPolicyAlways {
logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "always", options.Architecture, options.OS, options.Variant)
pullPolicy = config.PullPolicyAlways
}
} }
if pullPolicy == config.PullPolicyNever { if pullPolicy == config.PullPolicyNever {
@ -422,8 +426,15 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
} }
// If we found a local image, we should use it's locally resolved name // If we found a local image, we should use it's locally resolved name
// (see containers/buildah #2904). // (see containers/buildah/issues/2904). An exception is if a custom
if localImage != nil { // platform is specified (e.g., `--arch=arm64`). In that case, we need
// to pessimistically pull the image since some images declare wrong
// platforms making platform checks absolutely unreliable (see
// containers/podman/issues/10682).
//
// In other words: multi-arch support can only be as good as the images
// in the wild.
if localImage != nil && !customPlatform {
if imageName != resolvedImageName { if imageName != resolvedImageName {
logrus.Debugf("Image %s resolved to local image %s which will be used for pulling", imageName, resolvedImageName) logrus.Debugf("Image %s resolved to local image %s which will be used for pulling", imageName, resolvedImageName)
} }