github.com/grubernaut/docker@v1.6.0-rc2/integration-cli/docker_cli_by_digest_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os/exec"
     6  	"regexp"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/docker/docker/utils"
    11  )
    12  
    13  var (
    14  	repoName    = fmt.Sprintf("%v/dockercli/busybox-by-dgst", privateRegistryURL)
    15  	digestRegex = regexp.MustCompile("Digest: ([^\n]+)")
    16  )
    17  
    18  func setupImage() (string, error) {
    19  	return setupImageWithTag("latest")
    20  }
    21  
    22  func setupImageWithTag(tag string) (string, error) {
    23  	containerName := "busyboxbydigest"
    24  
    25  	c := exec.Command(dockerBinary, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
    26  	if _, err := runCommand(c); err != nil {
    27  		return "", err
    28  	}
    29  
    30  	// tag the image to upload it to the private registry
    31  	repoAndTag := utils.ImageReference(repoName, tag)
    32  	c = exec.Command(dockerBinary, "commit", containerName, repoAndTag)
    33  	if out, _, err := runCommandWithOutput(c); err != nil {
    34  		return "", fmt.Errorf("image tagging failed: %s, %v", out, err)
    35  	}
    36  	defer deleteImages(repoAndTag)
    37  
    38  	// delete the container as we don't need it any more
    39  	if err := deleteContainer(containerName); err != nil {
    40  		return "", err
    41  	}
    42  
    43  	// push the image
    44  	c = exec.Command(dockerBinary, "push", repoAndTag)
    45  	out, _, err := runCommandWithOutput(c)
    46  	if err != nil {
    47  		return "", fmt.Errorf("pushing the image to the private registry has failed: %s, %v", out, err)
    48  	}
    49  
    50  	// delete our local repo that we previously tagged
    51  	c = exec.Command(dockerBinary, "rmi", repoAndTag)
    52  	if out, _, err := runCommandWithOutput(c); err != nil {
    53  		return "", fmt.Errorf("error deleting images prior to real test: %s, %v", out, err)
    54  	}
    55  
    56  	// the push output includes "Digest: <digest>", so find that
    57  	matches := digestRegex.FindStringSubmatch(out)
    58  	if len(matches) != 2 {
    59  		return "", fmt.Errorf("unable to parse digest from push output: %s", out)
    60  	}
    61  	pushDigest := matches[1]
    62  
    63  	return pushDigest, nil
    64  }
    65  
    66  func TestPullByTagDisplaysDigest(t *testing.T) {
    67  	defer setupRegistry(t)()
    68  
    69  	pushDigest, err := setupImage()
    70  	if err != nil {
    71  		t.Fatalf("error setting up image: %v", err)
    72  	}
    73  
    74  	// pull from the registry using the tag
    75  	c := exec.Command(dockerBinary, "pull", repoName)
    76  	out, _, err := runCommandWithOutput(c)
    77  	if err != nil {
    78  		t.Fatalf("error pulling by tag: %s, %v", out, err)
    79  	}
    80  	defer deleteImages(repoName)
    81  
    82  	// the pull output includes "Digest: <digest>", so find that
    83  	matches := digestRegex.FindStringSubmatch(out)
    84  	if len(matches) != 2 {
    85  		t.Fatalf("unable to parse digest from pull output: %s", out)
    86  	}
    87  	pullDigest := matches[1]
    88  
    89  	// make sure the pushed and pull digests match
    90  	if pushDigest != pullDigest {
    91  		t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
    92  	}
    93  
    94  	logDone("by_digest - pull by tag displays digest")
    95  }
    96  
    97  func TestPullByDigest(t *testing.T) {
    98  	defer setupRegistry(t)()
    99  
   100  	pushDigest, err := setupImage()
   101  	if err != nil {
   102  		t.Fatalf("error setting up image: %v", err)
   103  	}
   104  
   105  	// pull from the registry using the <name>@<digest> reference
   106  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   107  	c := exec.Command(dockerBinary, "pull", imageReference)
   108  	out, _, err := runCommandWithOutput(c)
   109  	if err != nil {
   110  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   111  	}
   112  	defer deleteImages(imageReference)
   113  
   114  	// the pull output includes "Digest: <digest>", so find that
   115  	matches := digestRegex.FindStringSubmatch(out)
   116  	if len(matches) != 2 {
   117  		t.Fatalf("unable to parse digest from pull output: %s", out)
   118  	}
   119  	pullDigest := matches[1]
   120  
   121  	// make sure the pushed and pull digests match
   122  	if pushDigest != pullDigest {
   123  		t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
   124  	}
   125  
   126  	logDone("by_digest - pull by digest")
   127  }
   128  
   129  func TestCreateByDigest(t *testing.T) {
   130  	defer setupRegistry(t)()
   131  
   132  	pushDigest, err := setupImage()
   133  	if err != nil {
   134  		t.Fatalf("error setting up image: %v", err)
   135  	}
   136  
   137  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   138  
   139  	containerName := "createByDigest"
   140  	c := exec.Command(dockerBinary, "create", "--name", containerName, imageReference)
   141  	out, _, err := runCommandWithOutput(c)
   142  	if err != nil {
   143  		t.Fatalf("error creating by digest: %s, %v", out, err)
   144  	}
   145  	defer deleteContainer(containerName)
   146  
   147  	res, err := inspectField(containerName, "Config.Image")
   148  	if err != nil {
   149  		t.Fatalf("failed to get Config.Image: %s, %v", out, err)
   150  	}
   151  	if res != imageReference {
   152  		t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
   153  	}
   154  
   155  	logDone("by_digest - create by digest")
   156  }
   157  
   158  func TestRunByDigest(t *testing.T) {
   159  	defer setupRegistry(t)()
   160  
   161  	pushDigest, err := setupImage()
   162  	if err != nil {
   163  		t.Fatalf("error setting up image: %v", err)
   164  	}
   165  
   166  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   167  
   168  	containerName := "runByDigest"
   169  	c := exec.Command(dockerBinary, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
   170  	out, _, err := runCommandWithOutput(c)
   171  	if err != nil {
   172  		t.Fatalf("error run by digest: %s, %v", out, err)
   173  	}
   174  	defer deleteContainer(containerName)
   175  
   176  	foundRegex := regexp.MustCompile("found=([^\n]+)")
   177  	matches := foundRegex.FindStringSubmatch(out)
   178  	if len(matches) != 2 {
   179  		t.Fatalf("error locating expected 'found=1' output: %s", out)
   180  	}
   181  	if matches[1] != "1" {
   182  		t.Fatalf("Expected %q, got %q", "1", matches[1])
   183  	}
   184  
   185  	res, err := inspectField(containerName, "Config.Image")
   186  	if err != nil {
   187  		t.Fatalf("failed to get Config.Image: %s, %v", out, err)
   188  	}
   189  	if res != imageReference {
   190  		t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
   191  	}
   192  
   193  	logDone("by_digest - run by digest")
   194  }
   195  
   196  func TestRemoveImageByDigest(t *testing.T) {
   197  	defer setupRegistry(t)()
   198  
   199  	digest, err := setupImage()
   200  	if err != nil {
   201  		t.Fatalf("error setting up image: %v", err)
   202  	}
   203  
   204  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   205  
   206  	// pull from the registry using the <name>@<digest> reference
   207  	c := exec.Command(dockerBinary, "pull", imageReference)
   208  	out, _, err := runCommandWithOutput(c)
   209  	if err != nil {
   210  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   211  	}
   212  
   213  	// make sure inspect runs ok
   214  	if _, err := inspectField(imageReference, "Id"); err != nil {
   215  		t.Fatalf("failed to inspect image: %v", err)
   216  	}
   217  
   218  	// do the delete
   219  	if err := deleteImages(imageReference); err != nil {
   220  		t.Fatalf("unexpected error deleting image: %v", err)
   221  	}
   222  
   223  	// try to inspect again - it should error this time
   224  	if _, err := inspectField(imageReference, "Id"); err == nil {
   225  		t.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
   226  	} else if !strings.Contains(err.Error(), "No such image") {
   227  		t.Fatalf("expected 'No such image' output, got %v", err)
   228  	}
   229  
   230  	logDone("by_digest - remove image by digest")
   231  }
   232  
   233  func TestBuildByDigest(t *testing.T) {
   234  	defer setupRegistry(t)()
   235  
   236  	digest, err := setupImage()
   237  	if err != nil {
   238  		t.Fatalf("error setting up image: %v", err)
   239  	}
   240  
   241  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   242  
   243  	// pull from the registry using the <name>@<digest> reference
   244  	c := exec.Command(dockerBinary, "pull", imageReference)
   245  	out, _, err := runCommandWithOutput(c)
   246  	if err != nil {
   247  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   248  	}
   249  
   250  	// get the image id
   251  	imageID, err := inspectField(imageReference, "Id")
   252  	if err != nil {
   253  		t.Fatalf("error getting image id: %v", err)
   254  	}
   255  
   256  	// do the build
   257  	name := "buildbydigest"
   258  	defer deleteImages(name)
   259  	_, err = buildImage(name, fmt.Sprintf(
   260  		`FROM %s
   261       CMD ["/bin/echo", "Hello World"]`, imageReference),
   262  		true)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	// get the build's image id
   268  	res, err := inspectField(name, "Config.Image")
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	// make sure they match
   273  	if res != imageID {
   274  		t.Fatalf("Image %s, expected %s", res, imageID)
   275  	}
   276  
   277  	logDone("by_digest - build by digest")
   278  }
   279  
   280  func TestTagByDigest(t *testing.T) {
   281  	defer setupRegistry(t)()
   282  
   283  	digest, err := setupImage()
   284  	if err != nil {
   285  		t.Fatalf("error setting up image: %v", err)
   286  	}
   287  
   288  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   289  
   290  	// pull from the registry using the <name>@<digest> reference
   291  	c := exec.Command(dockerBinary, "pull", imageReference)
   292  	out, _, err := runCommandWithOutput(c)
   293  	if err != nil {
   294  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   295  	}
   296  
   297  	// tag it
   298  	tag := "tagbydigest"
   299  	c = exec.Command(dockerBinary, "tag", imageReference, tag)
   300  	if _, err := runCommand(c); err != nil {
   301  		t.Fatalf("unexpected error tagging: %v", err)
   302  	}
   303  
   304  	expectedID, err := inspectField(imageReference, "Id")
   305  	if err != nil {
   306  		t.Fatalf("error getting original image id: %v", err)
   307  	}
   308  
   309  	tagID, err := inspectField(tag, "Id")
   310  	if err != nil {
   311  		t.Fatalf("error getting tagged image id: %v", err)
   312  	}
   313  
   314  	if tagID != expectedID {
   315  		t.Fatalf("expected image id %q, got %q", expectedID, tagID)
   316  	}
   317  
   318  	logDone("by_digest - tag by digest")
   319  }
   320  
   321  func TestListImagesWithoutDigests(t *testing.T) {
   322  	defer setupRegistry(t)()
   323  
   324  	digest, err := setupImage()
   325  	if err != nil {
   326  		t.Fatalf("error setting up image: %v", err)
   327  	}
   328  
   329  	imageReference := fmt.Sprintf("%s@%s", repoName, digest)
   330  
   331  	// pull from the registry using the <name>@<digest> reference
   332  	c := exec.Command(dockerBinary, "pull", imageReference)
   333  	out, _, err := runCommandWithOutput(c)
   334  	if err != nil {
   335  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   336  	}
   337  
   338  	c = exec.Command(dockerBinary, "images")
   339  	out, _, err = runCommandWithOutput(c)
   340  	if err != nil {
   341  		t.Fatalf("error listing images: %s, %v", out, err)
   342  	}
   343  
   344  	if strings.Contains(out, "DIGEST") {
   345  		t.Fatalf("list output should not have contained DIGEST header: %s", out)
   346  	}
   347  
   348  	logDone("by_digest - list images - digest header not displayed by default")
   349  }
   350  
   351  func TestListImagesWithDigests(t *testing.T) {
   352  	defer setupRegistry(t)()
   353  	defer deleteImages(repoName+":tag1", repoName+":tag2")
   354  
   355  	// setup image1
   356  	digest1, err := setupImageWithTag("tag1")
   357  	if err != nil {
   358  		t.Fatalf("error setting up image: %v", err)
   359  	}
   360  	imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
   361  	defer deleteImages(imageReference1)
   362  	t.Logf("imageReference1 = %s", imageReference1)
   363  
   364  	// pull image1 by digest
   365  	c := exec.Command(dockerBinary, "pull", imageReference1)
   366  	out, _, err := runCommandWithOutput(c)
   367  	if err != nil {
   368  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   369  	}
   370  
   371  	// list images
   372  	c = exec.Command(dockerBinary, "images", "--digests")
   373  	out, _, err = runCommandWithOutput(c)
   374  	if err != nil {
   375  		t.Fatalf("error listing images: %s, %v", out, err)
   376  	}
   377  
   378  	// make sure repo shown, tag=<none>, digest = $digest1
   379  	re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
   380  	if !re1.MatchString(out) {
   381  		t.Fatalf("expected %q: %s", re1.String(), out)
   382  	}
   383  
   384  	// setup image2
   385  	digest2, err := setupImageWithTag("tag2")
   386  	if err != nil {
   387  		t.Fatalf("error setting up image: %v", err)
   388  	}
   389  	imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
   390  	defer deleteImages(imageReference2)
   391  	t.Logf("imageReference2 = %s", imageReference2)
   392  
   393  	// pull image1 by digest
   394  	c = exec.Command(dockerBinary, "pull", imageReference1)
   395  	out, _, err = runCommandWithOutput(c)
   396  	if err != nil {
   397  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   398  	}
   399  
   400  	// pull image2 by digest
   401  	c = exec.Command(dockerBinary, "pull", imageReference2)
   402  	out, _, err = runCommandWithOutput(c)
   403  	if err != nil {
   404  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   405  	}
   406  
   407  	// list images
   408  	c = exec.Command(dockerBinary, "images", "--digests")
   409  	out, _, err = runCommandWithOutput(c)
   410  	if err != nil {
   411  		t.Fatalf("error listing images: %s, %v", out, err)
   412  	}
   413  
   414  	// make sure repo shown, tag=<none>, digest = $digest1
   415  	if !re1.MatchString(out) {
   416  		t.Fatalf("expected %q: %s", re1.String(), out)
   417  	}
   418  
   419  	// make sure repo shown, tag=<none>, digest = $digest2
   420  	re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
   421  	if !re2.MatchString(out) {
   422  		t.Fatalf("expected %q: %s", re2.String(), out)
   423  	}
   424  
   425  	// pull tag1
   426  	c = exec.Command(dockerBinary, "pull", repoName+":tag1")
   427  	out, _, err = runCommandWithOutput(c)
   428  	if err != nil {
   429  		t.Fatalf("error pulling tag1: %s, %v", out, err)
   430  	}
   431  
   432  	// list images
   433  	c = exec.Command(dockerBinary, "images", "--digests")
   434  	out, _, err = runCommandWithOutput(c)
   435  	if err != nil {
   436  		t.Fatalf("error listing images: %s, %v", out, err)
   437  	}
   438  
   439  	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
   440  	reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
   441  	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
   442  	if !reWithTag1.MatchString(out) {
   443  		t.Fatalf("expected %q: %s", reWithTag1.String(), out)
   444  	}
   445  	if !reWithDigest1.MatchString(out) {
   446  		t.Fatalf("expected %q: %s", reWithDigest1.String(), out)
   447  	}
   448  	// make sure image 2 has repo, <none>, digest
   449  	if !re2.MatchString(out) {
   450  		t.Fatalf("expected %q: %s", re2.String(), out)
   451  	}
   452  
   453  	// pull tag 2
   454  	c = exec.Command(dockerBinary, "pull", repoName+":tag2")
   455  	out, _, err = runCommandWithOutput(c)
   456  	if err != nil {
   457  		t.Fatalf("error pulling tag2: %s, %v", out, err)
   458  	}
   459  
   460  	// list images
   461  	c = exec.Command(dockerBinary, "images", "--digests")
   462  	out, _, err = runCommandWithOutput(c)
   463  	if err != nil {
   464  		t.Fatalf("error listing images: %s, %v", out, err)
   465  	}
   466  
   467  	// make sure image 1 has repo, tag, digest
   468  	if !reWithTag1.MatchString(out) {
   469  		t.Fatalf("expected %q: %s", re1.String(), out)
   470  	}
   471  
   472  	// make sure image 2 has repo, tag, digest
   473  	reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
   474  	reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
   475  	if !reWithTag2.MatchString(out) {
   476  		t.Fatalf("expected %q: %s", reWithTag2.String(), out)
   477  	}
   478  	if !reWithDigest2.MatchString(out) {
   479  		t.Fatalf("expected %q: %s", reWithDigest2.String(), out)
   480  	}
   481  
   482  	// list images
   483  	c = exec.Command(dockerBinary, "images", "--digests")
   484  	out, _, err = runCommandWithOutput(c)
   485  	if err != nil {
   486  		t.Fatalf("error listing images: %s, %v", out, err)
   487  	}
   488  
   489  	// make sure image 1 has repo, tag, digest
   490  	if !reWithTag1.MatchString(out) {
   491  		t.Fatalf("expected %q: %s", re1.String(), out)
   492  	}
   493  	// make sure image 2 has repo, tag, digest
   494  	if !reWithTag2.MatchString(out) {
   495  		t.Fatalf("expected %q: %s", re2.String(), out)
   496  	}
   497  	// make sure busybox has tag, but not digest
   498  	busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
   499  	if !busyboxRe.MatchString(out) {
   500  		t.Fatalf("expected %q: %s", busyboxRe.String(), out)
   501  	}
   502  
   503  	logDone("by_digest - list images with digests")
   504  }
   505  
   506  func TestDeleteImageByIDOnlyPulledByDigest(t *testing.T) {
   507  	defer setupRegistry(t)()
   508  
   509  	pushDigest, err := setupImage()
   510  	if err != nil {
   511  		t.Fatalf("error setting up image: %v", err)
   512  	}
   513  
   514  	// pull from the registry using the <name>@<digest> reference
   515  	imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
   516  	c := exec.Command(dockerBinary, "pull", imageReference)
   517  	out, _, err := runCommandWithOutput(c)
   518  	if err != nil {
   519  		t.Fatalf("error pulling by digest: %s, %v", out, err)
   520  	}
   521  	// just in case...
   522  	defer deleteImages(imageReference)
   523  
   524  	imageID, err := inspectField(imageReference, ".Id")
   525  	if err != nil {
   526  		t.Fatalf("error inspecting image id: %v", err)
   527  	}
   528  
   529  	c = exec.Command(dockerBinary, "rmi", imageID)
   530  	if _, err := runCommand(c); err != nil {
   531  		t.Fatalf("error deleting image by id: %v", err)
   532  	}
   533  
   534  	logDone("by_digest - delete image by id only pulled by digest")
   535  }