github.com/skatsuta/docker@v1.8.1/integration-cli/docker_cli_pull_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os/exec" 6 "strings" 7 "time" 8 9 "io/ioutil" 10 11 "github.com/go-check/check" 12 ) 13 14 // See issue docker/docker#8141 15 func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) { 16 repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) 17 18 repos := []string{} 19 for _, tag := range []string{"recent", "fresh"} { 20 repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag)) 21 } 22 23 // Tag and push the same image multiple times. 24 for _, repo := range repos { 25 dockerCmd(c, "tag", "busybox", repo) 26 dockerCmd(c, "push", repo) 27 } 28 29 // Clear local images store. 30 args := append([]string{"rmi"}, repos...) 31 dockerCmd(c, args...) 32 33 // Pull a single tag and verify it doesn't bring down all aliases. 34 dockerCmd(c, "pull", repos[0]) 35 dockerCmd(c, "inspect", repos[0]) 36 for _, repo := range repos[1:] { 37 if _, _, err := dockerCmdWithError(c, "inspect", repo); err == nil { 38 c.Fatalf("Image %v shouldn't have been pulled down", repo) 39 } 40 } 41 } 42 43 // pulling library/hello-world should show verified message 44 func (s *DockerSuite) TestPullVerified(c *check.C) { 45 c.Skip("Skipping hub dependent test") 46 47 // Image must be pulled from central repository to get verified message 48 // unless keychain is manually updated to contain the daemon's sign key. 49 50 verifiedName := "hello-world" 51 52 // pull it 53 expected := "The image you are pulling has been verified" 54 if out, exitCode, err := dockerCmdWithError(c, "pull", verifiedName); err != nil || !strings.Contains(out, expected) { 55 if err != nil || exitCode != 0 { 56 c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err)) 57 } 58 c.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err) 59 } 60 61 // pull it again 62 if out, exitCode, err := dockerCmdWithError(c, "pull", verifiedName); err != nil || strings.Contains(out, expected) { 63 if err != nil || exitCode != 0 { 64 c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err)) 65 } 66 c.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err) 67 } 68 69 } 70 71 // pulling an image from the central registry should work 72 func (s *DockerSuite) TestPullImageFromCentralRegistry(c *check.C) { 73 testRequires(c, Network) 74 75 dockerCmd(c, "pull", "hello-world") 76 } 77 78 // pulling a non-existing image from the central registry should return a non-zero exit code 79 func (s *DockerSuite) TestPullNonExistingImage(c *check.C) { 80 testRequires(c, Network) 81 82 name := "sadfsadfasdf" 83 out, _, err := dockerCmdWithError(c, "pull", name) 84 85 if err == nil || !strings.Contains(out, fmt.Sprintf("Error: image library/%s:latest not found", name)) { 86 c.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out) 87 } 88 } 89 90 // pulling an image from the central registry using official names should work 91 // ensure all pulls result in the same image 92 func (s *DockerSuite) TestPullImageOfficialNames(c *check.C) { 93 testRequires(c, Network) 94 95 names := []string{ 96 "library/hello-world", 97 "docker.io/library/hello-world", 98 "index.docker.io/library/hello-world", 99 } 100 for _, name := range names { 101 out, exitCode, err := dockerCmdWithError(c, "pull", name) 102 if err != nil || exitCode != 0 { 103 c.Errorf("pulling the '%s' image from the registry has failed: %s", name, err) 104 continue 105 } 106 107 // ensure we don't have multiple image names. 108 out, _ = dockerCmd(c, "images") 109 if strings.Contains(out, name) { 110 c.Errorf("images should not have listed '%s'", name) 111 } 112 } 113 } 114 115 func (s *DockerSuite) TestPullScratchNotAllowed(c *check.C) { 116 testRequires(c, Network) 117 118 out, exitCode, err := dockerCmdWithError(c, "pull", "scratch") 119 if err == nil { 120 c.Fatal("expected pull of scratch to fail, but it didn't") 121 } 122 if exitCode != 1 { 123 c.Fatalf("pulling scratch expected exit code 1, got %d", exitCode) 124 } 125 if strings.Contains(out, "Pulling repository scratch") { 126 c.Fatalf("pulling scratch should not have begun: %s", out) 127 } 128 if !strings.Contains(out, "'scratch' is a reserved name") { 129 c.Fatalf("unexpected output pulling scratch: %s", out) 130 } 131 } 132 133 // pulling an image with --all-tags=true 134 func (s *DockerSuite) TestPullImageWithAllTagFromCentralRegistry(c *check.C) { 135 testRequires(c, Network) 136 137 dockerCmd(c, "pull", "busybox") 138 139 outImageCmd, _ := dockerCmd(c, "images", "busybox") 140 141 dockerCmd(c, "pull", "--all-tags=true", "busybox") 142 143 outImageAllTagCmd, _ := dockerCmd(c, "images", "busybox") 144 145 if strings.Count(outImageCmd, "busybox") >= strings.Count(outImageAllTagCmd, "busybox") { 146 c.Fatalf("Pulling with all tags should get more images") 147 } 148 149 // FIXME has probably no effect (tags already pushed) 150 dockerCmd(c, "pull", "-a", "busybox") 151 152 outImageAllTagCmd, _ = dockerCmd(c, "images", "busybox") 153 154 if strings.Count(outImageCmd, "busybox") >= strings.Count(outImageAllTagCmd, "busybox") { 155 c.Fatalf("Pulling with all tags should get more images") 156 } 157 } 158 159 func (s *DockerTrustSuite) TestTrustedPull(c *check.C) { 160 repoName := s.setupTrustedImage(c, "trusted-pull") 161 162 // Try pull 163 pullCmd := exec.Command(dockerBinary, "pull", repoName) 164 s.trustedCmd(pullCmd) 165 out, _, err := runCommandWithOutput(pullCmd) 166 if err != nil { 167 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 168 } 169 170 if !strings.Contains(string(out), "Tagging") { 171 c.Fatalf("Missing expected output on trusted push:\n%s", out) 172 } 173 174 dockerCmd(c, "rmi", repoName) 175 176 // Try untrusted pull to ensure we pushed the tag to the registry 177 pullCmd = exec.Command(dockerBinary, "pull", "--disable-content-trust=true", repoName) 178 s.trustedCmd(pullCmd) 179 out, _, err = runCommandWithOutput(pullCmd) 180 if err != nil { 181 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 182 } 183 184 if !strings.Contains(string(out), "Status: Downloaded") { 185 c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out) 186 } 187 } 188 189 func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) { 190 repoName := s.setupTrustedImage(c, "trusted-isolatd-pull") 191 192 // Try pull (run from isolated directory without trust information) 193 pullCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated", "pull", repoName) 194 s.trustedCmd(pullCmd) 195 out, _, err := runCommandWithOutput(pullCmd) 196 if err != nil { 197 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 198 } 199 200 if !strings.Contains(string(out), "Tagging") { 201 c.Fatalf("Missing expected output on trusted push:\n%s", out) 202 } 203 204 dockerCmd(c, "rmi", repoName) 205 } 206 207 func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) { 208 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 209 // tag the image and upload it to the private registry 210 dockerCmd(c, "tag", "busybox", repoName) 211 dockerCmd(c, "push", repoName) 212 dockerCmd(c, "rmi", repoName) 213 214 // Try trusted pull on untrusted tag 215 pullCmd := exec.Command(dockerBinary, "pull", repoName) 216 s.trustedCmd(pullCmd) 217 out, _, err := runCommandWithOutput(pullCmd) 218 if err == nil { 219 c.Fatalf("Error expected when running trusted pull with:\n%s", out) 220 } 221 222 if !strings.Contains(string(out), "no trust data available") { 223 c.Fatalf("Missing expected output on trusted pull:\n%s", out) 224 } 225 } 226 227 func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) { 228 c.Skip("Currently changes system time, causing instability") 229 repoName := s.setupTrustedImage(c, "trusted-cert-expired") 230 231 // Certificates have 10 years of expiration 232 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 233 234 runAtDifferentDate(elevenYearsFromNow, func() { 235 // Try pull 236 pullCmd := exec.Command(dockerBinary, "pull", repoName) 237 s.trustedCmd(pullCmd) 238 out, _, err := runCommandWithOutput(pullCmd) 239 if err == nil { 240 c.Fatalf("Error running trusted pull in the distant future: %s\n%s", err, out) 241 } 242 243 if !strings.Contains(string(out), "could not validate the path to a trusted root") { 244 c.Fatalf("Missing expected output on trusted pull in the distant future:\n%s", out) 245 } 246 }) 247 248 runAtDifferentDate(elevenYearsFromNow, func() { 249 // Try pull 250 pullCmd := exec.Command(dockerBinary, "pull", "--disable-content-trust", repoName) 251 s.trustedCmd(pullCmd) 252 out, _, err := runCommandWithOutput(pullCmd) 253 if err != nil { 254 c.Fatalf("Error running untrusted pull in the distant future: %s\n%s", err, out) 255 } 256 257 if !strings.Contains(string(out), "Status: Downloaded") { 258 c.Fatalf("Missing expected output on untrusted pull in the distant future:\n%s", out) 259 } 260 }) 261 } 262 263 func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) { 264 repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL) 265 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 266 if err != nil { 267 c.Fatalf("Failed to create local temp dir") 268 } 269 270 // tag the image and upload it to the private registry 271 dockerCmd(c, "tag", "busybox", repoName) 272 273 pushCmd := exec.Command(dockerBinary, "push", repoName) 274 s.trustedCmd(pushCmd) 275 out, _, err := runCommandWithOutput(pushCmd) 276 if err != nil { 277 c.Fatalf("Error running trusted push: %s\n%s", err, out) 278 } 279 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 280 c.Fatalf("Missing expected output on trusted push:\n%s", out) 281 } 282 283 dockerCmd(c, "rmi", repoName) 284 285 // Try pull 286 pullCmd := exec.Command(dockerBinary, "pull", repoName) 287 s.trustedCmd(pullCmd) 288 out, _, err = runCommandWithOutput(pullCmd) 289 if err != nil { 290 c.Fatalf("Error running trusted pull: %s\n%s", err, out) 291 } 292 293 if !strings.Contains(string(out), "Tagging") { 294 c.Fatalf("Missing expected output on trusted push:\n%s", out) 295 } 296 297 dockerCmd(c, "rmi", repoName) 298 299 // Kill the notary server, start a new "evil" one. 300 s.not.Close() 301 s.not, err = newTestNotary(c) 302 if err != nil { 303 c.Fatalf("Restarting notary server failed.") 304 } 305 306 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 307 // tag an image and upload it to the private registry 308 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 309 310 // Push up to the new server 311 pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName) 312 s.trustedCmd(pushCmd) 313 out, _, err = runCommandWithOutput(pushCmd) 314 if err != nil { 315 c.Fatalf("Error running trusted push: %s\n%s", err, out) 316 } 317 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 318 c.Fatalf("Missing expected output on trusted push:\n%s", out) 319 } 320 321 // Now, try pulling with the original client from this new trust server. This should fail. 322 pullCmd = exec.Command(dockerBinary, "pull", repoName) 323 s.trustedCmd(pullCmd) 324 out, _, err = runCommandWithOutput(pullCmd) 325 if err == nil { 326 c.Fatalf("Expected to fail on this pull due to different remote data: %s\n%s", err, out) 327 } 328 329 if !strings.Contains(string(out), "failed to validate data with current trusted certificates") { 330 c.Fatalf("Missing expected output on trusted push:\n%s", out) 331 } 332 } 333 334 func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) { 335 c.Skip("Currently changes system time, causing instability") 336 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppull/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 dockerCmd(c, "rmi", repoName) 353 354 // Snapshots last for three years. This should be expired 355 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 356 357 // Should succeed because the server transparently re-signs one 358 runAtDifferentDate(fourYearsLater, func() { 359 // Try pull 360 pullCmd := exec.Command(dockerBinary, "pull", repoName) 361 s.trustedCmd(pullCmd) 362 out, _, err = runCommandWithOutput(pullCmd) 363 if err == nil { 364 c.Fatalf("Missing expected error running trusted pull with expired snapshots") 365 } 366 367 if !strings.Contains(string(out), "repository out-of-date") { 368 c.Fatalf("Missing expected output on trusted pull with expired snapshot:\n%s", out) 369 } 370 }) 371 }