From 7450c258abe01585f861f4a1b5d2b97539dbbdce Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Fri, 8 Jan 2016 15:38:55 -0800 Subject: [PATCH] Use RootFS from image config to register layers on Windows Signed-off-by: Aaron Lehmann --- distribution/pull_v2.go | 57 +++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index a364473fb9..7277d07fb1 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -406,8 +406,31 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s descriptors = append(descriptors, layerDescriptor) } - rootFS, release, err := p.config.DownloadManager.Download(ctx, *image.NewRootFS(), descriptors, p.config.ProgressOutput) + var ( + configJSON []byte // raw serialized image config + unmarshalledConfig image.Image // deserialized image config + downloadRootFS image.RootFS // rootFS to use for registering layers. + ) + if runtime.GOOS == "windows" { + configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan) + if err != nil { + return "", "", err + } + if unmarshalledConfig.RootFS == nil { + return "", "", errors.New("image config has no rootfs section") + } + downloadRootFS = *unmarshalledConfig.RootFS + downloadRootFS.DiffIDs = []layer.DiffID{} + } else { + downloadRootFS = *image.NewRootFS() + } + + rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput) if err != nil { + if configJSON != nil { + // Already received the config + return "", "", err + } select { case err = <-errChan: return "", "", err @@ -422,23 +445,16 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s } defer release() - var configJSON []byte - select { - case configJSON = <-configChan: - case err = <-errChan: - return "", "", err - // Don't need a case for ctx.Done in the select because cancellation - // will trigger an error in p.pullSchema2ImageConfig. + if configJSON == nil { + configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan) + if err != nil { + return "", "", err + } } // The DiffIDs returned in rootFS MUST match those in the config. // Otherwise the image config could be referencing layers that aren't // included in the manifest. - var unmarshalledConfig image.Image - if err = json.Unmarshal(configJSON, &unmarshalledConfig); err != nil { - return "", "", err - } - if len(rootFS.DiffIDs) != len(unmarshalledConfig.RootFS.DiffIDs) { return "", "", errRootFSMismatch } @@ -457,6 +473,21 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s return imageID, manifestDigest, nil } +func receiveConfig(configChan <-chan []byte, errChan <-chan error) ([]byte, image.Image, error) { + select { + case configJSON := <-configChan: + var unmarshalledConfig image.Image + if err := json.Unmarshal(configJSON, &unmarshalledConfig); err != nil { + return nil, image.Image{}, err + } + return configJSON, unmarshalledConfig, nil + case err := <-errChan: + return nil, image.Image{}, err + // Don't need a case for ctx.Done in the select because cancellation + // will trigger an error in p.pullSchema2ImageConfig. + } +} + // pullManifestList handles "manifest lists" which point to various // platform-specifc manifests. func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mfstList *manifestlist.DeserializedManifestList) (imageID image.ID, manifestListDigest digest.Digest, err error) {