From bee8cae830370f39da11997a34864361767a58c5 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 27 Jun 2021 13:05:08 +0200 Subject: [PATCH] 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 --- libimage/pull.go | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/libimage/pull.go b/libimage/pull.go index 0a5e49fd2..8fc82ce98 100644 --- a/libimage/pull.go +++ b/libimage/pull.go @@ -384,18 +384,22 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str } } - // Unless the pull policy is "always", we must pessimistically assume - // that the local image has an invalid architecture (see - // containers/podman/issues/10682). Hence, whenever the user requests - // a custom platform, set the pull policy to "always" to make sure - // we're pulling down the image. - // - // NOTE that this is will even override --pull={false,never}. This is - // very likely a bug but a consistent one in Podman/Buildah and should - // be addressed at a later point. - if pullPolicy != config.PullPolicyAlways && len(options.Architecture)+len(options.OS)+len(options.Variant) > 0 { - 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 + customPlatform := false + if len(options.Architecture)+len(options.OS)+len(options.Variant) > 0 { + customPlatform = true + // Unless the pull policy is "always", we must pessimistically assume + // that the local image has an invalid architecture (see + // containers/podman/issues/10682). Hence, whenever the user requests + // a custom platform, set the pull policy to "always" to make sure + // we're pulling down the image. + // + // NOTE that this is will even override --pull={false,never}. This is + // very likely a bug but a consistent one in Podman/Buildah and should + // 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 { @@ -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 - // (see containers/buildah #2904). - if localImage != nil { + // (see containers/buildah/issues/2904). An exception is if a custom + // 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 { logrus.Debugf("Image %s resolved to local image %s which will be used for pulling", imageName, resolvedImageName) }