14 "github.com/docker/distribution/reference"
15 "github.com/docker/docker/cli/config"
16 "github.com/docker/docker/integration-cli/checker"
17 "github.com/docker/docker/integration-cli/cli"
18 "github.com/docker/docker/integration-cli/cli/build"
19 icmd "github.com/docker/docker/pkg/testutil/cmd"
20 "github.com/go-check/check"
23 // Pushing an image to a private registry.
24 func testPushBusyboxImage(c *check.C) {
25 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
26 // tag the image to upload it to the private registry
27 dockerCmd(c, "tag", "busybox", repoName)
28 // push the image to the registry
29 dockerCmd(c, "push", repoName)
32 func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) {
33 testPushBusyboxImage(c)
36 func (s *DockerSchema1RegistrySuite) TestPushBusyboxImage(c *check.C) {
37 testPushBusyboxImage(c)
40 // pushing an image without a prefix should throw an error
41 func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
42 out, _, err := dockerCmdWithError("push", "busybox")
43 c.Assert(err, check.NotNil, check.Commentf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out))
46 func testPushUntagged(c *check.C) {
47 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
48 expected := "An image does not exist locally with the tag"
50 out, _, err := dockerCmdWithError("push", repoName)
51 c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
52 c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
55 func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) {
59 func (s *DockerSchema1RegistrySuite) TestPushUntagged(c *check.C) {
63 func testPushBadTag(c *check.C) {
64 repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
65 expected := "does not exist"
67 out, _, err := dockerCmdWithError("push", repoName)
68 c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
69 c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
72 func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) {
76 func (s *DockerSchema1RegistrySuite) TestPushBadTag(c *check.C) {
80 func testPushMultipleTags(c *check.C) {
81 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
82 repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
83 repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL)
84 // tag the image and upload it to the private registry
85 dockerCmd(c, "tag", "busybox", repoTag1)
87 dockerCmd(c, "tag", "busybox", repoTag2)
89 dockerCmd(c, "push", repoName)
91 // Ensure layer list is equivalent for repoTag1 and repoTag2
92 out1, _ := dockerCmd(c, "pull", repoTag1)
94 imageAlreadyExists := ": Image already exists"
95 var out1Lines []string
96 for _, outputLine := range strings.Split(out1, "\n") {
97 if strings.Contains(outputLine, imageAlreadyExists) {
98 out1Lines = append(out1Lines, outputLine)
102 out2, _ := dockerCmd(c, "pull", repoTag2)
104 var out2Lines []string
105 for _, outputLine := range strings.Split(out2, "\n") {
106 if strings.Contains(outputLine, imageAlreadyExists) {
107 out1Lines = append(out1Lines, outputLine)
110 c.Assert(out2Lines, checker.HasLen, len(out1Lines))
112 for i := range out1Lines {
113 c.Assert(out1Lines[i], checker.Equals, out2Lines[i])
117 func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) {
118 testPushMultipleTags(c)
121 func (s *DockerSchema1RegistrySuite) TestPushMultipleTags(c *check.C) {
122 testPushMultipleTags(c)
125 func testPushEmptyLayer(c *check.C) {
126 repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
127 emptyTarball, err := ioutil.TempFile("", "empty_tarball")
128 c.Assert(err, check.IsNil, check.Commentf("Unable to create test file"))
130 tw := tar.NewWriter(emptyTarball)
132 c.Assert(err, check.IsNil, check.Commentf("Error creating empty tarball"))
134 freader, err := os.Open(emptyTarball.Name())
135 c.Assert(err, check.IsNil, check.Commentf("Could not open test tarball"))
136 defer freader.Close()
138 icmd.RunCmd(icmd.Cmd{
139 Command: []string{dockerBinary, "import", "-", repoName},
141 }).Assert(c, icmd.Success)
143 // Now verify we can push it
144 out, _, err := dockerCmdWithError("push", repoName)
145 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out))
148 func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
149 testPushEmptyLayer(c)
152 func (s *DockerSchema1RegistrySuite) TestPushEmptyLayer(c *check.C) {
153 testPushEmptyLayer(c)
156 // testConcurrentPush pushes multiple tags to the same repo
158 func testConcurrentPush(c *check.C) {
159 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
162 for _, tag := range []string{"push1", "push2", "push3"} {
163 repo := fmt.Sprintf("%v:%v", repoName, tag)
164 buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
166 ENTRYPOINT ["/bin/echo"]
171 repos = append(repos, repo)
174 // Push tags, in parallel
175 results := make(chan error)
177 for _, repo := range repos {
178 go func(repo string) {
179 result := icmd.RunCommand(dockerBinary, "push", repo)
180 results <- result.Error
186 c.Assert(err, checker.IsNil, check.Commentf("concurrent push failed with error: %v", err))
189 // Clear local images store.
190 args := append([]string{"rmi"}, repos...)
191 dockerCmd(c, args...)
193 // Re-pull and run individual tags, to make sure pushes succeeded
194 for _, repo := range repos {
195 dockerCmd(c, "pull", repo)
196 dockerCmd(c, "inspect", repo)
197 out, _ := dockerCmd(c, "run", "--rm", repo)
198 c.Assert(strings.TrimSpace(out), checker.Equals, "/bin/sh -c echo "+repo)
202 func (s *DockerRegistrySuite) TestConcurrentPush(c *check.C) {
203 testConcurrentPush(c)
206 func (s *DockerSchema1RegistrySuite) TestConcurrentPush(c *check.C) {
207 testConcurrentPush(c)
210 func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) {
211 sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
212 // tag the image to upload it to the private registry
213 dockerCmd(c, "tag", "busybox", sourceRepoName)
214 // push the image to the registry
215 out1, _, err := dockerCmdWithError("push", sourceRepoName)
216 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out1))
217 // ensure that none of the layers were mounted from another repository during push
218 c.Assert(strings.Contains(out1, "Mounted from"), check.Equals, false)
220 digest1 := reference.DigestRegexp.FindString(out1)
221 c.Assert(len(digest1), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
223 destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL)
224 // retag the image to upload the same layers to another repo in the same registry
225 dockerCmd(c, "tag", "busybox", destRepoName)
226 // push the image to the registry
227 out2, _, err := dockerCmdWithError("push", destRepoName)
228 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2))
229 // ensure that layers were mounted from the first repo during push
230 c.Assert(strings.Contains(out2, "Mounted from dockercli/busybox"), check.Equals, true)
232 digest2 := reference.DigestRegexp.FindString(out2)
233 c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
234 c.Assert(digest1, check.Equals, digest2)
236 // ensure that pushing again produces the same digest
237 out3, _, err := dockerCmdWithError("push", destRepoName)
238 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2))
240 digest3 := reference.DigestRegexp.FindString(out3)
241 c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
242 c.Assert(digest3, check.Equals, digest2)
244 // ensure that we can pull and run the cross-repo-pushed repository
245 dockerCmd(c, "rmi", destRepoName)
246 dockerCmd(c, "pull", destRepoName)
247 out4, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world")
248 c.Assert(out4, check.Equals, "hello world")
251 func (s *DockerSchema1RegistrySuite) TestCrossRepositoryLayerPushNotSupported(c *check.C) {
252 sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
253 // tag the image to upload it to the private registry
254 dockerCmd(c, "tag", "busybox", sourceRepoName)
255 // push the image to the registry
256 out1, _, err := dockerCmdWithError("push", sourceRepoName)
257 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out1))
258 // ensure that none of the layers were mounted from another repository during push
259 c.Assert(strings.Contains(out1, "Mounted from"), check.Equals, false)
261 digest1 := reference.DigestRegexp.FindString(out1)
262 c.Assert(len(digest1), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
264 destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL)
265 // retag the image to upload the same layers to another repo in the same registry
266 dockerCmd(c, "tag", "busybox", destRepoName)
267 // push the image to the registry
268 out2, _, err := dockerCmdWithError("push", destRepoName)
269 c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2))
270 // schema1 registry should not support cross-repo layer mounts, so ensure that this does not happen
271 c.Assert(strings.Contains(out2, "Mounted from"), check.Equals, false)
273 digest2 := reference.DigestRegexp.FindString(out2)
274 c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
275 c.Assert(digest1, check.Not(check.Equals), digest2)
277 // ensure that we can pull and run the second pushed repository
278 dockerCmd(c, "rmi", destRepoName)
279 dockerCmd(c, "pull", destRepoName)
280 out3, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world")
281 c.Assert(out3, check.Equals, "hello world")
284 func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
285 repoName := fmt.Sprintf("%v/dockerclitrusted/pushtest:latest", privateRegistryURL)
286 // tag the image and upload it to the private registry
287 cli.DockerCmd(c, "tag", "busybox", repoName)
289 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
291 // Try pull after push
292 cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{
293 Out: "Status: Image is up to date",
296 // Assert that we rotated the snapshot key to the server by checking our local keystore
297 contents, err := ioutil.ReadDir(filepath.Join(config.Dir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest"))
298 c.Assert(err, check.IsNil, check.Commentf("Unable to read local tuf key files"))
299 // Check that we only have 1 key (targets key)
300 c.Assert(contents, checker.HasLen, 1)
303 func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
304 repoName := fmt.Sprintf("%v/dockerclienv/trusted:latest", privateRegistryURL)
305 // tag the image and upload it to the private registry
306 cli.DockerCmd(c, "tag", "busybox", repoName)
308 cli.Docker(cli.Args("push", repoName), trustedCmdWithPassphrases("12345678", "12345678")).Assert(c, SuccessSigningAndPushing)
310 // Try pull after push
311 cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{
312 Out: "Status: Image is up to date",
316 func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) {
317 repoName := fmt.Sprintf("%v/dockerclitrusted/failingserver:latest", privateRegistryURL)
318 // tag the image and upload it to the private registry
319 cli.DockerCmd(c, "tag", "busybox", repoName)
321 // Using a name that doesn't resolve to an address makes this test faster
322 cli.Docker(cli.Args("push", repoName), trustedCmdWithServer("https://server.invalid:81/")).Assert(c, icmd.Expected{
324 Err: "error contacting notary server",
328 func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
329 repoName := fmt.Sprintf("%v/dockerclitrusted/trustedandnot:latest", privateRegistryURL)
330 // tag the image and upload it to the private registry
331 cli.DockerCmd(c, "tag", "busybox", repoName)
333 result := cli.Docker(cli.Args("push", "--disable-content-trust", repoName), trustedCmdWithServer("https://server.invalid:81/"))
334 result.Assert(c, icmd.Success)
335 c.Assert(result.Combined(), check.Not(checker.Contains), "Error establishing connection to notary repository", check.Commentf("Missing expected output on trusted push with --disable-content-trust:"))
338 func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
339 repoName := fmt.Sprintf("%v/dockerclitag/trusted:latest", privateRegistryURL)
340 // tag the image and upload it to the private registry
341 cli.DockerCmd(c, "tag", "busybox", repoName)
342 cli.DockerCmd(c, "push", repoName)
344 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
346 // Try pull after push
347 cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{
348 Out: "Status: Image is up to date",
352 func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
353 repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
354 // tag the image and upload it to the private registry
355 cli.DockerCmd(c, "tag", "busybox", repoName)
358 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
360 // Do another trusted push
361 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
362 cli.DockerCmd(c, "rmi", repoName)
364 // Try pull to ensure the double push did not break our ability to pull
365 cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessDownloaded)
368 func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
369 repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
370 // tag the image and upload it to the private registry
371 cli.DockerCmd(c, "tag", "busybox", repoName)
373 // Push with default passphrases
374 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
376 // Push with wrong passphrases
377 cli.Docker(cli.Args("push", repoName), trustedCmdWithPassphrases("12345678", "87654321")).Assert(c, icmd.Expected{
379 Err: "could not find necessary signing keys",
383 func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) {
384 testRequires(c, NotaryHosting)
385 repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL)
386 targetName := fmt.Sprintf("%s:latest", repoName)
387 s.notaryInitRepo(c, repoName)
388 s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public)
389 s.notaryPublish(c, repoName)
391 s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private)
393 // tag the image and upload it to the private registry
394 cli.DockerCmd(c, "tag", "busybox", targetName)
396 cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing)
397 // check to make sure that the target has been added to targets/releases and not targets
398 s.assertTargetInRoles(c, repoName, "latest", "targets/releases")
399 s.assertTargetNotInRoles(c, repoName, "latest", "targets")
401 // Try pull after push
402 os.RemoveAll(filepath.Join(config.Dir(), "trust"))
404 cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{
405 Out: "Status: Image is up to date",
409 func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) {
410 testRequires(c, NotaryHosting)
411 repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL)
412 targetName := fmt.Sprintf("%s:latest", repoName)
413 s.notaryInitRepo(c, repoName)
414 s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public)
415 s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public)
416 s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public)
418 // import everything except the third key
419 s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private)
420 s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private)
422 s.notaryCreateDelegation(c, repoName, "targets/role1/subrole", s.not.keys[3].Public)
423 s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private)
425 s.notaryPublish(c, repoName)
427 // tag the image and upload it to the private registry
428 cli.DockerCmd(c, "tag", "busybox", targetName)
430 cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing)
432 // check to make sure that the target has been added to targets/role1 and targets/role2, and
433 // not targets (because there are delegations) or targets/role3 (due to missing key) or
434 // targets/role1/subrole (due to it being a second level delegation)
435 s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role2")
436 s.assertTargetNotInRoles(c, repoName, "latest", "targets")
438 // Try pull after push
439 os.RemoveAll(filepath.Join(config.Dir(), "trust"))
441 // pull should fail because none of these are the releases role
442 cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{
447 func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *check.C) {
448 repoName := fmt.Sprintf("%v/dockerclirolesbykeysandpaths/trusted", privateRegistryURL)
449 targetName := fmt.Sprintf("%s:latest", repoName)
450 s.notaryInitRepo(c, repoName)
451 s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public, "l", "z")
452 s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public, "x", "y")
453 s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public, "latest")
454 s.notaryCreateDelegation(c, repoName, "targets/role4", s.not.keys[3].Public, "latest")
456 // import everything except the third key
457 s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private)
458 s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private)
459 s.notaryImportKey(c, repoName, "targets/role4", s.not.keys[3].Private)
461 s.notaryPublish(c, repoName)
463 // tag the image and upload it to the private registry
464 cli.DockerCmd(c, "tag", "busybox", targetName)
466 cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing)
468 // check to make sure that the target has been added to targets/role1 and targets/role4, and
469 // not targets (because there are delegations) or targets/role2 (due to path restrictions) or
470 // targets/role3 (due to missing key)
471 s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role4")
472 s.assertTargetNotInRoles(c, repoName, "latest", "targets")
474 // Try pull after push
475 os.RemoveAll(filepath.Join(config.Dir(), "trust"))
477 // pull should fail because none of these are the releases role
478 cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{
483 func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c *check.C) {
484 testRequires(c, NotaryHosting)
485 repoName := fmt.Sprintf("%v/dockerclireleasedelegationnotsignable/trusted", privateRegistryURL)
486 targetName := fmt.Sprintf("%s:latest", repoName)
487 s.notaryInitRepo(c, repoName)
488 s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public)
489 s.notaryPublish(c, repoName)
491 // do not import any delegations key
493 // tag the image and upload it to the private registry
494 cli.DockerCmd(c, "tag", "busybox", targetName)
496 cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Expected{
498 Err: "no valid signing keys",
500 s.assertTargetNotInRoles(c, repoName, "latest", "targets", "targets/role1")
503 func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) {
504 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
505 dockerCmd(c, "tag", "busybox", repoName)
506 out, _, err := dockerCmdWithError("push", repoName)
507 c.Assert(err, check.NotNil, check.Commentf(out))
508 c.Assert(out, check.Not(checker.Contains), "Retrying")
509 c.Assert(out, checker.Contains, "no basic auth credentials")
512 // This may be flaky but it's needed not to regress on unauthorized push, see #21054
513 func (s *DockerSuite) TestPushToCentralRegistryUnauthorized(c *check.C) {
514 testRequires(c, Network)
515 repoName := "test/busybox"
516 dockerCmd(c, "tag", "busybox", repoName)
517 out, _, err := dockerCmdWithError("push", repoName)
518 c.Assert(err, check.NotNil, check.Commentf(out))
519 c.Assert(out, check.Not(checker.Contains), "Retrying")
522 func getTestTokenService(status int, body string, retries int) *httptest.Server {
524 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
527 w.WriteHeader(http.StatusServiceUnavailable)
528 w.Header().Set("Content-Type", "application/json")
529 w.Write([]byte(`{"errors":[{"code":"UNAVAILABLE","message":"cannot create token at this time"}]}`))
532 w.WriteHeader(status)
533 w.Header().Set("Content-Type", "application/json")
534 w.Write([]byte(body))
540 func (s *DockerRegistryAuthTokenSuite) TestPushTokenServiceUnauthResponse(c *check.C) {
541 ts := getTestTokenService(http.StatusUnauthorized, `{"errors": [{"Code":"UNAUTHORIZED", "message": "a message", "detail": null}]}`, 0)
543 s.setupRegistryWithTokenService(c, ts.URL)
544 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
545 dockerCmd(c, "tag", "busybox", repoName)
546 out, _, err := dockerCmdWithError("push", repoName)
547 c.Assert(err, check.NotNil, check.Commentf(out))
548 c.Assert(out, checker.Not(checker.Contains), "Retrying")
549 c.Assert(out, checker.Contains, "unauthorized: a message")
552 func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponseUnauthorized(c *check.C) {
553 ts := getTestTokenService(http.StatusUnauthorized, `{"error": "unauthorized"}`, 0)
555 s.setupRegistryWithTokenService(c, ts.URL)
556 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
557 dockerCmd(c, "tag", "busybox", repoName)
558 out, _, err := dockerCmdWithError("push", repoName)
559 c.Assert(err, check.NotNil, check.Commentf(out))
560 c.Assert(out, checker.Not(checker.Contains), "Retrying")
561 split := strings.Split(out, "\n")
562 c.Assert(split[len(split)-2], check.Equals, "unauthorized: authentication required")
565 func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponseError(c *check.C) {
566 ts := getTestTokenService(http.StatusTooManyRequests, `{"errors": [{"code":"TOOMANYREQUESTS","message":"out of tokens"}]}`, 3)
568 s.setupRegistryWithTokenService(c, ts.URL)
569 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
570 dockerCmd(c, "tag", "busybox", repoName)
571 out, _, err := dockerCmdWithError("push", repoName)
572 c.Assert(err, check.NotNil, check.Commentf(out))
573 // TODO: isolate test so that it can be guaranteed that the 503 will trigger xfer retries
574 //c.Assert(out, checker.Contains, "Retrying")
575 //c.Assert(out, checker.Not(checker.Contains), "Retrying in 15")
576 split := strings.Split(out, "\n")
577 c.Assert(split[len(split)-2], check.Equals, "toomanyrequests: out of tokens")
580 func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponseUnparsable(c *check.C) {
581 ts := getTestTokenService(http.StatusForbidden, `no way`, 0)
583 s.setupRegistryWithTokenService(c, ts.URL)
584 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
585 dockerCmd(c, "tag", "busybox", repoName)
586 out, _, err := dockerCmdWithError("push", repoName)
587 c.Assert(err, check.NotNil, check.Commentf(out))
588 c.Assert(out, checker.Not(checker.Contains), "Retrying")
589 split := strings.Split(out, "\n")
590 c.Assert(split[len(split)-2], checker.Contains, "error parsing HTTP 403 response body: ")
593 func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponseNoToken(c *check.C) {
594 ts := getTestTokenService(http.StatusOK, `{"something": "wrong"}`, 0)
596 s.setupRegistryWithTokenService(c, ts.URL)
597 repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
598 dockerCmd(c, "tag", "busybox", repoName)
599 out, _, err := dockerCmdWithError("push", repoName)
600 c.Assert(err, check.NotNil, check.Commentf(out))
601 c.Assert(out, checker.Not(checker.Contains), "Retrying")
602 split := strings.Split(out, "\n")
603 c.Assert(split[len(split)-2], check.Equals, "authorization server did not include a token in the response")