Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
| ... | ... |
@@ -406,8 +406,31 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s |
| 406 | 406 |
descriptors = append(descriptors, layerDescriptor) |
| 407 | 407 |
} |
| 408 | 408 |
|
| 409 |
- rootFS, release, err := p.config.DownloadManager.Download(ctx, *image.NewRootFS(), descriptors, p.config.ProgressOutput) |
|
| 409 |
+ var ( |
|
| 410 |
+ configJSON []byte // raw serialized image config |
|
| 411 |
+ unmarshalledConfig image.Image // deserialized image config |
|
| 412 |
+ downloadRootFS image.RootFS // rootFS to use for registering layers. |
|
| 413 |
+ ) |
|
| 414 |
+ if runtime.GOOS == "windows" {
|
|
| 415 |
+ configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan) |
|
| 416 |
+ if err != nil {
|
|
| 417 |
+ return "", "", err |
|
| 418 |
+ } |
|
| 419 |
+ if unmarshalledConfig.RootFS == nil {
|
|
| 420 |
+ return "", "", errors.New("image config has no rootfs section")
|
|
| 421 |
+ } |
|
| 422 |
+ downloadRootFS = *unmarshalledConfig.RootFS |
|
| 423 |
+ downloadRootFS.DiffIDs = []layer.DiffID{}
|
|
| 424 |
+ } else {
|
|
| 425 |
+ downloadRootFS = *image.NewRootFS() |
|
| 426 |
+ } |
|
| 427 |
+ |
|
| 428 |
+ rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput) |
|
| 410 | 429 |
if err != nil {
|
| 430 |
+ if configJSON != nil {
|
|
| 431 |
+ // Already received the config |
|
| 432 |
+ return "", "", err |
|
| 433 |
+ } |
|
| 411 | 434 |
select {
|
| 412 | 435 |
case err = <-errChan: |
| 413 | 436 |
return "", "", err |
| ... | ... |
@@ -422,23 +445,16 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s |
| 422 | 422 |
} |
| 423 | 423 |
defer release() |
| 424 | 424 |
|
| 425 |
- var configJSON []byte |
|
| 426 |
- select {
|
|
| 427 |
- case configJSON = <-configChan: |
|
| 428 |
- case err = <-errChan: |
|
| 429 |
- return "", "", err |
|
| 430 |
- // Don't need a case for ctx.Done in the select because cancellation |
|
| 431 |
- // will trigger an error in p.pullSchema2ImageConfig. |
|
| 425 |
+ if configJSON == nil {
|
|
| 426 |
+ configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan) |
|
| 427 |
+ if err != nil {
|
|
| 428 |
+ return "", "", err |
|
| 429 |
+ } |
|
| 432 | 430 |
} |
| 433 | 431 |
|
| 434 | 432 |
// The DiffIDs returned in rootFS MUST match those in the config. |
| 435 | 433 |
// Otherwise the image config could be referencing layers that aren't |
| 436 | 434 |
// included in the manifest. |
| 437 |
- var unmarshalledConfig image.Image |
|
| 438 |
- if err = json.Unmarshal(configJSON, &unmarshalledConfig); err != nil {
|
|
| 439 |
- return "", "", err |
|
| 440 |
- } |
|
| 441 |
- |
|
| 442 | 435 |
if len(rootFS.DiffIDs) != len(unmarshalledConfig.RootFS.DiffIDs) {
|
| 443 | 436 |
return "", "", errRootFSMismatch |
| 444 | 437 |
} |
| ... | ... |
@@ -457,6 +473,21 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s |
| 457 | 457 |
return imageID, manifestDigest, nil |
| 458 | 458 |
} |
| 459 | 459 |
|
| 460 |
+func receiveConfig(configChan <-chan []byte, errChan <-chan error) ([]byte, image.Image, error) {
|
|
| 461 |
+ select {
|
|
| 462 |
+ case configJSON := <-configChan: |
|
| 463 |
+ var unmarshalledConfig image.Image |
|
| 464 |
+ if err := json.Unmarshal(configJSON, &unmarshalledConfig); err != nil {
|
|
| 465 |
+ return nil, image.Image{}, err
|
|
| 466 |
+ } |
|
| 467 |
+ return configJSON, unmarshalledConfig, nil |
|
| 468 |
+ case err := <-errChan: |
|
| 469 |
+ return nil, image.Image{}, err
|
|
| 470 |
+ // Don't need a case for ctx.Done in the select because cancellation |
|
| 471 |
+ // will trigger an error in p.pullSchema2ImageConfig. |
|
| 472 |
+ } |
|
| 473 |
+} |
|
| 474 |
+ |
|
| 460 | 475 |
// pullManifestList handles "manifest lists" which point to various |
| 461 | 476 |
// platform-specifc manifests. |
| 462 | 477 |
func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mfstList *manifestlist.DeserializedManifestList) (imageID image.ID, manifestListDigest digest.Digest, err error) {
|