Browse code

Add integration test for pulling a manifest list

The test injects a synthetic manifest list into the registry blob store,
since there isn't a tool for pushing them yet.

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

Aaron Lehmann authored on 2015/12/19 09:03:38
Showing 1 changed files
... ...
@@ -1,10 +1,20 @@
1 1
 package main
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"fmt"
6
+	"io/ioutil"
7
+	"os"
5 8
 	"os/exec"
9
+	"path/filepath"
10
+	"runtime"
6 11
 	"strings"
7 12
 
13
+	"github.com/docker/distribution"
14
+	"github.com/docker/distribution/digest"
15
+	"github.com/docker/distribution/manifest"
16
+	"github.com/docker/distribution/manifest/manifestlist"
17
+	"github.com/docker/distribution/manifest/schema2"
8 18
 	"github.com/docker/docker/pkg/integration/checker"
9 19
 	"github.com/go-check/check"
10 20
 )
... ...
@@ -280,3 +290,85 @@ func (s *DockerRegistrySuite) TestPullFallbackOn404(c *check.C) {
280 280
 
281 281
 	c.Assert(out, checker.Contains, "v1 ping attempt")
282 282
 }
283
+
284
+func (s *DockerRegistrySuite) TestPullManifestList(c *check.C) {
285
+	pushDigest, err := setupImage(c)
286
+	c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
287
+
288
+	// Inject a manifest list into the registry
289
+	manifestList := &manifestlist.ManifestList{
290
+		Versioned: manifest.Versioned{
291
+			SchemaVersion: 2,
292
+			MediaType:     manifestlist.MediaTypeManifestList,
293
+		},
294
+		Manifests: []manifestlist.ManifestDescriptor{
295
+			{
296
+				Descriptor: distribution.Descriptor{
297
+					Digest:    "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
298
+					Size:      3253,
299
+					MediaType: schema2.MediaTypeManifest,
300
+				},
301
+				Platform: manifestlist.PlatformSpec{
302
+					Architecture: "bogus_arch",
303
+					OS:           "bogus_os",
304
+				},
305
+			},
306
+			{
307
+				Descriptor: distribution.Descriptor{
308
+					Digest:    pushDigest,
309
+					Size:      3253,
310
+					MediaType: schema2.MediaTypeManifest,
311
+				},
312
+				Platform: manifestlist.PlatformSpec{
313
+					Architecture: runtime.GOARCH,
314
+					OS:           runtime.GOOS,
315
+				},
316
+			},
317
+		},
318
+	}
319
+
320
+	manifestListJSON, err := json.MarshalIndent(manifestList, "", "   ")
321
+	c.Assert(err, checker.IsNil, check.Commentf("error marshalling manifest list"))
322
+
323
+	manifestListDigest := digest.FromBytes(manifestListJSON)
324
+	hexDigest := manifestListDigest.Hex()
325
+
326
+	registryV2Path := filepath.Join(s.reg.dir, "docker", "registry", "v2")
327
+
328
+	// Write manifest list to blob store
329
+	blobDir := filepath.Join(registryV2Path, "blobs", "sha256", hexDigest[:2], hexDigest)
330
+	err = os.MkdirAll(blobDir, 0755)
331
+	c.Assert(err, checker.IsNil, check.Commentf("error creating blob dir"))
332
+	blobPath := filepath.Join(blobDir, "data")
333
+	err = ioutil.WriteFile(blobPath, []byte(manifestListJSON), 0644)
334
+	c.Assert(err, checker.IsNil, check.Commentf("error writing manifest list"))
335
+
336
+	// Add to revision store
337
+	revisionDir := filepath.Join(registryV2Path, "repositories", remoteRepoName, "_manifests", "revisions", "sha256", hexDigest)
338
+	err = os.Mkdir(revisionDir, 0755)
339
+	c.Assert(err, checker.IsNil, check.Commentf("error creating revision dir"))
340
+	revisionPath := filepath.Join(revisionDir, "link")
341
+	err = ioutil.WriteFile(revisionPath, []byte(manifestListDigest.String()), 0644)
342
+	c.Assert(err, checker.IsNil, check.Commentf("error writing revision link"))
343
+
344
+	// Update tag
345
+	tagPath := filepath.Join(registryV2Path, "repositories", remoteRepoName, "_manifests", "tags", "latest", "current", "link")
346
+	err = ioutil.WriteFile(tagPath, []byte(manifestListDigest.String()), 0644)
347
+	c.Assert(err, checker.IsNil, check.Commentf("error writing tag link"))
348
+
349
+	// Verify that the image can be pulled through the manifest list.
350
+	out, _ := dockerCmd(c, "pull", repoName)
351
+
352
+	// The pull output includes "Digest: <digest>", so find that
353
+	matches := digestRegex.FindStringSubmatch(out)
354
+	c.Assert(matches, checker.HasLen, 2, check.Commentf("unable to parse digest from pull output: %s", out))
355
+	pullDigest := matches[1]
356
+
357
+	// Make sure the pushed and pull digests match
358
+	c.Assert(manifestListDigest.String(), checker.Equals, pullDigest)
359
+
360
+	// Was the image actually created?
361
+	dockerCmd(c, "inspect", repoName)
362
+
363
+	dockerCmd(c, "rmi", repoName)
364
+}