github.com/akashshinde/docker@v1.9.1/integration-cli/docker_cli_push_test.go (about) 1 package main 2 3 import ( 4 "archive/tar" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 "time" 13 14 "github.com/docker/docker/image" 15 "github.com/go-check/check" 16 ) 17 18 // Pushing an image to a private registry. 19 func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) { 20 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 21 // tag the image to upload it to the private registry 22 dockerCmd(c, "tag", "busybox", repoName) 23 // push the image to the registry 24 dockerCmd(c, "push", repoName) 25 } 26 27 // pushing an image without a prefix should throw an error 28 func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) { 29 if out, _, err := dockerCmdWithError("push", "busybox"); err == nil { 30 c.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out) 31 } 32 } 33 34 func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) { 35 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 36 37 expected := "Repository does not exist" 38 if out, _, err := dockerCmdWithError("push", repoName); err == nil { 39 c.Fatalf("pushing the image to the private registry should have failed: output %q", out) 40 } else if !strings.Contains(out, expected) { 41 c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out) 42 } 43 } 44 45 func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) { 46 repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL) 47 48 expected := "does not exist" 49 50 if out, _, err := dockerCmdWithError("push", repoName); err == nil { 51 c.Fatalf("pushing the image to the private registry should have failed: output %q", out) 52 } else if !strings.Contains(out, expected) { 53 c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out) 54 } 55 } 56 57 func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) { 58 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 59 repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL) 60 repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL) 61 // tag the image and upload it to the private registry 62 dockerCmd(c, "tag", "busybox", repoTag1) 63 64 dockerCmd(c, "tag", "busybox", repoTag2) 65 66 dockerCmd(c, "push", repoName) 67 68 // Ensure layer list is equivalent for repoTag1 and repoTag2 69 out1, _ := dockerCmd(c, "pull", repoTag1) 70 if strings.Contains(out1, "Tag t1 not found") { 71 c.Fatalf("Unable to pull pushed image: %s", out1) 72 } 73 imageAlreadyExists := ": Image already exists" 74 var out1Lines []string 75 for _, outputLine := range strings.Split(out1, "\n") { 76 if strings.Contains(outputLine, imageAlreadyExists) { 77 out1Lines = append(out1Lines, outputLine) 78 } 79 } 80 81 out2, _ := dockerCmd(c, "pull", repoTag2) 82 if strings.Contains(out2, "Tag t2 not found") { 83 c.Fatalf("Unable to pull pushed image: %s", out1) 84 } 85 var out2Lines []string 86 for _, outputLine := range strings.Split(out2, "\n") { 87 if strings.Contains(outputLine, imageAlreadyExists) { 88 out1Lines = append(out1Lines, outputLine) 89 } 90 } 91 92 if len(out1Lines) != len(out2Lines) { 93 c.Fatalf("Mismatched output length:\n%s\n%s", out1, out2) 94 } 95 96 for i := range out1Lines { 97 if out1Lines[i] != out2Lines[i] { 98 c.Fatalf("Mismatched output line:\n%s\n%s", out1Lines[i], out2Lines[i]) 99 } 100 } 101 } 102 103 // TestPushBadParentChain tries to push an image with a corrupted parent chain 104 // in the v1compatibility files, and makes sure the push process fixes it. 105 func (s *DockerRegistrySuite) TestPushBadParentChain(c *check.C) { 106 repoName := fmt.Sprintf("%v/dockercli/badparent", privateRegistryURL) 107 108 id, err := buildImage(repoName, ` 109 FROM busybox 110 CMD echo "adding another layer" 111 `, true) 112 if err != nil { 113 c.Fatal(err) 114 } 115 116 // Push to create v1compatibility file 117 dockerCmd(c, "push", repoName) 118 119 // Corrupt the parent in the v1compatibility file from the top layer 120 filename := filepath.Join(dockerBasePath, "graph", id, "v1Compatibility") 121 122 jsonBytes, err := ioutil.ReadFile(filename) 123 c.Assert(err, check.IsNil, check.Commentf("Could not read v1Compatibility file: %s", err)) 124 125 var img image.Image 126 err = json.Unmarshal(jsonBytes, &img) 127 c.Assert(err, check.IsNil, check.Commentf("Could not unmarshal json: %s", err)) 128 129 img.Parent = "1234123412341234123412341234123412341234123412341234123412341234" 130 131 jsonBytes, err = json.Marshal(&img) 132 c.Assert(err, check.IsNil, check.Commentf("Could not marshal json: %s", err)) 133 134 err = ioutil.WriteFile(filename, jsonBytes, 0600) 135 c.Assert(err, check.IsNil, check.Commentf("Could not write v1Compatibility file: %s", err)) 136 137 dockerCmd(c, "push", repoName) 138 139 // pull should succeed 140 dockerCmd(c, "pull", repoName) 141 } 142 143 func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) { 144 repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL) 145 emptyTarball, err := ioutil.TempFile("", "empty_tarball") 146 if err != nil { 147 c.Fatalf("Unable to create test file: %v", err) 148 } 149 tw := tar.NewWriter(emptyTarball) 150 err = tw.Close() 151 if err != nil { 152 c.Fatalf("Error creating empty tarball: %v", err) 153 } 154 freader, err := os.Open(emptyTarball.Name()) 155 if err != nil { 156 c.Fatalf("Could not open test tarball: %v", err) 157 } 158 159 importCmd := exec.Command(dockerBinary, "import", "-", repoName) 160 importCmd.Stdin = freader 161 out, _, err := runCommandWithOutput(importCmd) 162 if err != nil { 163 c.Errorf("import failed with errors: %v, output: %q", err, out) 164 } 165 166 // Now verify we can push it 167 if out, _, err := dockerCmdWithError("push", repoName); err != nil { 168 c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err) 169 } 170 } 171 172 func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { 173 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 174 // tag the image and upload it to the private registry 175 dockerCmd(c, "tag", "busybox", repoName) 176 177 pushCmd := exec.Command(dockerBinary, "push", repoName) 178 s.trustedCmd(pushCmd) 179 out, _, err := runCommandWithOutput(pushCmd) 180 if err != nil { 181 c.Fatalf("Error running trusted push: %s\n%s", err, out) 182 } 183 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 184 c.Fatalf("Missing expected output on trusted push:\n%s", out) 185 } 186 } 187 188 func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) { 189 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 190 // tag the image and upload it to the private registry 191 dockerCmd(c, "tag", "busybox", repoName) 192 193 pushCmd := exec.Command(dockerBinary, "push", repoName) 194 s.trustedCmdWithPassphrases(pushCmd, "12345678", "12345678") 195 out, _, err := runCommandWithOutput(pushCmd) 196 if err != nil { 197 c.Fatalf("Error running trusted push: %s\n%s", err, out) 198 } 199 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 200 c.Fatalf("Missing expected output on trusted push:\n%s", out) 201 } 202 } 203 204 // This test ensures backwards compatibility with old ENV variables. Should be 205 // deprecated by 1.10 206 func (s *DockerTrustSuite) TestTrustedPushWithDeprecatedEnvPasswords(c *check.C) { 207 repoName := fmt.Sprintf("%v/dockercli/trusteddeprecated:latest", privateRegistryURL) 208 // tag the image and upload it to the private registry 209 dockerCmd(c, "tag", "busybox", repoName) 210 211 pushCmd := exec.Command(dockerBinary, "push", repoName) 212 s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "12345678") 213 out, _, err := runCommandWithOutput(pushCmd) 214 if err != nil { 215 c.Fatalf("Error running trusted push: %s\n%s", err, out) 216 } 217 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 218 c.Fatalf("Missing expected output on trusted push:\n%s", out) 219 } 220 } 221 222 func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) { 223 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 224 // tag the image and upload it to the private registry 225 dockerCmd(c, "tag", "busybox", repoName) 226 227 pushCmd := exec.Command(dockerBinary, "push", repoName) 228 s.trustedCmdWithServer(pushCmd, "https://example.com:81/") 229 out, _, err := runCommandWithOutput(pushCmd) 230 if err == nil { 231 c.Fatalf("Missing error while running trusted push w/ no server") 232 } 233 234 if !strings.Contains(string(out), "error contacting notary server") { 235 c.Fatalf("Missing expected output on trusted push:\n%s", out) 236 } 237 } 238 239 func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) { 240 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 241 // tag the image and upload it to the private registry 242 dockerCmd(c, "tag", "busybox", repoName) 243 244 pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName) 245 s.trustedCmdWithServer(pushCmd, "https://example.com/") 246 out, _, err := runCommandWithOutput(pushCmd) 247 if err != nil { 248 c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out) 249 } 250 251 if strings.Contains(string(out), "Error establishing connection to notary repository") { 252 c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out) 253 } 254 } 255 256 func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) { 257 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 258 // tag the image and upload it to the private registry 259 dockerCmd(c, "tag", "busybox", repoName) 260 dockerCmd(c, "push", repoName) 261 262 pushCmd := exec.Command(dockerBinary, "push", repoName) 263 s.trustedCmd(pushCmd) 264 out, _, err := runCommandWithOutput(pushCmd) 265 if err != nil { 266 c.Fatalf("trusted push failed: %s\n%s", err, out) 267 } 268 269 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 270 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 271 } 272 } 273 274 func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) { 275 repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL) 276 // tag the image and upload it to the private registry 277 dockerCmd(c, "tag", "busybox", repoName) 278 279 // Do a trusted push 280 pushCmd := exec.Command(dockerBinary, "push", repoName) 281 s.trustedCmd(pushCmd) 282 out, _, err := runCommandWithOutput(pushCmd) 283 if err != nil { 284 c.Fatalf("trusted push failed: %s\n%s", err, out) 285 } 286 287 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 288 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 289 } 290 291 // Do another trusted push 292 pushCmd = exec.Command(dockerBinary, "push", repoName) 293 s.trustedCmd(pushCmd) 294 out, _, err = runCommandWithOutput(pushCmd) 295 if err != nil { 296 c.Fatalf("trusted push failed: %s\n%s", err, out) 297 } 298 299 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 300 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 301 } 302 303 dockerCmd(c, "rmi", repoName) 304 305 // Try pull to ensure the double push did not break our ability to pull 306 pullCmd := exec.Command(dockerBinary, "pull", repoName) 307 s.trustedCmd(pullCmd) 308 out, _, err = runCommandWithOutput(pullCmd) 309 if err != nil { 310 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 311 } 312 313 if !strings.Contains(string(out), "Status: Downloaded") { 314 c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out) 315 } 316 } 317 318 func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) { 319 repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL) 320 // tag the image and upload it to the private registry 321 dockerCmd(c, "tag", "busybox", repoName) 322 323 // Push with default passphrases 324 pushCmd := exec.Command(dockerBinary, "push", repoName) 325 s.trustedCmd(pushCmd) 326 out, _, err := runCommandWithOutput(pushCmd) 327 if err != nil { 328 c.Fatalf("trusted push failed: %s\n%s", err, out) 329 } 330 331 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 332 c.Fatalf("Missing expected output on trusted push:\n%s", out) 333 } 334 335 // Push with wrong passphrases 336 pushCmd = exec.Command(dockerBinary, "push", repoName) 337 s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321") 338 out, _, err = runCommandWithOutput(pushCmd) 339 if err == nil { 340 c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out) 341 } 342 343 if !strings.Contains(string(out), "password invalid, operation has failed") { 344 c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out) 345 } 346 } 347 348 // This test ensures backwards compatibility with old ENV variables. Should be 349 // deprecated by 1.10 350 func (s *DockerTrustSuite) TestTrustedPushWithIncorrectDeprecatedPassphraseForNonRoot(c *check.C) { 351 repoName := fmt.Sprintf("%v/dockercliincorretdeprecatedpwd/trusted:latest", privateRegistryURL) 352 // tag the image and upload it to the private registry 353 dockerCmd(c, "tag", "busybox", repoName) 354 355 // Push with default passphrases 356 pushCmd := exec.Command(dockerBinary, "push", repoName) 357 s.trustedCmd(pushCmd) 358 out, _, err := runCommandWithOutput(pushCmd) 359 if err != nil { 360 c.Fatalf("trusted push failed: %s\n%s", err, out) 361 } 362 363 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 364 c.Fatalf("Missing expected output on trusted push:\n%s", out) 365 } 366 367 // Push with wrong passphrases 368 pushCmd = exec.Command(dockerBinary, "push", repoName) 369 s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "87654321") 370 out, _, err = runCommandWithOutput(pushCmd) 371 if err == nil { 372 c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out) 373 } 374 375 if !strings.Contains(string(out), "password invalid, operation has failed") { 376 c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out) 377 } 378 } 379 380 func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) { 381 c.Skip("Currently changes system time, causing instability") 382 repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL) 383 // tag the image and upload it to the private registry 384 dockerCmd(c, "tag", "busybox", repoName) 385 386 // Push with default passphrases 387 pushCmd := exec.Command(dockerBinary, "push", repoName) 388 s.trustedCmd(pushCmd) 389 out, _, err := runCommandWithOutput(pushCmd) 390 if err != nil { 391 c.Fatalf("trusted push failed: %s\n%s", err, out) 392 } 393 394 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 395 c.Fatalf("Missing expected output on trusted push:\n%s", out) 396 } 397 398 // Snapshots last for three years. This should be expired 399 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 400 401 runAtDifferentDate(fourYearsLater, func() { 402 // Push with wrong passphrases 403 pushCmd = exec.Command(dockerBinary, "push", repoName) 404 s.trustedCmd(pushCmd) 405 out, _, err = runCommandWithOutput(pushCmd) 406 if err == nil { 407 c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out) 408 } 409 410 if !strings.Contains(string(out), "repository out-of-date") { 411 c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out) 412 } 413 }) 414 } 415 416 func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) { 417 c.Skip("Currently changes system time, causing instability") 418 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL) 419 // tag the image and upload it to the private registry 420 dockerCmd(c, "tag", "busybox", repoName) 421 422 // Push with default passphrases 423 pushCmd := exec.Command(dockerBinary, "push", repoName) 424 s.trustedCmd(pushCmd) 425 out, _, err := runCommandWithOutput(pushCmd) 426 if err != nil { 427 c.Fatalf("trusted push failed: %s\n%s", err, out) 428 } 429 430 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 431 c.Fatalf("Missing expected output on trusted push:\n%s", out) 432 } 433 434 // The timestamps expire in two weeks. Lets check three 435 threeWeeksLater := time.Now().Add(time.Hour * 24 * 21) 436 437 // Should succeed because the server transparently re-signs one 438 runAtDifferentDate(threeWeeksLater, func() { 439 pushCmd := exec.Command(dockerBinary, "push", repoName) 440 s.trustedCmd(pushCmd) 441 out, _, err := runCommandWithOutput(pushCmd) 442 if err != nil { 443 c.Fatalf("Error running trusted push: %s\n%s", err, out) 444 } 445 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 446 c.Fatalf("Missing expected output on trusted push with expired timestamp:\n%s", out) 447 } 448 }) 449 }