diff --git a/distribution/config.go b/distribution/config.go index 71a3f11c07..48b0b46e26 100644 --- a/distribution/config.go +++ b/distribution/config.go @@ -3,7 +3,6 @@ package distribution // import "github.com/docker/docker/distribution" import ( "context" "encoding/json" - "fmt" "io" "runtime" @@ -21,6 +20,7 @@ import ( "github.com/docker/libtrust" digest "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" ) // Config stores configuration for communicating @@ -155,20 +155,12 @@ func (s *imageConfigStore) PlatformFromConfig(c []byte) (*specs.Platform, error) return nil, err } - // fail immediately on Windows when downloading a non-Windows image - // and vice versa. Exception on Windows if Linux Containers are enabled. - if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" && !system.LCOWSupported() { - return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) - } else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" { - return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) - } - os := unmarshalledConfig.OS if os == "" { os = runtime.GOOS } if !system.IsOSSupported(os) { - return nil, system.ErrNotSupportedOperatingSystem + return nil, errors.Wrapf(system.ErrNotSupportedOperatingSystem, "image operating system %q cannot be used on this platform", os) } return &specs.Platform{OS: os, Architecture: unmarshalledConfig.Architecture, Variant: unmarshalledConfig.Variant, OSVersion: unmarshalledConfig.OSVersion}, nil } diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index a8aa712fb1..cecc6ca13a 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -8,7 +8,6 @@ import ( "io/ioutil" "os" "runtime" - "strings" "github.com/containerd/containerd/log" "github.com/containerd/containerd/platforms" @@ -487,6 +486,14 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform } func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unverifiedManifest *schema1.SignedManifest, platform *specs.Platform) (id digest.Digest, manifestDigest digest.Digest, err error) { + if platform != nil { + // Early bath if the requested OS doesn't match that of the configuration. + // This avoids doing the download, only to potentially fail later. + if !system.IsOSSupported(platform.OS) { + return "", "", fmt.Errorf("cannot download image with operating system %q when requesting %q", runtime.GOOS, platform.OS) + } + } + var verifiedManifest *schema1.Manifest verifiedManifest, err = verifySchema1Manifest(unverifiedManifest, ref) if err != nil { @@ -541,44 +548,7 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unv descriptors = append(descriptors, layerDescriptor) } - // The v1 manifest itself doesn't directly contain an OS. However, - // the history does, but unfortunately that's a string, so search through - // all the history until hopefully we find one which indicates the OS. - // supertest2014/nyan is an example of a registry image with schemav1. - configOS := runtime.GOOS - if system.LCOWSupported() { - type config struct { - Os string `json:"os,omitempty"` - } - for _, v := range verifiedManifest.History { - var c config - if err := json.Unmarshal([]byte(v.V1Compatibility), &c); err == nil { - if c.Os != "" { - configOS = c.Os - break - } - } - } - } - - // In the situation that the API call didn't specify an OS explicitly, but - // we support the operating system, switch to that operating system. - // eg FROM supertest2014/nyan with no platform specifier, and docker build - // with no --platform= flag under LCOW. - requestedOS := "" - if platform != nil { - requestedOS = platform.OS - } else if system.IsOSSupported(configOS) { - requestedOS = configOS - } - - // Early bath if the requested OS doesn't match that of the configuration. - // This avoids doing the download, only to potentially fail later. - if !strings.EqualFold(configOS, requestedOS) { - return "", "", fmt.Errorf("cannot download image with operating system %q when requesting %q", configOS, requestedOS) - } - - resultRootFS, release, err := p.config.DownloadManager.Download(ctx, *rootFS, configOS, descriptors, p.config.ProgressOutput) + resultRootFS, release, err := p.config.DownloadManager.Download(ctx, *rootFS, runtime.GOOS, descriptors, p.config.ProgressOutput) if err != nil { return "", "", err }