github.com/slava-ustovytski/docker@v1.8.2-rc1/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 dockerCmd(c, "push", repoName) 64 65 // Ensure layer list is equivalent for repoTag1 and repoTag2 66 out1, _ := dockerCmd(c, "pull", repoTag1) 67 if strings.Contains(out1, "Tag t1 not found") { 68 c.Fatalf("Unable to pull pushed image: %s", out1) 69 } 70 imageAlreadyExists := ": Image already exists" 71 var out1Lines []string 72 for _, outputLine := range strings.Split(out1, "\n") { 73 if strings.Contains(outputLine, imageAlreadyExists) { 74 out1Lines = append(out1Lines, outputLine) 75 } 76 } 77 78 out2, _ := dockerCmd(c, "pull", repoTag2) 79 if strings.Contains(out2, "Tag t2 not found") { 80 c.Fatalf("Unable to pull pushed image: %s", out1) 81 } 82 var out2Lines []string 83 for _, outputLine := range strings.Split(out2, "\n") { 84 if strings.Contains(outputLine, imageAlreadyExists) { 85 out1Lines = append(out1Lines, outputLine) 86 } 87 } 88 89 if len(out1Lines) != len(out2Lines) { 90 c.Fatalf("Mismatched output length:\n%s\n%s", out1, out2) 91 } 92 93 for i := range out1Lines { 94 if out1Lines[i] != out2Lines[i] { 95 c.Fatalf("Mismatched output line:\n%s\n%s", out1Lines[i], out2Lines[i]) 96 } 97 } 98 } 99 100 func (s *DockerRegistrySuite) TestPushInterrupt(c *check.C) { 101 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 102 // tag the image and upload it to the private registry 103 dockerCmd(c, "tag", "busybox", repoName) 104 105 pushCmd := exec.Command(dockerBinary, "push", repoName) 106 if err := pushCmd.Start(); err != nil { 107 c.Fatalf("Failed to start pushing to private registry: %v", err) 108 } 109 110 // Interrupt push (yes, we have no idea at what point it will get killed). 111 time.Sleep(200 * time.Millisecond) 112 if err := pushCmd.Process.Kill(); err != nil { 113 c.Fatalf("Failed to kill push process: %v", err) 114 } 115 if out, _, err := dockerCmdWithError(c, "push", repoName); err == nil { 116 if !strings.Contains(out, "already in progress") { 117 c.Fatalf("Push should be continued on daemon side, but seems ok: %v, %s", err, out) 118 } 119 } 120 // now wait until all this pushes will complete 121 // if it failed with timeout - there would be some error, 122 // so no logic about it here 123 for exec.Command(dockerBinary, "push", repoName).Run() != nil { 124 } 125 } 126 127 func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) { 128 repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL) 129 emptyTarball, err := ioutil.TempFile("", "empty_tarball") 130 if err != nil { 131 c.Fatalf("Unable to create test file: %v", err) 132 } 133 tw := tar.NewWriter(emptyTarball) 134 err = tw.Close() 135 if err != nil { 136 c.Fatalf("Error creating empty tarball: %v", err) 137 } 138 freader, err := os.Open(emptyTarball.Name()) 139 if err != nil { 140 c.Fatalf("Could not open test tarball: %v", err) 141 } 142 143 importCmd := exec.Command(dockerBinary, "import", "-", repoName) 144 importCmd.Stdin = freader 145 out, _, err := runCommandWithOutput(importCmd) 146 if err != nil { 147 c.Errorf("import failed with errors: %v, output: %q", err, out) 148 } 149 150 // Now verify we can push it 151 if out, _, err := dockerCmdWithError(c, "push", repoName); err != nil { 152 c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err) 153 } 154 } 155 156 func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { 157 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 158 // tag the image and upload it to the private registry 159 dockerCmd(c, "tag", "busybox", repoName) 160 161 pushCmd := exec.Command(dockerBinary, "push", repoName) 162 s.trustedCmd(pushCmd) 163 out, _, err := runCommandWithOutput(pushCmd) 164 if err != nil { 165 c.Fatalf("Error running trusted push: %s\n%s", err, out) 166 } 167 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 168 c.Fatalf("Missing expected output on trusted push:\n%s", out) 169 } 170 } 171 172 func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(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.trustedCmdWithServer(pushCmd, "example/") 179 out, _, err := runCommandWithOutput(pushCmd) 180 if err == nil { 181 c.Fatalf("Missing error while running trusted push w/ no server") 182 } 183 184 if !strings.Contains(string(out), "Error establishing connection to notary repository") { 185 c.Fatalf("Missing expected output on trusted push:\n%s", out) 186 } 187 } 188 189 func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) { 190 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 191 // tag the image and upload it to the private registry 192 dockerCmd(c, "tag", "busybox", repoName) 193 194 pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName) 195 s.trustedCmdWithServer(pushCmd, "example/") 196 out, _, err := runCommandWithOutput(pushCmd) 197 if err != nil { 198 c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out) 199 } 200 201 if strings.Contains(string(out), "Error establishing connection to notary repository") { 202 c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out) 203 } 204 } 205 206 func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) { 207 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 208 // tag the image and upload it to the private registry 209 dockerCmd(c, "tag", "busybox", repoName) 210 dockerCmd(c, "push", repoName) 211 212 pushCmd := exec.Command(dockerBinary, "push", repoName) 213 s.trustedCmd(pushCmd) 214 out, _, err := runCommandWithOutput(pushCmd) 215 if err != nil { 216 c.Fatalf("trusted push failed: %s\n%s", err, out) 217 } 218 219 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 220 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 221 } 222 } 223 224 func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) { 225 repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL) 226 // tag the image and upload it to the private registry 227 dockerCmd(c, "tag", "busybox", repoName) 228 229 // Do a trusted push 230 pushCmd := exec.Command(dockerBinary, "push", repoName) 231 s.trustedCmd(pushCmd) 232 out, _, err := runCommandWithOutput(pushCmd) 233 if err != nil { 234 c.Fatalf("trusted push failed: %s\n%s", err, out) 235 } 236 237 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 238 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 239 } 240 241 // Do another trusted push 242 pushCmd = exec.Command(dockerBinary, "push", repoName) 243 s.trustedCmd(pushCmd) 244 out, _, err = runCommandWithOutput(pushCmd) 245 if err != nil { 246 c.Fatalf("trusted push failed: %s\n%s", err, out) 247 } 248 249 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 250 c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out) 251 } 252 253 dockerCmd(c, "rmi", repoName) 254 255 // Try pull to ensure the double push did not break our ability to pull 256 pullCmd := exec.Command(dockerBinary, "pull", repoName) 257 s.trustedCmd(pullCmd) 258 out, _, err = runCommandWithOutput(pullCmd) 259 if err != nil { 260 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 261 } 262 263 if !strings.Contains(string(out), "Status: Downloaded") { 264 c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out) 265 } 266 } 267 268 func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) { 269 repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL) 270 // tag the image and upload it to the private registry 271 dockerCmd(c, "tag", "busybox", repoName) 272 273 // Push with default passphrases 274 pushCmd := exec.Command(dockerBinary, "push", repoName) 275 s.trustedCmd(pushCmd) 276 out, _, err := runCommandWithOutput(pushCmd) 277 if err != nil { 278 c.Fatalf("trusted push failed: %s\n%s", err, out) 279 } 280 281 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 282 c.Fatalf("Missing expected output on trusted push:\n%s", out) 283 } 284 285 // Push with wrong passphrases 286 pushCmd = exec.Command(dockerBinary, "push", repoName) 287 s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321") 288 out, _, err = runCommandWithOutput(pushCmd) 289 if err == nil { 290 c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out) 291 } 292 293 if !strings.Contains(string(out), "password invalid, operation has failed") { 294 c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out) 295 } 296 } 297 298 func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) { 299 c.Skip("Currently changes system time, causing instability") 300 repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL) 301 // tag the image and upload it to the private registry 302 dockerCmd(c, "tag", "busybox", repoName) 303 304 // Push with default passphrases 305 pushCmd := exec.Command(dockerBinary, "push", repoName) 306 s.trustedCmd(pushCmd) 307 out, _, err := runCommandWithOutput(pushCmd) 308 if err != nil { 309 c.Fatalf("trusted push failed: %s\n%s", err, out) 310 } 311 312 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 313 c.Fatalf("Missing expected output on trusted push:\n%s", out) 314 } 315 316 // Snapshots last for three years. This should be expired 317 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 318 319 runAtDifferentDate(fourYearsLater, func() { 320 // Push with wrong passphrases 321 pushCmd = exec.Command(dockerBinary, "push", repoName) 322 s.trustedCmd(pushCmd) 323 out, _, err = runCommandWithOutput(pushCmd) 324 if err == nil { 325 c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out) 326 } 327 328 if !strings.Contains(string(out), "repository out-of-date") { 329 c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out) 330 } 331 }) 332 } 333 334 func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) { 335 c.Skip("Currently changes system time, causing instability") 336 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL) 337 // tag the image and upload it to the private registry 338 dockerCmd(c, "tag", "busybox", repoName) 339 340 // Push with default passphrases 341 pushCmd := exec.Command(dockerBinary, "push", repoName) 342 s.trustedCmd(pushCmd) 343 out, _, err := runCommandWithOutput(pushCmd) 344 if err != nil { 345 c.Fatalf("trusted push failed: %s\n%s", err, out) 346 } 347 348 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 349 c.Fatalf("Missing expected output on trusted push:\n%s", out) 350 } 351 352 // The timestamps expire in two weeks. Lets check three 353 threeWeeksLater := time.Now().Add(time.Hour * 24 * 21) 354 355 // Should succeed because the server transparently re-signs one 356 runAtDifferentDate(threeWeeksLater, func() { 357 pushCmd := exec.Command(dockerBinary, "push", repoName) 358 s.trustedCmd(pushCmd) 359 out, _, err := runCommandWithOutput(pushCmd) 360 if err != nil { 361 c.Fatalf("Error running trusted push: %s\n%s", err, out) 362 } 363 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 364 c.Fatalf("Missing expected output on trusted push with expired timestamp:\n%s", out) 365 } 366 }) 367 }