Browse code

Fix pulling images that contain no layers at all

The download manager assumed there was at least one layer involved in
all images. This can be false if the image is essentially a copy of
`scratch`.

Fix a nil pointer dereference that happened in this case. Add
integration tests that involve schema1 and schema2 manifests.

Fixes #21213

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

Aaron Lehmann authored on 2016/03/16 03:10:03
Showing 2 changed files
... ...
@@ -146,7 +146,11 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima
146 146
 	}
147 147
 
148 148
 	if topDownload == nil {
149
-		return rootFS, func() { layer.ReleaseAndLog(ldm.layerStore, topLayer) }, nil
149
+		return rootFS, func() {
150
+			if topLayer != nil {
151
+				layer.ReleaseAndLog(ldm.layerStore, topLayer)
152
+			}
153
+		}, nil
150 154
 	}
151 155
 
152 156
 	// Won't be using the list built up so far - will generate it
... ...
@@ -279,6 +279,31 @@ func (s *DockerSchema1RegistrySuite) TestPullIDStability(c *check.C) {
279 279
 	testPullIDStability(c)
280 280
 }
281 281
 
282
+// #21213
283
+func testPullNoLayers(c *check.C) {
284
+	repoName := fmt.Sprintf("%v/dockercli/scratch", privateRegistryURL)
285
+
286
+	_, err := buildImage(repoName, `
287
+	FROM scratch
288
+	ENV foo bar`,
289
+		true)
290
+	if err != nil {
291
+		c.Fatal(err)
292
+	}
293
+
294
+	dockerCmd(c, "push", repoName)
295
+	dockerCmd(c, "rmi", repoName)
296
+	dockerCmd(c, "pull", repoName)
297
+}
298
+
299
+func (s *DockerRegistrySuite) TestPullNoLayers(c *check.C) {
300
+	testPullNoLayers(c)
301
+}
302
+
303
+func (s *DockerSchema1RegistrySuite) TestPullNoLayers(c *check.C) {
304
+	testPullNoLayers(c)
305
+}
306
+
282 307
 func (s *DockerRegistrySuite) TestPullManifestList(c *check.C) {
283 308
 	testRequires(c, NotArm)
284 309
 	pushDigest, err := setupImage(c)