github.com/carlanton/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 }