github.com/flavio/docker@v0.1.3-0.20170117145210-f63d1a6eec47/integration-cli/docker_cli_ps_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "sort" 10 "strconv" 11 "strings" 12 "time" 13 14 "github.com/docker/docker/integration-cli/checker" 15 "github.com/docker/docker/pkg/stringid" 16 icmd "github.com/docker/docker/pkg/testutil/cmd" 17 "github.com/go-check/check" 18 ) 19 20 func (s *DockerSuite) TestPsListContainersBase(c *check.C) { 21 out, _ := runSleepingContainer(c, "-d") 22 firstID := strings.TrimSpace(out) 23 24 out, _ = runSleepingContainer(c, "-d") 25 secondID := strings.TrimSpace(out) 26 27 // not long running 28 out, _ = dockerCmd(c, "run", "-d", "busybox", "true") 29 thirdID := strings.TrimSpace(out) 30 31 out, _ = runSleepingContainer(c, "-d") 32 fourthID := strings.TrimSpace(out) 33 34 // make sure the second is running 35 c.Assert(waitRun(secondID), checker.IsNil) 36 37 // make sure third one is not running 38 dockerCmd(c, "wait", thirdID) 39 40 // make sure the forth is running 41 c.Assert(waitRun(fourthID), checker.IsNil) 42 43 // all 44 out, _ = dockerCmd(c, "ps", "-a") 45 c.Assert(assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}), checker.Equals, true, check.Commentf("ALL: Container list is not in the correct order: \n%s", out)) 46 47 // running 48 out, _ = dockerCmd(c, "ps") 49 c.Assert(assertContainerList(out, []string{fourthID, secondID, firstID}), checker.Equals, true, check.Commentf("RUNNING: Container list is not in the correct order: \n%s", out)) 50 51 // limit 52 out, _ = dockerCmd(c, "ps", "-n=2", "-a") 53 expected := []string{fourthID, thirdID} 54 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out)) 55 56 out, _ = dockerCmd(c, "ps", "-n=2") 57 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out)) 58 59 // filter since 60 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a") 61 expected = []string{fourthID, thirdID, secondID} 62 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out)) 63 64 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID) 65 expected = []string{fourthID, secondID} 66 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out)) 67 68 out, _ = dockerCmd(c, "ps", "-f", "since="+thirdID) 69 expected = []string{fourthID} 70 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out)) 71 72 // filter before 73 out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-a") 74 expected = []string{thirdID, secondID, firstID} 75 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out)) 76 77 out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID) 78 expected = []string{secondID, firstID} 79 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out)) 80 81 out, _ = dockerCmd(c, "ps", "-f", "before="+thirdID) 82 expected = []string{secondID, firstID} 83 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out)) 84 85 // filter since & before 86 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a") 87 expected = []string{thirdID, secondID} 88 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out)) 89 90 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID) 91 expected = []string{secondID} 92 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter: Container list is not in the correct order: \n%s", out)) 93 94 // filter since & limit 95 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a") 96 expected = []string{fourthID, thirdID} 97 98 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out)) 99 100 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2") 101 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out)) 102 103 // filter before & limit 104 out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a") 105 expected = []string{thirdID} 106 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out)) 107 108 out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1") 109 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out)) 110 111 // filter since & filter before & limit 112 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a") 113 expected = []string{thirdID} 114 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out)) 115 116 out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1") 117 c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out)) 118 119 } 120 121 func assertContainerList(out string, expected []string) bool { 122 lines := strings.Split(strings.Trim(out, "\n "), "\n") 123 124 if len(lines)-1 != len(expected) { 125 return false 126 } 127 128 containerIDIndex := strings.Index(lines[0], "CONTAINER ID") 129 for i := 0; i < len(expected); i++ { 130 foundID := lines[i+1][containerIDIndex : containerIDIndex+12] 131 if foundID != expected[i][:12] { 132 return false 133 } 134 } 135 136 return true 137 } 138 139 // FIXME(vdemeester) Move this into a unit test in daemon package 140 func (s *DockerSuite) TestPsListContainersInvalidFilterName(c *check.C) { 141 out, _, err := dockerCmdWithError("ps", "-f", "invalidFilter=test") 142 c.Assert(err, checker.NotNil) 143 c.Assert(out, checker.Contains, "Invalid filter") 144 } 145 146 func (s *DockerSuite) TestPsListContainersSize(c *check.C) { 147 // Problematic on Windows as it doesn't report the size correctly @swernli 148 testRequires(c, DaemonIsLinux) 149 dockerCmd(c, "run", "-d", "busybox") 150 151 baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1") 152 baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n") 153 baseSizeIndex := strings.Index(baseLines[0], "SIZE") 154 baseFoundsize := baseLines[1][baseSizeIndex:] 155 baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0]) 156 c.Assert(err, checker.IsNil) 157 158 name := "test_size" 159 dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test") 160 id, err := getIDByName(name) 161 c.Assert(err, checker.IsNil) 162 163 runCmd := exec.Command(dockerBinary, "ps", "-s", "-n=1") 164 var out string 165 166 wait := make(chan struct{}) 167 go func() { 168 out, _, err = runCommandWithOutput(runCmd) 169 close(wait) 170 }() 171 select { 172 case <-wait: 173 case <-time.After(3 * time.Second): 174 c.Fatalf("Calling \"docker ps -s\" timed out!") 175 } 176 c.Assert(err, checker.IsNil) 177 lines := strings.Split(strings.Trim(out, "\n "), "\n") 178 c.Assert(lines, checker.HasLen, 2, check.Commentf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))) 179 sizeIndex := strings.Index(lines[0], "SIZE") 180 idIndex := strings.Index(lines[0], "CONTAINER ID") 181 foundID := lines[1][idIndex : idIndex+12] 182 c.Assert(foundID, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s", id[:12], foundID)) 183 expectedSize := fmt.Sprintf("%d B", (2 + baseBytes)) 184 foundSize := lines[1][sizeIndex:] 185 c.Assert(foundSize, checker.Contains, expectedSize, check.Commentf("Expected size %q, got %q", expectedSize, foundSize)) 186 } 187 188 func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) { 189 // start exited container 190 out, _ := dockerCmd(c, "run", "-d", "busybox") 191 firstID := strings.TrimSpace(out) 192 193 // make sure the exited container is not running 194 dockerCmd(c, "wait", firstID) 195 196 // start running container 197 out, _ = dockerCmd(c, "run", "-itd", "busybox") 198 secondID := strings.TrimSpace(out) 199 200 // filter containers by exited 201 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited") 202 containerOut := strings.TrimSpace(out) 203 c.Assert(containerOut, checker.Equals, firstID) 204 205 out, _ = dockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running") 206 containerOut = strings.TrimSpace(out) 207 c.Assert(containerOut, checker.Equals, secondID) 208 209 result := dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish") 210 c.Assert(result, icmd.Matches, icmd.Expected{ 211 ExitCode: 1, 212 Err: "Unrecognised filter value for status", 213 }) 214 215 // Windows doesn't support pausing of containers 216 if testEnv.DaemonPlatform() != "windows" { 217 // pause running container 218 out, _ = dockerCmd(c, "run", "-itd", "busybox") 219 pausedID := strings.TrimSpace(out) 220 dockerCmd(c, "pause", pausedID) 221 // make sure the container is unpaused to let the daemon stop it properly 222 defer func() { dockerCmd(c, "unpause", pausedID) }() 223 224 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused") 225 containerOut = strings.TrimSpace(out) 226 c.Assert(containerOut, checker.Equals, pausedID) 227 } 228 } 229 230 func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) { 231 // Test legacy no health check 232 out, _ := runSleepingContainer(c, "--name=none_legacy") 233 containerID := strings.TrimSpace(out) 234 235 waitForContainer(containerID) 236 237 out, _ = dockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none") 238 containerOut := strings.TrimSpace(out) 239 c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for legacy none filter, output: %q", containerID, containerOut, out)) 240 241 // Test no health check specified explicitly 242 out, _ = runSleepingContainer(c, "--name=none", "--no-healthcheck") 243 containerID = strings.TrimSpace(out) 244 245 waitForContainer(containerID) 246 247 out, _ = dockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none") 248 containerOut = strings.TrimSpace(out) 249 c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for none filter, output: %q", containerID, containerOut, out)) 250 251 // Test failing health check 252 out, _ = runSleepingContainer(c, "--name=failing_container", "--health-cmd=exit 1", "--health-interval=1s") 253 containerID = strings.TrimSpace(out) 254 255 waitForHealthStatus(c, "failing_container", "starting", "unhealthy") 256 257 out, _ = dockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=unhealthy") 258 containerOut = strings.TrimSpace(out) 259 c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for unhealthy filter, output: %q", containerID, containerOut, out)) 260 261 // Check passing healthcheck 262 out, _ = runSleepingContainer(c, "--name=passing_container", "--health-cmd=exit 0", "--health-interval=1s") 263 containerID = strings.TrimSpace(out) 264 265 waitForHealthStatus(c, "passing_container", "starting", "healthy") 266 267 out, _ = dockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy") 268 containerOut = strings.TrimSpace(out) 269 c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out)) 270 } 271 272 func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) { 273 // start container 274 out, _ := dockerCmd(c, "run", "-d", "busybox") 275 firstID := strings.TrimSpace(out) 276 277 // start another container 278 runSleepingContainer(c) 279 280 // filter containers by id 281 out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID) 282 containerOut := strings.TrimSpace(out) 283 c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)) 284 } 285 286 func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) { 287 // start container 288 dockerCmd(c, "run", "--name=a_name_to_match", "busybox") 289 id, err := getIDByName("a_name_to_match") 290 c.Assert(err, check.IsNil) 291 292 // start another container 293 runSleepingContainer(c, "--name=b_name_to_match") 294 295 // filter containers by name 296 out, _ := dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match") 297 containerOut := strings.TrimSpace(out) 298 c.Assert(containerOut, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", id[:12], containerOut, out)) 299 } 300 301 // Test for the ancestor filter for ps. 302 // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go 303 // 304 // What the test setups : 305 // - Create 2 image based on busybox using the same repository but different tags 306 // - Create an image based on the previous image (images_ps_filter_test2) 307 // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2) 308 // - Filter them out :P 309 func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) { 310 // Build images 311 imageName1 := "images_ps_filter_test1" 312 imageID1, err := buildImage(imageName1, 313 `FROM busybox 314 LABEL match me 1`, true) 315 c.Assert(err, checker.IsNil) 316 317 imageName1Tagged := "images_ps_filter_test1:tag" 318 imageID1Tagged, err := buildImage(imageName1Tagged, 319 `FROM busybox 320 LABEL match me 1 tagged`, true) 321 c.Assert(err, checker.IsNil) 322 323 imageName2 := "images_ps_filter_test2" 324 imageID2, err := buildImage(imageName2, 325 fmt.Sprintf(`FROM %s 326 LABEL match me 2`, imageName1), true) 327 c.Assert(err, checker.IsNil) 328 329 // start containers 330 dockerCmd(c, "run", "--name=first", "busybox", "echo", "hello") 331 firstID, err := getIDByName("first") 332 c.Assert(err, check.IsNil) 333 334 // start another container 335 dockerCmd(c, "run", "--name=second", "busybox", "echo", "hello") 336 secondID, err := getIDByName("second") 337 c.Assert(err, check.IsNil) 338 339 // start third container 340 dockerCmd(c, "run", "--name=third", imageName1, "echo", "hello") 341 thirdID, err := getIDByName("third") 342 c.Assert(err, check.IsNil) 343 344 // start fourth container 345 dockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello") 346 fourthID, err := getIDByName("fourth") 347 c.Assert(err, check.IsNil) 348 349 // start fifth container 350 dockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello") 351 fifthID, err := getIDByName("fifth") 352 c.Assert(err, check.IsNil) 353 354 var filterTestSuite = []struct { 355 filterName string 356 expectedIDs []string 357 }{ 358 // non existent stuff 359 {"nonexistent", []string{}}, 360 {"nonexistent:tag", []string{}}, 361 // image 362 {"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}}, 363 {imageName1, []string{thirdID, fifthID}}, 364 {imageName2, []string{fifthID}}, 365 // image:tag 366 {fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}}, 367 {imageName1Tagged, []string{fourthID}}, 368 // short-id 369 {stringid.TruncateID(imageID1), []string{thirdID, fifthID}}, 370 {stringid.TruncateID(imageID2), []string{fifthID}}, 371 // full-id 372 {imageID1, []string{thirdID, fifthID}}, 373 {imageID1Tagged, []string{fourthID}}, 374 {imageID2, []string{fifthID}}, 375 } 376 377 var out string 378 for _, filter := range filterTestSuite { 379 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName) 380 checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs) 381 } 382 383 // Multiple ancestor filter 384 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged) 385 checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID}) 386 } 387 388 func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) { 389 actualIDs := []string{} 390 if out != "" { 391 actualIDs = strings.Split(out[:len(out)-1], "\n") 392 } 393 sort.Strings(actualIDs) 394 sort.Strings(expectedIDs) 395 396 c.Assert(actualIDs, checker.HasLen, len(expectedIDs), check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs)) 397 if len(expectedIDs) > 0 { 398 same := true 399 for i := range expectedIDs { 400 if actualIDs[i] != expectedIDs[i] { 401 c.Logf("%s, %s", actualIDs[i], expectedIDs[i]) 402 same = false 403 break 404 } 405 } 406 c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs)) 407 } 408 } 409 410 func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) { 411 // start container 412 dockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox") 413 firstID, err := getIDByName("first") 414 c.Assert(err, check.IsNil) 415 416 // start another container 417 dockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox") 418 secondID, err := getIDByName("second") 419 c.Assert(err, check.IsNil) 420 421 // start third container 422 dockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox") 423 thirdID, err := getIDByName("third") 424 c.Assert(err, check.IsNil) 425 426 // filter containers by exact match 427 out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me") 428 containerOut := strings.TrimSpace(out) 429 c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)) 430 431 // filter containers by two labels 432 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag") 433 containerOut = strings.TrimSpace(out) 434 c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)) 435 436 // filter containers by two labels, but expect not found because of AND behavior 437 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no") 438 containerOut = strings.TrimSpace(out) 439 c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)) 440 441 // filter containers by exact key 442 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match") 443 containerOut = strings.TrimSpace(out) 444 c.Assert(containerOut, checker.Contains, firstID) 445 c.Assert(containerOut, checker.Contains, secondID) 446 c.Assert(containerOut, checker.Not(checker.Contains), thirdID) 447 } 448 449 func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) { 450 runSleepingContainer(c, "--name=sleep") 451 452 dockerCmd(c, "run", "--name", "zero1", "busybox", "true") 453 firstZero, err := getIDByName("zero1") 454 c.Assert(err, checker.IsNil) 455 456 dockerCmd(c, "run", "--name", "zero2", "busybox", "true") 457 secondZero, err := getIDByName("zero2") 458 c.Assert(err, checker.IsNil) 459 460 out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false") 461 c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err)) 462 463 firstNonZero, err := getIDByName("nonzero1") 464 c.Assert(err, checker.IsNil) 465 466 out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false") 467 c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err)) 468 secondNonZero, err := getIDByName("nonzero2") 469 c.Assert(err, checker.IsNil) 470 471 // filter containers by exited=0 472 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0") 473 ids := strings.Split(strings.TrimSpace(out), "\n") 474 c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out)) 475 c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0])) 476 c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1])) 477 478 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1") 479 ids = strings.Split(strings.TrimSpace(out), "\n") 480 c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d", len(ids))) 481 c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0])) 482 c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1])) 483 484 } 485 486 func (s *DockerSuite) TestPsRightTagName(c *check.C) { 487 // TODO Investigate further why this fails on Windows to Windows CI 488 testRequires(c, DaemonIsLinux) 489 tag := "asybox:shmatest" 490 dockerCmd(c, "tag", "busybox", tag) 491 492 var id1 string 493 out, _ := runSleepingContainer(c) 494 id1 = strings.TrimSpace(string(out)) 495 496 var id2 string 497 out, _ = runSleepingContainerInImage(c, tag) 498 id2 = strings.TrimSpace(string(out)) 499 500 var imageID string 501 out = inspectField(c, "busybox", "Id") 502 imageID = strings.TrimSpace(string(out)) 503 504 var id3 string 505 out, _ = runSleepingContainerInImage(c, imageID) 506 id3 = strings.TrimSpace(string(out)) 507 508 out, _ = dockerCmd(c, "ps", "--no-trunc") 509 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 510 // skip header 511 lines = lines[1:] 512 c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines))) 513 for _, line := range lines { 514 f := strings.Fields(line) 515 switch f[0] { 516 case id1: 517 c.Assert(f[1], checker.Equals, "busybox", check.Commentf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])) 518 case id2: 519 c.Assert(f[1], checker.Equals, tag, check.Commentf("Expected %s tag for id %s, got %s", tag, id2, f[1])) 520 case id3: 521 c.Assert(f[1], checker.Equals, imageID, check.Commentf("Expected %s imageID for id %s, got %s", tag, id3, f[1])) 522 default: 523 c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3) 524 } 525 } 526 } 527 528 func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) { 529 // Problematic on Windows as it doesn't support links as of Jan 2016 530 testRequires(c, DaemonIsLinux) 531 runSleepingContainer(c, "--name=first") 532 runSleepingContainer(c, "--name=second", "--link=first:first") 533 534 out, _ := dockerCmd(c, "ps", "--no-trunc") 535 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 536 // strip header 537 lines = lines[1:] 538 expected := []string{"second", "first,second/first"} 539 var names []string 540 for _, l := range lines { 541 fields := strings.Fields(l) 542 names = append(names, fields[len(fields)-1]) 543 } 544 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array: %v, got: %v", expected, names)) 545 } 546 547 func (s *DockerSuite) TestPsGroupPortRange(c *check.C) { 548 // Problematic on Windows as it doesn't support port ranges as of Jan 2016 549 testRequires(c, DaemonIsLinux) 550 portRange := "3850-3900" 551 dockerCmd(c, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top") 552 553 out, _ := dockerCmd(c, "ps") 554 555 c.Assert(string(out), checker.Contains, portRange, check.Commentf("docker ps output should have had the port range %q: %s", portRange, string(out))) 556 557 } 558 559 func (s *DockerSuite) TestPsWithSize(c *check.C) { 560 // Problematic on Windows as it doesn't report the size correctly @swernli 561 testRequires(c, DaemonIsLinux) 562 dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top") 563 564 out, _ := dockerCmd(c, "ps", "--size") 565 c.Assert(out, checker.Contains, "virtual", check.Commentf("docker ps with --size should show virtual size of container")) 566 } 567 568 func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) { 569 // create a container 570 out, _ := dockerCmd(c, "create", "busybox") 571 cID := strings.TrimSpace(out) 572 shortCID := cID[:12] 573 574 // Make sure it DOESN'T show up w/o a '-a' for normal 'ps' 575 out, _ = dockerCmd(c, "ps", "-q") 576 c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out)) 577 578 // Make sure it DOES show up as 'Created' for 'ps -a' 579 out, _ = dockerCmd(c, "ps", "-a") 580 581 hits := 0 582 for _, line := range strings.Split(out, "\n") { 583 if !strings.Contains(line, shortCID) { 584 continue 585 } 586 hits++ 587 c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line)) 588 } 589 590 c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out)) 591 592 // filter containers by 'create' - note, no -a needed 593 out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created") 594 containerOut := strings.TrimSpace(out) 595 c.Assert(cID, checker.HasPrefix, containerOut) 596 } 597 598 func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) { 599 // Problematic on Windows as it doesn't support link as of Jan 2016 600 testRequires(c, DaemonIsLinux) 601 //create 2 containers and link them 602 dockerCmd(c, "run", "--name=child", "-d", "busybox", "top") 603 dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top") 604 605 //use the new format capabilities to only list the names and --no-trunc to get all names 606 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc") 607 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 608 expected := []string{"parent", "child,parent/linkedone"} 609 var names []string 610 names = append(names, lines...) 611 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names)) 612 613 //now list without turning off truncation and make sure we only get the non-link names 614 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}") 615 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 616 expected = []string{"parent", "child"} 617 var truncNames []string 618 truncNames = append(truncNames, lines...) 619 c.Assert(expected, checker.DeepEquals, truncNames, check.Commentf("Expected array with truncated names: %v, got: %v", expected, truncNames)) 620 } 621 622 // Test for GitHub issue #21772 623 func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) { 624 runSleepingContainer(c, "--name=test1") 625 runSleepingContainer(c, "--name=test2") 626 627 //use the new format capabilities to list the names twice 628 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Names}}") 629 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 630 expected := []string{"test2 test2", "test1 test1"} 631 var names []string 632 names = append(names, lines...) 633 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with names displayed twice: %v, got: %v", expected, names)) 634 } 635 636 func (s *DockerSuite) TestPsFormatHeaders(c *check.C) { 637 // make sure no-container "docker ps" still prints the header row 638 out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}") 639 c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out)) 640 641 // verify that "docker ps" with a container still prints the header row also 642 runSleepingContainer(c, "--name=test") 643 out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}") 644 c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out)) 645 } 646 647 func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) { 648 config := `{ 649 "psFormat": "default {{ .ID }}" 650 }` 651 d, err := ioutil.TempDir("", "integration-cli-") 652 c.Assert(err, checker.IsNil) 653 defer os.RemoveAll(d) 654 655 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644) 656 c.Assert(err, checker.IsNil) 657 658 out, _ := runSleepingContainer(c, "--name=test") 659 id := strings.TrimSpace(out) 660 661 out, _ = dockerCmd(c, "--config", d, "ps", "-q") 662 c.Assert(id, checker.HasPrefix, strings.TrimSpace(out), check.Commentf("Expected to print only the container id, got %v\n", out)) 663 } 664 665 // Test for GitHub issue #12595 666 func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) { 667 // TODO: Investigate why this fails on Windows to Windows CI further. 668 testRequires(c, DaemonIsLinux) 669 originalImageName := "busybox:TestPsImageIDAfterUpdate-original" 670 updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated" 671 672 icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success) 673 674 originalImageID, err := getIDByName(originalImageName) 675 c.Assert(err, checker.IsNil) 676 677 result := icmd.RunCommand(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...) 678 result.Assert(c, icmd.Success) 679 containerID := strings.TrimSpace(result.Combined()) 680 681 result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc") 682 result.Assert(c, icmd.Success) 683 684 lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n") 685 // skip header 686 lines = lines[1:] 687 c.Assert(len(lines), checker.Equals, 1) 688 689 for _, line := range lines { 690 f := strings.Fields(line) 691 c.Assert(f[1], checker.Equals, originalImageName) 692 } 693 694 icmd.RunCommand(dockerBinary, "commit", containerID, updatedImageName).Assert(c, icmd.Success) 695 icmd.RunCommand(dockerBinary, "tag", updatedImageName, originalImageName).Assert(c, icmd.Success) 696 697 result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc") 698 result.Assert(c, icmd.Success) 699 700 lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n") 701 // skip header 702 lines = lines[1:] 703 c.Assert(len(lines), checker.Equals, 1) 704 705 for _, line := range lines { 706 f := strings.Fields(line) 707 c.Assert(f[1], checker.Equals, originalImageID) 708 } 709 710 } 711 712 func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) { 713 testRequires(c, DaemonIsLinux) 714 dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top") 715 c.Assert(waitRun("foo"), checker.IsNil) 716 out, _ := dockerCmd(c, "ps") 717 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 718 expected := "0.0.0.0:5000->5000/tcp" 719 fields := strings.Fields(lines[1]) 720 c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2])) 721 722 dockerCmd(c, "kill", "foo") 723 dockerCmd(c, "wait", "foo") 724 out, _ = dockerCmd(c, "ps", "-l") 725 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 726 fields = strings.Fields(lines[1]) 727 c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected)) 728 } 729 730 func (s *DockerSuite) TestPsShowMounts(c *check.C) { 731 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 732 733 mp := prefix + slash + "test" 734 735 dockerCmd(c, "volume", "create", "ps-volume-test") 736 // volume mount containers 737 runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp) 738 c.Assert(waitRun("volume-test-1"), checker.IsNil) 739 runSleepingContainer(c, "--name=volume-test-2", "--volume", mp) 740 c.Assert(waitRun("volume-test-2"), checker.IsNil) 741 // bind mount container 742 var bindMountSource string 743 var bindMountDestination string 744 if DaemonIsWindows() { 745 bindMountSource = "c:\\" 746 bindMountDestination = "c:\\t" 747 } else { 748 bindMountSource = "/tmp" 749 bindMountDestination = "/t" 750 } 751 runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination) 752 c.Assert(waitRun("bind-mount-test"), checker.IsNil) 753 754 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}") 755 756 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 757 c.Assert(lines, checker.HasLen, 3) 758 759 fields := strings.Fields(lines[0]) 760 c.Assert(fields, checker.HasLen, 2) 761 c.Assert(fields[0], checker.Equals, "bind-mount-test") 762 c.Assert(fields[1], checker.Equals, bindMountSource) 763 764 fields = strings.Fields(lines[1]) 765 c.Assert(fields, checker.HasLen, 2) 766 767 annonymounsVolumeID := fields[1] 768 769 fields = strings.Fields(lines[2]) 770 c.Assert(fields[1], checker.Equals, "ps-volume-test") 771 772 // filter by volume name 773 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test") 774 775 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 776 c.Assert(lines, checker.HasLen, 1) 777 778 fields = strings.Fields(lines[0]) 779 c.Assert(fields[1], checker.Equals, "ps-volume-test") 780 781 // empty results filtering by unknown volume 782 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist") 783 c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0) 784 785 // filter by mount destination 786 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp) 787 788 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 789 c.Assert(lines, checker.HasLen, 2) 790 791 fields = strings.Fields(lines[0]) 792 c.Assert(fields[1], checker.Equals, annonymounsVolumeID) 793 fields = strings.Fields(lines[1]) 794 c.Assert(fields[1], checker.Equals, "ps-volume-test") 795 796 // filter by bind mount source 797 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource) 798 799 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 800 c.Assert(lines, checker.HasLen, 1) 801 802 fields = strings.Fields(lines[0]) 803 c.Assert(fields, checker.HasLen, 2) 804 c.Assert(fields[0], checker.Equals, "bind-mount-test") 805 c.Assert(fields[1], checker.Equals, bindMountSource) 806 807 // filter by bind mount destination 808 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination) 809 810 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 811 c.Assert(lines, checker.HasLen, 1) 812 813 fields = strings.Fields(lines[0]) 814 c.Assert(fields, checker.HasLen, 2) 815 c.Assert(fields[0], checker.Equals, "bind-mount-test") 816 c.Assert(fields[1], checker.Equals, bindMountSource) 817 818 // empty results filtering by unknown mount point 819 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted") 820 c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0) 821 } 822 823 func (s *DockerSuite) TestPsFormatSize(c *check.C) { 824 testRequires(c, DaemonIsLinux) 825 runSleepingContainer(c) 826 827 out, _ := dockerCmd(c, "ps", "--format", "table {{.Size}}") 828 lines := strings.Split(out, "\n") 829 c.Assert(lines[1], checker.Not(checker.Equals), "0 B", check.Commentf("Should not display a size of 0 B")) 830 831 out, _ = dockerCmd(c, "ps", "--size", "--format", "table {{.Size}}") 832 lines = strings.Split(out, "\n") 833 c.Assert(lines[0], checker.Equals, "SIZE", check.Commentf("Should only have one size column")) 834 835 out, _ = dockerCmd(c, "ps", "--size", "--format", "raw") 836 lines = strings.Split(out, "\n") 837 c.Assert(lines[8], checker.HasPrefix, "size:", check.Commentf("Size should be appended on a newline")) 838 } 839 840 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { 841 // TODO default network on Windows is not called "bridge", and creating a 842 // custom network fails on Windows fails with "Error response from daemon: plugin not found") 843 testRequires(c, DaemonIsLinux) 844 845 // create some containers 846 runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") 847 runSleepingContainer(c, "--net=none", "--name=onnonenetwork") 848 849 // Filter docker ps on non existing network 850 out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") 851 containerOut := strings.TrimSpace(string(out)) 852 lines := strings.Split(containerOut, "\n") 853 854 // skip header 855 lines = lines[1:] 856 857 // ps output should have no containers 858 c.Assert(lines, checker.HasLen, 0) 859 860 // Filter docker ps on network bridge 861 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") 862 containerOut = strings.TrimSpace(string(out)) 863 864 lines = strings.Split(containerOut, "\n") 865 866 // skip header 867 lines = lines[1:] 868 869 // ps output should have only one container 870 c.Assert(lines, checker.HasLen, 1) 871 872 // Making sure onbridgenetwork is on the output 873 c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) 874 875 // Filter docker ps on networks bridge and none 876 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") 877 containerOut = strings.TrimSpace(string(out)) 878 879 lines = strings.Split(containerOut, "\n") 880 881 // skip header 882 lines = lines[1:] 883 884 //ps output should have both the containers 885 c.Assert(lines, checker.HasLen, 2) 886 887 // Making sure onbridgenetwork and onnonenetwork is on the output 888 c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) 889 c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) 890 891 nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") 892 893 // Filter by network ID 894 out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) 895 containerOut = strings.TrimSpace(string(out)) 896 897 c.Assert(containerOut, checker.Contains, "onbridgenetwork") 898 } 899 900 func (s *DockerSuite) TestPsByOrder(c *check.C) { 901 name1 := "xyz-abc" 902 out, err := runSleepingContainer(c, "--name", name1) 903 c.Assert(err, checker.NotNil) 904 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 905 container1 := strings.TrimSpace(out) 906 907 name2 := "xyz-123" 908 out, err = runSleepingContainer(c, "--name", name2) 909 c.Assert(err, checker.NotNil) 910 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 911 container2 := strings.TrimSpace(out) 912 913 name3 := "789-abc" 914 out, err = runSleepingContainer(c, "--name", name3) 915 c.Assert(err, checker.NotNil) 916 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 917 918 name4 := "789-123" 919 out, err = runSleepingContainer(c, "--name", name4) 920 c.Assert(err, checker.NotNil) 921 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 922 923 // Run multiple time should have the same result 924 out, err = dockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz") 925 c.Assert(err, checker.NotNil) 926 c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1)) 927 928 // Run multiple time should have the same result 929 out, err = dockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz") 930 c.Assert(err, checker.NotNil) 931 c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1)) 932 } 933 934 func (s *DockerSuite) TestPsFilterMissingArgErrorCode(c *check.C) { 935 _, errCode, _ := dockerCmdWithError("ps", "--filter") 936 c.Assert(errCode, checker.Equals, 125) 937 }