github.com/csfrancis/docker@v1.8.0-rc2/integration-cli/docker_cli_push_test.go (about) 1 package main 2 3 import ( 4 "archive/tar" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "strings" 10 "time" 11 12 "github.com/go-check/check" 13 ) 14 15 // Pushing an image to a private registry. 16 func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) { 17 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 18 // tag the image to upload it to the private registry 19 dockerCmd(c, "tag", "busybox", repoName) 20 // push the image to the registry 21 dockerCmd(c, "push", repoName) 22 } 23 24 // pushing an image without a prefix should throw an error 25 func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) { 26 if out, _, err := dockerCmdWithError(c, "push", "busybox"); err == nil { 27 c.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out) 28 } 29 } 30 31 func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) { 32 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 33 34 expected := "Repository does not exist" 35 if out, _, err := dockerCmdWithError(c, "push", repoName); err == nil { 36 c.Fatalf("pushing the image to the private registry should have failed: output %q", out) 37 } else if !strings.Contains(out, expected) { 38 c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out) 39 } 40 } 41 42 func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) { 43 repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL) 44 45 expected := "does not exist" 46 47 if out, _, err := dockerCmdWithError(c, "push", repoName); err == nil { 48 c.Fatalf("pushing the image to the private registry should have failed: output %q", out) 49 } else if !strings.Contains(out, expected) { 50 c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out) 51 } 52 } 53 54 func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) { 55 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 56 repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL) 57 repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL) 58 // tag the image and upload it to the private registry 59 dockerCmd(c, "tag", "busybox", repoTag1) 60 61 dockerCmd(c, "tag", "busybox", repoTag2) 62 63 out, _ := dockerCmd(c, "push", repoName) 64 65 // There should be no duplicate hashes in the output 66 imageSuccessfullyPushed := ": Image successfully pushed" 67 imageAlreadyExists := ": Image already exists" 68 imagePushHashes := make(map[string]struct{}) 69 outputLines := strings.Split(out, "\n") 70 for _, outputLine := range outputLines { 71 if strings.Contains(outputLine, imageSuccessfullyPushed) { 72 hash := strings.TrimSuffix(outputLine, imageSuccessfullyPushed) 73 if _, present := imagePushHashes[hash]; present { 74 c.Fatalf("Duplicate image push: %s", outputLine) 75 } 76 imagePushHashes[hash] = struct{}{} 77 } else if strings.Contains(outputLine, imageAlreadyExists) { 78 hash := strings.TrimSuffix(outputLine, imageAlreadyExists) 79 if _, present := imagePushHashes[hash]; present { 80 c.Fatalf("Duplicate image push: %s", outputLine) 81 } 82 imagePushHashes[hash] = struct{}{} 83 } 84 } 85 86 if len(imagePushHashes) == 0 { 87 c.Fatal(`Expected at least one line containing "Image successfully pushed"`) 88 } 89 } 90 91 func (s *DockerRegistrySuite) TestPushInterrupt(c *check.C) { 92 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 93 // tag the image and upload it to the private registry 94 dockerCmd(c, "tag", "busybox", repoName) 95 96 pushCmd := exec.Command(dockerBinary, "push", repoName) 97 if err := pushCmd.Start(); err != nil { 98 c.Fatalf("Failed to start pushing to private registry: %v", err) 99 } 100 101 // Interrupt push (yes, we have no idea at what point it will get killed). 102 time.Sleep(200 * time.Millisecond) 103 if err := pushCmd.Process.Kill(); err != nil { 104 c.Fatalf("Failed to kill push process: %v", err) 105 } 106 if out, _, err := dockerCmdWithError(c, "push", repoName); err == nil { 107 if !strings.Contains(out, "already in progress") { 108 c.Fatalf("Push should be continued on daemon side, but seems ok: %v, %s", err, out) 109 } 110 } 111 // now wait until all this pushes will complete 112 // if it failed with timeout - there would be some error, 113 // so no logic about it here 114 for exec.Command(dockerBinary, "push", repoName).Run() != nil { 115 } 116 } 117 118 func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) { 119 repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL) 120 emptyTarball, err := ioutil.TempFile("", "empty_tarball") 121 if err != nil { 122 c.Fatalf("Unable to create test file: %v", err) 123 } 124 tw := tar.NewWriter(emptyTarball) 125 err = tw.Close() 126 if err != nil { 127 c.Fatalf("Error creating empty tarball: %v", err) 128 } 129 freader, err := os.Open(emptyTarball.Name()) 130 if err != nil { 131 c.Fatalf("Could not open test tarball: %v", err) 132 } 133 134 importCmd := exec.Command(dockerBinary, "import", "-", repoName) 135 importCmd.Stdin = freader 136 out, _, err := runCommandWithOutput(importCmd) 137 if err != nil { 138 c.Errorf("import failed with errors: %v, output: %q", err, out) 139 } 140 141 // Now verify we can push it 142 if out, _, err := dockerCmdWithError(c, "push", repoName); err != nil { 143 c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err) 144 } 145 } 146 147 func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { 148 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 149 // tag the image and upload it to the private registry 150 dockerCmd(c, "tag", "busybox", repoName) 151 152 pushCmd := exec.Command(dockerBinary, "push", repoName) 153 s.trustedCmd(pushCmd) 154 out, _, err := runCommandWithOutput(pushCmd) 155 if err != nil { 156 c.Fatalf("Error running trusted push: %s\n%s", err, out) 157 } 158 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 159 c.Fatalf("Missing expected output on trusted push:\n%s", out) 160 } 161 } 162 163 func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) { 164 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 165 // tag the image and upload it to the private registry 166 dockerCmd(c, "tag", "busybox", repoName) 167 168 pushCmd := exec.Command(dockerBinary, "push", repoName) 169 s.trustedCmdWithServer(pushCmd, "example/") 170 out, _, err := runCommandWithOutput(pushCmd) 171 if err == nil { 172 c.Fatalf("Missing error while running trusted push w/ no server") 173 } 174 175 if !strings.Contains(string(out), "Error establishing connection to notary repository") { 176 c.Fatalf("Missing expected output on trusted push:\n%s", out) 177 } 178 } 179 180 func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) { 181 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 182 // tag the image and upload it to the private registry 183 dockerCmd(c, "tag", "busybox", repoName) 184 185 pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName) 186 s.trustedCmdWithServer(pushCmd, "example/") 187 out, _, err := runCommandWithOutput(pushCmd) 188 if err != nil { 189 c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out) 190 } 191 192 if strings.Contains(string(out), "Error establishing connection to notary repository") { 193 c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out) 194 } 195 } 196 197 func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) { 198 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 199 // tag the image and upload it to the private registry 200 dockerCmd(c, "tag", "busybox", repoName) 201 dockerCmd(c, "push", repoName) 202 203 pushCmd := exec.Command(dockerBinary, "push", repoName) 204 s.trustedCmd(pushCmd) 205 out, _, err := runCommandWithOutput(pushCmd) 206 if err != nil { 207 c.Fatalf("trusted push failed: %s\n%s", err, out) 208 } 209 210 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 211 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 212 } 213 } 214 215 func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) { 216 repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL) 217 // tag the image and upload it to the private registry 218 dockerCmd(c, "tag", "busybox", repoName) 219 220 // Do a trusted push 221 pushCmd := exec.Command(dockerBinary, "push", repoName) 222 s.trustedCmd(pushCmd) 223 out, _, err := runCommandWithOutput(pushCmd) 224 if err != nil { 225 c.Fatalf("trusted push failed: %s\n%s", err, out) 226 } 227 228 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 229 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 230 } 231 232 // Do another trusted push 233 pushCmd = exec.Command(dockerBinary, "push", repoName) 234 s.trustedCmd(pushCmd) 235 out, _, err = runCommandWithOutput(pushCmd) 236 if err != nil { 237 c.Fatalf("trusted push failed: %s\n%s", err, out) 238 } 239 240 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 241 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 242 } 243 244 dockerCmd(c, "rmi", repoName) 245 246 // Try pull to ensure the double push did not break our ability to pull 247 pullCmd := exec.Command(dockerBinary, "pull", repoName) 248 s.trustedCmd(pullCmd) 249 out, _, err = runCommandWithOutput(pullCmd) 250 if err != nil { 251 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 252 } 253 254 if !strings.Contains(string(out), "Status: Downloaded") { 255 c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out) 256 } 257 } 258 259 func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) { 260 repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL) 261 // tag the image and upload it to the private registry 262 dockerCmd(c, "tag", "busybox", repoName) 263 264 // Push with default passphrases 265 pushCmd := exec.Command(dockerBinary, "push", repoName) 266 s.trustedCmd(pushCmd) 267 out, _, err := runCommandWithOutput(pushCmd) 268 if err != nil { 269 c.Fatalf("trusted push failed: %s\n%s", err, out) 270 } 271 272 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 273 c.Fatalf("Missing expected output on trusted push:\n%s", out) 274 } 275 276 // Push with wrong passphrases 277 pushCmd = exec.Command(dockerBinary, "push", repoName) 278 s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321") 279 out, _, err = runCommandWithOutput(pushCmd) 280 if err == nil { 281 c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out) 282 } 283 284 if !strings.Contains(string(out), "password invalid, operation has failed") { 285 c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out) 286 } 287 } 288 289 func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) { 290 repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL) 291 // tag the image and upload it to the private registry 292 dockerCmd(c, "tag", "busybox", repoName) 293 294 // Push with default passphrases 295 pushCmd := exec.Command(dockerBinary, "push", repoName) 296 s.trustedCmd(pushCmd) 297 out, _, err := runCommandWithOutput(pushCmd) 298 if err != nil { 299 c.Fatalf("trusted push failed: %s\n%s", err, out) 300 } 301 302 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 303 c.Fatalf("Missing expected output on trusted push:\n%s", out) 304 } 305 306 // Snapshots last for three years. This should be expired 307 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 308 309 runAtDifferentDate(fourYearsLater, func() { 310 // Push with wrong passphrases 311 pushCmd = exec.Command(dockerBinary, "push", repoName) 312 s.trustedCmd(pushCmd) 313 out, _, err = runCommandWithOutput(pushCmd) 314 if err == nil { 315 c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out) 316 } 317 318 if !strings.Contains(string(out), "repository out-of-date") { 319 c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out) 320 } 321 }) 322 } 323 324 func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) { 325 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL) 326 // tag the image and upload it to the private registry 327 dockerCmd(c, "tag", "busybox", repoName) 328 329 // Push with default passphrases 330 pushCmd := exec.Command(dockerBinary, "push", repoName) 331 s.trustedCmd(pushCmd) 332 out, _, err := runCommandWithOutput(pushCmd) 333 if err != nil { 334 c.Fatalf("trusted push failed: %s\n%s", err, out) 335 } 336 337 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 338 c.Fatalf("Missing expected output on trusted push:\n%s", out) 339 } 340 341 // The timestamps expire in two weeks. Lets check three 342 threeWeeksLater := time.Now().Add(time.Hour * 24 * 21) 343 344 // Should succeed because the server transparently re-signs one 345 runAtDifferentDate(threeWeeksLater, func() { 346 pushCmd := exec.Command(dockerBinary, "push", repoName) 347 s.trustedCmd(pushCmd) 348 out, _, err := runCommandWithOutput(pushCmd) 349 if err != nil { 350 c.Fatalf("Error running trusted push: %s\n%s", err, out) 351 } 352 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 353 c.Fatalf("Missing expected output on trusted push with expired timestamp:\n%s", out) 354 } 355 }) 356 }