1
0
mirror of https://github.com/moby/moby.git synced 2025-07-30 18:23:29 +03:00

Update daemon and docker core to use new content addressable storage

Add distribution package for managing pulls and pushes. This is based on
the old code in the graph package, with major changes to work with the
new image/layer model.

Add v1 migration code.

Update registry, api/*, and daemon packages to use the reference
package's types where applicable.

Update daemon package to use image/layer/tag stores instead of the graph
package

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2015-11-18 14:20:54 -08:00
committed by Aaron Lehmann
parent 5fc0e1f324
commit 4352da7803
70 changed files with 2037 additions and 1282 deletions

View File

@ -1,11 +1,7 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"time"
@ -46,19 +42,19 @@ func (s *DockerHubPullSuite) TestPullFromCentralRegistry(c *check.C) {
func (s *DockerHubPullSuite) TestPullNonExistingImage(c *check.C) {
testRequires(c, DaemonIsLinux)
for _, e := range []struct {
Image string
Repo string
Alias string
}{
{"library/asdfasdf:foobar", "asdfasdf:foobar"},
{"library/asdfasdf:foobar", "library/asdfasdf:foobar"},
{"library/asdfasdf:latest", "asdfasdf"},
{"library/asdfasdf:latest", "asdfasdf:latest"},
{"library/asdfasdf:latest", "library/asdfasdf"},
{"library/asdfasdf:latest", "library/asdfasdf:latest"},
{"library/asdfasdf", "asdfasdf:foobar"},
{"library/asdfasdf", "library/asdfasdf:foobar"},
{"library/asdfasdf", "asdfasdf"},
{"library/asdfasdf", "asdfasdf:latest"},
{"library/asdfasdf", "library/asdfasdf"},
{"library/asdfasdf", "library/asdfasdf:latest"},
} {
out, err := s.CmdWithError("pull", e.Alias)
c.Assert(err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", out))
c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Image), check.Commentf("expected image not found error messages"))
c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Repo), check.Commentf("expected image not found error messages"))
}
}
@ -163,254 +159,3 @@ func (s *DockerHubPullSuite) TestPullClientDisconnect(c *check.C) {
time.Sleep(500 * time.Millisecond)
}
}
type idAndParent struct {
ID string
Parent string
}
func inspectImage(c *check.C, imageRef string) idAndParent {
out, _ := dockerCmd(c, "inspect", imageRef)
var inspectOutput []idAndParent
err := json.Unmarshal([]byte(out), &inspectOutput)
if err != nil {
c.Fatal(err)
}
return inspectOutput[0]
}
func imageID(c *check.C, imageRef string) string {
return inspectImage(c, imageRef).ID
}
func imageParent(c *check.C, imageRef string) string {
return inspectImage(c, imageRef).Parent
}
// TestPullMigration verifies that pulling an image based on layers
// that already exists locally will reuse those existing layers.
func (s *DockerRegistrySuite) TestPullMigration(c *check.C) {
repoName := privateRegistryURL + "/dockercli/migration"
baseImage := repoName + ":base"
_, err := buildImage(baseImage, fmt.Sprintf(`
FROM scratch
ENV IMAGE base
CMD echo %s
`, baseImage), true)
if err != nil {
c.Fatal(err)
}
baseIDBeforePush := imageID(c, baseImage)
baseParentBeforePush := imageParent(c, baseImage)
derivedImage := repoName + ":derived"
_, err = buildImage(derivedImage, fmt.Sprintf(`
FROM %s
CMD echo %s
`, baseImage, derivedImage), true)
if err != nil {
c.Fatal(err)
}
derivedIDBeforePush := imageID(c, derivedImage)
dockerCmd(c, "push", derivedImage)
// Remove derived image from the local store
dockerCmd(c, "rmi", derivedImage)
// Repull
dockerCmd(c, "pull", derivedImage)
// Check that the parent of this pulled image is the original base
// image
derivedIDAfterPull1 := imageID(c, derivedImage)
derivedParentAfterPull1 := imageParent(c, derivedImage)
if derivedIDAfterPull1 == derivedIDBeforePush {
c.Fatal("image's ID should have changed on after deleting and pulling")
}
if derivedParentAfterPull1 != baseIDBeforePush {
c.Fatalf("pulled image's parent ID (%s) does not match base image's ID (%s)", derivedParentAfterPull1, baseIDBeforePush)
}
// Confirm that repushing and repulling does not change the computed ID
dockerCmd(c, "push", derivedImage)
dockerCmd(c, "rmi", derivedImage)
dockerCmd(c, "pull", derivedImage)
derivedIDAfterPull2 := imageID(c, derivedImage)
derivedParentAfterPull2 := imageParent(c, derivedImage)
if derivedIDAfterPull2 != derivedIDAfterPull1 {
c.Fatal("image's ID unexpectedly changed after a repush/repull")
}
if derivedParentAfterPull2 != baseIDBeforePush {
c.Fatalf("pulled image's parent ID (%s) does not match base image's ID (%s)", derivedParentAfterPull2, baseIDBeforePush)
}
// Remove everything, repull, and make sure everything uses computed IDs
dockerCmd(c, "rmi", baseImage, derivedImage)
dockerCmd(c, "pull", derivedImage)
derivedIDAfterPull3 := imageID(c, derivedImage)
derivedParentAfterPull3 := imageParent(c, derivedImage)
derivedGrandparentAfterPull3 := imageParent(c, derivedParentAfterPull3)
if derivedIDAfterPull3 != derivedIDAfterPull1 {
c.Fatal("image's ID unexpectedly changed after a second repull")
}
if derivedParentAfterPull3 == baseIDBeforePush {
c.Fatalf("pulled image's parent ID (%s) should not match base image's original ID (%s)", derivedParentAfterPull3, derivedIDBeforePush)
}
if derivedGrandparentAfterPull3 == baseParentBeforePush {
c.Fatal("base image's parent ID should have been rewritten on pull")
}
}
// TestPullMigrationRun verifies that pulling an image based on layers
// that already exists locally will result in an image that runs properly.
func (s *DockerRegistrySuite) TestPullMigrationRun(c *check.C) {
type idAndParent struct {
ID string
Parent string
}
derivedImage := privateRegistryURL + "/dockercli/migration-run"
baseImage := "busybox"
_, err := buildImage(derivedImage, fmt.Sprintf(`
FROM %s
RUN dd if=/dev/zero of=/file bs=1024 count=1024
CMD echo %s
`, baseImage, derivedImage), true)
if err != nil {
c.Fatal(err)
}
baseIDBeforePush := imageID(c, baseImage)
derivedIDBeforePush := imageID(c, derivedImage)
dockerCmd(c, "push", derivedImage)
// Remove derived image from the local store
dockerCmd(c, "rmi", derivedImage)
// Repull
dockerCmd(c, "pull", derivedImage)
// Check that this pulled image is based on the original base image
derivedIDAfterPull1 := imageID(c, derivedImage)
derivedParentAfterPull1 := imageParent(c, imageParent(c, derivedImage))
if derivedIDAfterPull1 == derivedIDBeforePush {
c.Fatal("image's ID should have changed on after deleting and pulling")
}
if derivedParentAfterPull1 != baseIDBeforePush {
c.Fatalf("pulled image's parent ID (%s) does not match base image's ID (%s)", derivedParentAfterPull1, baseIDBeforePush)
}
// Make sure the image runs correctly
out, _ := dockerCmd(c, "run", "--rm", derivedImage)
if strings.TrimSpace(out) != derivedImage {
c.Fatalf("expected %s; got %s", derivedImage, out)
}
// Confirm that repushing and repulling does not change the computed ID
dockerCmd(c, "push", derivedImage)
dockerCmd(c, "rmi", derivedImage)
dockerCmd(c, "pull", derivedImage)
derivedIDAfterPull2 := imageID(c, derivedImage)
derivedParentAfterPull2 := imageParent(c, imageParent(c, derivedImage))
if derivedIDAfterPull2 != derivedIDAfterPull1 {
c.Fatal("image's ID unexpectedly changed after a repush/repull")
}
if derivedParentAfterPull2 != baseIDBeforePush {
c.Fatalf("pulled image's parent ID (%s) does not match base image's ID (%s)", derivedParentAfterPull2, baseIDBeforePush)
}
// Make sure the image still runs
out, _ = dockerCmd(c, "run", "--rm", derivedImage)
if strings.TrimSpace(out) != derivedImage {
c.Fatalf("expected %s; got %s", derivedImage, out)
}
}
// TestPullConflict provides coverage of the situation where a computed
// strongID conflicts with some unverifiable data in the graph.
func (s *DockerRegistrySuite) TestPullConflict(c *check.C) {
repoName := privateRegistryURL + "/dockercli/conflict"
_, err := buildImage(repoName, `
FROM scratch
ENV IMAGE conflict
CMD echo conflict
`, true)
if err != nil {
c.Fatal(err)
}
dockerCmd(c, "push", repoName)
// Pull to make it content-addressable
dockerCmd(c, "rmi", repoName)
dockerCmd(c, "pull", repoName)
IDBeforeLoad := imageID(c, repoName)
// Load/save to turn this into an unverified image with the same ID
tmpDir, err := ioutil.TempDir("", "conflict-save-output")
if err != nil {
c.Errorf("failed to create temporary directory: %s", err)
}
defer os.RemoveAll(tmpDir)
tarFile := filepath.Join(tmpDir, "repo.tar")
dockerCmd(c, "save", "-o", tarFile, repoName)
dockerCmd(c, "rmi", repoName)
dockerCmd(c, "load", "-i", tarFile)
// Check that the the ID is the same after save/load.
IDAfterLoad := imageID(c, repoName)
if IDAfterLoad != IDBeforeLoad {
c.Fatal("image's ID should be the same after save/load")
}
// Repull
dockerCmd(c, "pull", repoName)
// Check that the ID is now different because of the conflict.
IDAfterPull1 := imageID(c, repoName)
// Expect the new ID to be SHA256(oldID)
expectedIDDigest, err := digest.FromBytes([]byte(IDBeforeLoad))
if err != nil {
c.Fatalf("digest error: %v", err)
}
expectedID := expectedIDDigest.Hex()
if IDAfterPull1 != expectedID {
c.Fatalf("image's ID should have changed on pull to %s (got %s)", expectedID, IDAfterPull1)
}
// A second pull should use the new ID again.
dockerCmd(c, "pull", repoName)
IDAfterPull2 := imageID(c, repoName)
if IDAfterPull2 != IDAfterPull1 {
c.Fatal("image's ID unexpectedly changed after a repull")
}
}