github.com/slene/docker@v1.8.0-rc1/integration-cli/docker_cli_by_digest_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/utils"
     9  	"github.com/go-check/check"
    10  )
    11  
    12  var (
    13  	repoName        = fmt.Sprintf("%v/dockercli/busybox-by-dgst", privateRegistryURL)
    14  	pushDigestRegex = regexp.MustCompile("[\\S]+: digest: ([\\S]+) size: [0-9]+")
    15  	digestRegex     = regexp.MustCompile("Digest: ([\\S]+)")
    16  )
    17  
    18  func setupImage(c *check.C) (string, error) {
    19  	return setupImageWithTag(c, "latest")
    20  }
    21  
    22  func setupImageWithTag(c *check.C, tag string) (string, error) {
    23  	containerName := "busyboxbydigest"
    24  
    25  	dockerCmd(c, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
    26  
    27  	// tag the image to upload it to the private registry
    28  	repoAndTag := utils.ImageReference(repoName, tag)
    29  	if out, _, err := dockerCmdWithError(c, "commit", containerName, repoAndTag); err != nil {
    30  		return "", fmt.Errorf("image tagging failed: %s, %v", out, err)
    31  	}
    32  
    33  	// delete the container as we don't need it any more
    34  	if err := deleteContainer(containerName); err != nil {
    35  		return "", err
    36  	}
    37  
    38  	// push the image
    39  	out, _, err := dockerCmdWithError(c, "push", repoAndTag)
    40  	if err != nil {
    41  		return "", fmt.Errorf("pushing the image to the private registry has failed: %s, %v", out, err)
    42  	}
    43  
    44  	// delete our local repo that we previously tagged
    45  	if rmiout, _, err := dockerCmdWithError(c, "rmi", repoAndTag); err != nil {
    46  		return "", fmt.Errorf("error deleting images prior to real test: %s, %v", rmiout, err)
    47  	}
    48  
    49  	matches := pushDigestRegex.FindStringSubmatch(out)
    50  	if len(matches) != 2 {
    51  		return "", fmt.Errorf("unable to parse digest from push output: %s", out)
    52  	}
    53  	pushDigest := matches[1]
    54  
    55  	return pushDigest, nil
    56  }
    57  
    58  func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *check.C) {
    59  	pushDigest, err := setupImage(c)
    60  	if err != nil {
    61  		c.Fatalf("error setting up image: %v", err)
    62  	}
    63  
    64  	// pull from the registry using the tag
    65  	out, _ := dockerCmd(c, "pull", repoName)
    66  
    67  	// the pull output includes "Digest: <digest>", so find that
    68  	matches := digestRegex.FindStringSubmatch(out)
    69  	if len(matches) != 2 {
    70  		c.Fatalf("unable to parse digest from pull output: %s", out)
    71  	}
    72  	pullDigest := matches[1]
    73  
    74  	// make sure the pushed and pull digests match
    75  	if pushDigest != pullDigest {
    76  		c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
    77  	}
    78  }
    79  
    80  func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) {
    81  	pushDigest, err := setupImage(c)
    82  	if err != nil {
    83  		c.Fatalf("error setting up image: %v", err)
    84  	}
    85  
    86  	// pull from the registry using the <name>@<digest> reference
    87  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
    88  	out, _ := dockerCmd(c, "pull", imageReference)
    89  
    90  	// the pull output includes "Digest: <digest>", so find that
    91  	matches := digestRegex.FindStringSubmatch(out)
    92  	if len(matches) != 2 {
    93  		c.Fatalf("unable to parse digest from pull output: %s", out)
    94  	}
    95  	pullDigest := matches[1]
    96  
    97  	// make sure the pushed and pull digests match
    98  	if pushDigest != pullDigest {
    99  		c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
   100  	}
   101  }
   102  
   103  func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) {
   104  	// pull from the registry using the <name>@<digest> reference
   105  	imageReference := fmt.Sprintf("%s@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", repoName)
   106  	out, _, err := dockerCmdWithError(c, "pull", imageReference)
   107  	if err == nil || !strings.Contains(out, "manifest unknown") {
   108  		c.Fatalf("expected non-zero exit status and correct error message when pulling non-existing image: %s", out)
   109  	}
   110  }
   111  
   112  func (s *DockerRegistrySuite) TestCreateByDigest(c *check.C) {
   113  	pushDigest, err := setupImage(c)
   114  	if err != nil {
   115  		c.Fatalf("error setting up image: %v", err)
   116  	}
   117  
   118  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   119  
   120  	containerName := "createByDigest"
   121  	out, _ := dockerCmd(c, "create", "--name", containerName, imageReference)
   122  
   123  	res, err := inspectField(containerName, "Config.Image")
   124  	if err != nil {
   125  		c.Fatalf("failed to get Config.Image: %s, %v", out, err)
   126  	}
   127  	if res != imageReference {
   128  		c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
   129  	}
   130  }
   131  
   132  func (s *DockerRegistrySuite) TestRunByDigest(c *check.C) {
   133  	pushDigest, err := setupImage(c)
   134  	if err != nil {
   135  		c.Fatalf("error setting up image: %v", err)
   136  	}
   137  
   138  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   139  
   140  	containerName := "runByDigest"
   141  	out, _ := dockerCmd(c, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
   142  
   143  	foundRegex := regexp.MustCompile("found=([^\n]+)")
   144  	matches := foundRegex.FindStringSubmatch(out)
   145  	if len(matches) != 2 {
   146  		c.Fatalf("error locating expected 'found=1' output: %s", out)
   147  	}
   148  	if matches[1] != "1" {
   149  		c.Fatalf("Expected %q, got %q", "1", matches[1])
   150  	}
   151  
   152  	res, err := inspectField(containerName, "Config.Image")
   153  	if err != nil {
   154  		c.Fatalf("failed to get Config.Image: %s, %v", out, err)
   155  	}
   156  	if res != imageReference {
   157  		c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
   158  	}
   159  }
   160  
   161  func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *check.C) {
   162  	digest, err := setupImage(c)
   163  	if err != nil {
   164  		c.Fatalf("error setting up image: %v", err)
   165  	}
   166  
   167  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   168  
   169  	// pull from the registry using the <name>@<digest> reference
   170  	dockerCmd(c, "pull", imageReference)
   171  
   172  	// make sure inspect runs ok
   173  	if _, err := inspectField(imageReference, "Id"); err != nil {
   174  		c.Fatalf("failed to inspect image: %v", err)
   175  	}
   176  
   177  	// do the delete
   178  	if err := deleteImages(imageReference); err != nil {
   179  		c.Fatalf("unexpected error deleting image: %v", err)
   180  	}
   181  
   182  	// try to inspect again - it should error this time
   183  	if _, err := inspectField(imageReference, "Id"); err == nil {
   184  		c.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
   185  	} else if !strings.Contains(err.Error(), "No such image") {
   186  		c.Fatalf("expected 'No such image' output, got %v", err)
   187  	}
   188  }
   189  
   190  func (s *DockerRegistrySuite) TestBuildByDigest(c *check.C) {
   191  	digest, err := setupImage(c)
   192  	if err != nil {
   193  		c.Fatalf("error setting up image: %v", err)
   194  	}
   195  
   196  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   197  
   198  	// pull from the registry using the <name>@<digest> reference
   199  	dockerCmd(c, "pull", imageReference)
   200  
   201  	// get the image id
   202  	imageID, err := inspectField(imageReference, "Id")
   203  	if err != nil {
   204  		c.Fatalf("error getting image id: %v", err)
   205  	}
   206  
   207  	// do the build
   208  	name := "buildbydigest"
   209  	_, err = buildImage(name, fmt.Sprintf(
   210  		`FROM %s
   211       CMD ["/bin/echo", "Hello World"]`, imageReference),
   212  		true)
   213  	if err != nil {
   214  		c.Fatal(err)
   215  	}
   216  
   217  	// get the build's image id
   218  	res, err := inspectField(name, "Config.Image")
   219  	if err != nil {
   220  		c.Fatal(err)
   221  	}
   222  	// make sure they match
   223  	if res != imageID {
   224  		c.Fatalf("Image %s, expected %s", res, imageID)
   225  	}
   226  }
   227  
   228  func (s *DockerRegistrySuite) TestTagByDigest(c *check.C) {
   229  	digest, err := setupImage(c)
   230  	if err != nil {
   231  		c.Fatalf("error setting up image: %v", err)
   232  	}
   233  
   234  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   235  
   236  	// pull from the registry using the <name>@<digest> reference
   237  	dockerCmd(c, "pull", imageReference)
   238  
   239  	// tag it
   240  	tag := "tagbydigest"
   241  	dockerCmd(c, "tag", imageReference, tag)
   242  
   243  	expectedID, err := inspectField(imageReference, "Id")
   244  	if err != nil {
   245  		c.Fatalf("error getting original image id: %v", err)
   246  	}
   247  
   248  	tagID, err := inspectField(tag, "Id")
   249  	if err != nil {
   250  		c.Fatalf("error getting tagged image id: %v", err)
   251  	}
   252  
   253  	if tagID != expectedID {
   254  		c.Fatalf("expected image id %q, got %q", expectedID, tagID)
   255  	}
   256  }
   257  
   258  func (s *DockerRegistrySuite) TestListImagesWithoutDigests(c *check.C) {
   259  	digest, err := setupImage(c)
   260  	if err != nil {
   261  		c.Fatalf("error setting up image: %v", err)
   262  	}
   263  
   264  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   265  
   266  	// pull from the registry using the <name>@<digest> reference
   267  	dockerCmd(c, "pull", imageReference)
   268  
   269  	out, _ := dockerCmd(c, "images")
   270  
   271  	if strings.Contains(out, "DIGEST") {
   272  		c.Fatalf("list output should not have contained DIGEST header: %s", out)
   273  	}
   274  
   275  }
   276  
   277  func (s *DockerRegistrySuite) TestListImagesWithDigests(c *check.C) {
   278  
   279  	// setup image1
   280  	digest1, err := setupImageWithTag(c, "tag1")
   281  	if err != nil {
   282  		c.Fatalf("error setting up image: %v", err)
   283  	}
   284  	imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
   285  	c.Logf("imageReference1 = %s", imageReference1)
   286  
   287  	// pull image1 by digest
   288  	dockerCmd(c, "pull", imageReference1)
   289  
   290  	// list images
   291  	out, _ := dockerCmd(c, "images", "--digests")
   292  
   293  	// make sure repo shown, tag=<none>, digest = $digest1
   294  	re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
   295  	if !re1.MatchString(out) {
   296  		c.Fatalf("expected %q: %s", re1.String(), out)
   297  	}
   298  
   299  	// setup image2
   300  	digest2, err := setupImageWithTag(c, "tag2")
   301  	if err != nil {
   302  		c.Fatalf("error setting up image: %v", err)
   303  	}
   304  	imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
   305  	c.Logf("imageReference2 = %s", imageReference2)
   306  
   307  	// pull image1 by digest
   308  	dockerCmd(c, "pull", imageReference1)
   309  
   310  	// pull image2 by digest
   311  	dockerCmd(c, "pull", imageReference2)
   312  
   313  	// list images
   314  	out, _ = dockerCmd(c, "images", "--digests")
   315  
   316  	// make sure repo shown, tag=<none>, digest = $digest1
   317  	if !re1.MatchString(out) {
   318  		c.Fatalf("expected %q: %s", re1.String(), out)
   319  	}
   320  
   321  	// make sure repo shown, tag=<none>, digest = $digest2
   322  	re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
   323  	if !re2.MatchString(out) {
   324  		c.Fatalf("expected %q: %s", re2.String(), out)
   325  	}
   326  
   327  	// pull tag1
   328  	dockerCmd(c, "pull", repoName+":tag1")
   329  
   330  	// list images
   331  	out, _ = dockerCmd(c, "images", "--digests")
   332  
   333  	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
   334  	reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
   335  	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
   336  	if !reWithTag1.MatchString(out) {
   337  		c.Fatalf("expected %q: %s", reWithTag1.String(), out)
   338  	}
   339  	if !reWithDigest1.MatchString(out) {
   340  		c.Fatalf("expected %q: %s", reWithDigest1.String(), out)
   341  	}
   342  	// make sure image 2 has repo, <none>, digest
   343  	if !re2.MatchString(out) {
   344  		c.Fatalf("expected %q: %s", re2.String(), out)
   345  	}
   346  
   347  	// pull tag 2
   348  	dockerCmd(c, "pull", repoName+":tag2")
   349  
   350  	// list images
   351  	out, _ = dockerCmd(c, "images", "--digests")
   352  
   353  	// make sure image 1 has repo, tag, digest
   354  	if !reWithTag1.MatchString(out) {
   355  		c.Fatalf("expected %q: %s", re1.String(), out)
   356  	}
   357  
   358  	// make sure image 2 has repo, tag, digest
   359  	reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
   360  	reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
   361  	if !reWithTag2.MatchString(out) {
   362  		c.Fatalf("expected %q: %s", reWithTag2.String(), out)
   363  	}
   364  	if !reWithDigest2.MatchString(out) {
   365  		c.Fatalf("expected %q: %s", reWithDigest2.String(), out)
   366  	}
   367  
   368  	// list images
   369  	out, _ = dockerCmd(c, "images", "--digests")
   370  
   371  	// make sure image 1 has repo, tag, digest
   372  	if !reWithTag1.MatchString(out) {
   373  		c.Fatalf("expected %q: %s", re1.String(), out)
   374  	}
   375  	// make sure image 2 has repo, tag, digest
   376  	if !reWithTag2.MatchString(out) {
   377  		c.Fatalf("expected %q: %s", re2.String(), out)
   378  	}
   379  	// make sure busybox has tag, but not digest
   380  	busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
   381  	if !busyboxRe.MatchString(out) {
   382  		c.Fatalf("expected %q: %s", busyboxRe.String(), out)
   383  	}
   384  }
   385  
   386  func (s *DockerRegistrySuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C) {
   387  	pushDigest, err := setupImage(c)
   388  	if err != nil {
   389  		c.Fatalf("error setting up image: %v", err)
   390  	}
   391  
   392  	// pull from the registry using the <name>@<digest> reference
   393  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   394  	dockerCmd(c, "pull", imageReference)
   395  	// just in case...
   396  
   397  	imageID, err := inspectField(imageReference, "Id")
   398  	if err != nil {
   399  		c.Fatalf("error inspecting image id: %v", err)
   400  	}
   401  
   402  	dockerCmd(c, "rmi", imageID)
   403  }