Browse code

Use RootFS from image config to register layers on Windows

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>

Aaron Lehmann authored on 2016/01/09 08:38:55
Showing 1 changed files
... ...
@@ -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) {