libimage: normalize platform
Buildah, containers and probably other container engines are normalizing the platform parameters to support common values. For instance, "x86_64" is normalized to the OCI conformant "amd64". Use the same normalization when copying images and looking up local images. Also add some debug logs to facilitate future debugging. Fixes: containers/podman/issues/12680 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
463f91ec52
commit
281201d87d
|
@ -218,15 +218,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) {
|
|||
|
||||
c.systemContext.DockerArchiveAdditionalTags = options.dockerArchiveAdditionalTags
|
||||
|
||||
if options.Architecture != "" {
|
||||
c.systemContext.ArchitectureChoice = options.Architecture
|
||||
}
|
||||
if options.OS != "" {
|
||||
c.systemContext.OSChoice = options.OS
|
||||
}
|
||||
if options.Variant != "" {
|
||||
c.systemContext.VariantChoice = options.Variant
|
||||
}
|
||||
c.systemContext.OSChoice, c.systemContext.ArchitectureChoice, c.systemContext.VariantChoice = NormalizePlatform(options.OS, options.Architecture, options.Variant)
|
||||
|
||||
if options.SignaturePolicyPath != "" {
|
||||
c.systemContext.SignaturePolicyPath = options.SignaturePolicyPath
|
||||
|
|
|
@ -1,13 +1,51 @@
|
|||
package libimage
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NormalizePlatform normalizes (according to the OCI spec) the specified os,
|
||||
// arch and variant. If left empty, the individual item will not be normalized.
|
||||
func NormalizePlatform(rawOS, rawArch, rawVariant string) (os, arch, variant string) {
|
||||
os, arch, variant = rawOS, rawArch, rawVariant
|
||||
if os == "" {
|
||||
os = runtime.GOOS
|
||||
}
|
||||
if arch == "" {
|
||||
arch = runtime.GOARCH
|
||||
}
|
||||
rawPlatform := os + "/" + arch
|
||||
if variant != "" {
|
||||
rawPlatform += "/" + variant
|
||||
}
|
||||
|
||||
normalizedPlatform, err := platforms.Parse(rawPlatform)
|
||||
if err != nil {
|
||||
logrus.Debugf("Error normalizing platform: %v", err)
|
||||
return rawOS, rawArch, rawVariant
|
||||
}
|
||||
logrus.Debugf("Normalized platform %s to %s", rawPlatform, normalizedPlatform)
|
||||
os = rawOS
|
||||
if rawOS != "" {
|
||||
os = normalizedPlatform.OS
|
||||
}
|
||||
arch = rawArch
|
||||
if rawArch != "" {
|
||||
arch = normalizedPlatform.Architecture
|
||||
}
|
||||
variant = rawVariant
|
||||
if rawVariant != "" {
|
||||
variant = normalizedPlatform.Variant
|
||||
}
|
||||
return os, arch, variant
|
||||
}
|
||||
|
||||
// NormalizeName normalizes the provided name according to the conventions by
|
||||
// Podman and Buildah. If tag and digest are missing, the "latest" tag will be
|
||||
// used. If it's a short name, it will be prefixed with "localhost/".
|
||||
|
|
|
@ -7,6 +7,61 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNormalizePlatform(t *testing.T) {
|
||||
type platform struct {
|
||||
os, arch, variant string
|
||||
}
|
||||
for _, test := range []struct {
|
||||
input, expected platform
|
||||
}{
|
||||
{
|
||||
platform{"", "", ""},
|
||||
platform{"", "", ""},
|
||||
},
|
||||
{
|
||||
platform{"foo", "", "garbage"},
|
||||
platform{"foo", "", "garbage"},
|
||||
},
|
||||
{
|
||||
platform{"&", "invalid", "os"},
|
||||
platform{"&", "invalid", "os"},
|
||||
},
|
||||
{
|
||||
platform{"linux", "", ""},
|
||||
platform{"linux", "", ""},
|
||||
},
|
||||
{
|
||||
platform{"LINUX", "", ""},
|
||||
platform{"linux", "", ""},
|
||||
},
|
||||
{
|
||||
platform{"", "aarch64", ""},
|
||||
platform{"", "arm64", ""},
|
||||
},
|
||||
{
|
||||
platform{"macos", "x86_64", ""},
|
||||
platform{"darwin", "amd64", ""},
|
||||
},
|
||||
{
|
||||
platform{"linux", "amd64", ""},
|
||||
platform{"linux", "amd64", ""},
|
||||
},
|
||||
{
|
||||
platform{"linux", "arm64", "v8"},
|
||||
platform{"linux", "arm64", "v8"},
|
||||
},
|
||||
{
|
||||
platform{"linux", "aarch64", ""},
|
||||
platform{"linux", "arm64", ""},
|
||||
},
|
||||
} {
|
||||
os, arch, variant := NormalizePlatform(test.input.os, test.input.arch, test.input.variant)
|
||||
assert.Equal(t, test.expected.os, os, test.input)
|
||||
assert.Equal(t, test.expected.arch, arch, test.input)
|
||||
assert.Equal(t, test.expected.variant, variant, test.input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeName(t *testing.T) {
|
||||
const digestSuffix = "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
|
||||
|
|
|
@ -123,7 +123,12 @@ func TestPullPlatforms(t *testing.T) {
|
|||
|
||||
image, _, err = runtime.LookupImage(withTag, &LookupImageOptions{Architecture: "arm"})
|
||||
require.NoError(t, err, "lookup busybox - by arm")
|
||||
require.NotNil(t, image, "lookup busybox - by local arch")
|
||||
require.NotNil(t, image, "lookup busybox - by arm")
|
||||
|
||||
pullOptions.Architecture = "aarch64"
|
||||
pulledImages, err = runtime.Pull(ctx, withTag, config.PullPolicyAlways, pullOptions)
|
||||
require.NoError(t, err, "pull busybox - aarch64")
|
||||
require.Len(t, pulledImages, 1)
|
||||
}
|
||||
|
||||
func TestPullPolicy(t *testing.T) {
|
||||
|
|
|
@ -253,6 +253,8 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image,
|
|||
if options.Variant == "" {
|
||||
options.Variant = r.systemContext.VariantChoice
|
||||
}
|
||||
// Normalize platform to be OCI compatible (e.g., "aarch64" -> "arm64").
|
||||
options.OS, options.Architecture, options.Variant = NormalizePlatform(options.OS, options.Architecture, options.Variant)
|
||||
|
||||
// First, check if we have an exact match in the storage. Maybe an ID
|
||||
// or a fully-qualified image name.
|
||||
|
@ -489,13 +491,16 @@ func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options
|
|||
}
|
||||
|
||||
if options.Architecture != "" && options.Architecture != data.Architecture {
|
||||
return false, err
|
||||
logrus.Debugf("architecture %q does not match architecture %q of image %s", options.Architecture, data.Architecture, ref)
|
||||
return false, nil
|
||||
}
|
||||
if options.OS != "" && options.OS != data.Os {
|
||||
return false, err
|
||||
logrus.Debugf("OS %q does not match OS %q of image %s", options.OS, data.Os, ref)
|
||||
return false, nil
|
||||
}
|
||||
if options.Variant != "" && options.Variant != data.Variant {
|
||||
return false, err
|
||||
logrus.Debugf("variant %q does not match variant %q of image %s", options.Variant, data.Variant, ref)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
|
Loading…
Reference in New Issue