github.com/vvnotw/moby@v1.13.1/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/pkg/integration/checker" 15 icmd "github.com/docker/docker/pkg/integration/cmd" 16 "github.com/docker/docker/pkg/stringid" 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 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 runCmd := exec.Command(dockerBinary, "tag", "busybox:latest", originalImageName) 673 out, _, err := runCommandWithOutput(runCmd) 674 c.Assert(err, checker.IsNil) 675 676 originalImageID, err := getIDByName(originalImageName) 677 c.Assert(err, checker.IsNil) 678 679 runCmd = exec.Command(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...) 680 out, _, err = runCommandWithOutput(runCmd) 681 c.Assert(err, checker.IsNil) 682 containerID := strings.TrimSpace(out) 683 684 linesOut, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput() 685 c.Assert(err, checker.IsNil) 686 687 lines := strings.Split(strings.TrimSpace(string(linesOut)), "\n") 688 // skip header 689 lines = lines[1:] 690 c.Assert(len(lines), checker.Equals, 1) 691 692 for _, line := range lines { 693 f := strings.Fields(line) 694 c.Assert(f[1], checker.Equals, originalImageName) 695 } 696 697 runCmd = exec.Command(dockerBinary, "commit", containerID, updatedImageName) 698 out, _, err = runCommandWithOutput(runCmd) 699 c.Assert(err, checker.IsNil) 700 701 runCmd = exec.Command(dockerBinary, "tag", updatedImageName, originalImageName) 702 out, _, err = runCommandWithOutput(runCmd) 703 c.Assert(err, checker.IsNil) 704 705 linesOut, err = exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput() 706 c.Assert(err, checker.IsNil) 707 708 lines = strings.Split(strings.TrimSpace(string(linesOut)), "\n") 709 // skip header 710 lines = lines[1:] 711 c.Assert(len(lines), checker.Equals, 1) 712 713 for _, line := range lines { 714 f := strings.Fields(line) 715 c.Assert(f[1], checker.Equals, originalImageID) 716 } 717 718 } 719 720 func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) { 721 testRequires(c, DaemonIsLinux) 722 dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top") 723 c.Assert(waitRun("foo"), checker.IsNil) 724 out, _ := dockerCmd(c, "ps") 725 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 726 expected := "0.0.0.0:5000->5000/tcp" 727 fields := strings.Fields(lines[1]) 728 c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2])) 729 730 dockerCmd(c, "kill", "foo") 731 dockerCmd(c, "wait", "foo") 732 out, _ = dockerCmd(c, "ps", "-l") 733 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 734 fields = strings.Fields(lines[1]) 735 c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected)) 736 } 737 738 func (s *DockerSuite) TestPsShowMounts(c *check.C) { 739 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 740 741 mp := prefix + slash + "test" 742 743 dockerCmd(c, "volume", "create", "ps-volume-test") 744 // volume mount containers 745 runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp) 746 c.Assert(waitRun("volume-test-1"), checker.IsNil) 747 runSleepingContainer(c, "--name=volume-test-2", "--volume", mp) 748 c.Assert(waitRun("volume-test-2"), checker.IsNil) 749 // bind mount container 750 var bindMountSource string 751 var bindMountDestination string 752 if DaemonIsWindows.Condition() { 753 bindMountSource = "c:\\" 754 bindMountDestination = "c:\\t" 755 } else { 756 bindMountSource = "/tmp" 757 bindMountDestination = "/t" 758 } 759 runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination) 760 c.Assert(waitRun("bind-mount-test"), checker.IsNil) 761 762 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}") 763 764 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 765 c.Assert(lines, checker.HasLen, 3) 766 767 fields := strings.Fields(lines[0]) 768 c.Assert(fields, checker.HasLen, 2) 769 c.Assert(fields[0], checker.Equals, "bind-mount-test") 770 c.Assert(fields[1], checker.Equals, bindMountSource) 771 772 fields = strings.Fields(lines[1]) 773 c.Assert(fields, checker.HasLen, 2) 774 775 annonymounsVolumeID := fields[1] 776 777 fields = strings.Fields(lines[2]) 778 c.Assert(fields[1], checker.Equals, "ps-volume-test") 779 780 // filter by volume name 781 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test") 782 783 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 784 c.Assert(lines, checker.HasLen, 1) 785 786 fields = strings.Fields(lines[0]) 787 c.Assert(fields[1], checker.Equals, "ps-volume-test") 788 789 // empty results filtering by unknown volume 790 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist") 791 c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0) 792 793 // filter by mount destination 794 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp) 795 796 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 797 c.Assert(lines, checker.HasLen, 2) 798 799 fields = strings.Fields(lines[0]) 800 c.Assert(fields[1], checker.Equals, annonymounsVolumeID) 801 fields = strings.Fields(lines[1]) 802 c.Assert(fields[1], checker.Equals, "ps-volume-test") 803 804 // filter by bind mount source 805 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource) 806 807 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 808 c.Assert(lines, checker.HasLen, 1) 809 810 fields = strings.Fields(lines[0]) 811 c.Assert(fields, checker.HasLen, 2) 812 c.Assert(fields[0], checker.Equals, "bind-mount-test") 813 c.Assert(fields[1], checker.Equals, bindMountSource) 814 815 // filter by bind mount destination 816 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination) 817 818 lines = strings.Split(strings.TrimSpace(string(out)), "\n") 819 c.Assert(lines, checker.HasLen, 1) 820 821 fields = strings.Fields(lines[0]) 822 c.Assert(fields, checker.HasLen, 2) 823 c.Assert(fields[0], checker.Equals, "bind-mount-test") 824 c.Assert(fields[1], checker.Equals, bindMountSource) 825 826 // empty results filtering by unknown mount point 827 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted") 828 c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0) 829 } 830 831 func (s *DockerSuite) TestPsFormatSize(c *check.C) { 832 testRequires(c, DaemonIsLinux) 833 runSleepingContainer(c) 834 835 out, _ := dockerCmd(c, "ps", "--format", "table {{.Size}}") 836 lines := strings.Split(out, "\n") 837 c.Assert(lines[1], checker.Not(checker.Equals), "0 B", check.Commentf("Should not display a size of 0 B")) 838 839 out, _ = dockerCmd(c, "ps", "--size", "--format", "table {{.Size}}") 840 lines = strings.Split(out, "\n") 841 c.Assert(lines[0], checker.Equals, "SIZE", check.Commentf("Should only have one size column")) 842 843 out, _ = dockerCmd(c, "ps", "--size", "--format", "raw") 844 lines = strings.Split(out, "\n") 845 c.Assert(lines[8], checker.HasPrefix, "size:", check.Commentf("Size should be appended on a newline")) 846 } 847 848 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { 849 // TODO default network on Windows is not called "bridge", and creating a 850 // custom network fails on Windows fails with "Error response from daemon: plugin not found") 851 testRequires(c, DaemonIsLinux) 852 853 // create some containers 854 runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") 855 runSleepingContainer(c, "--net=none", "--name=onnonenetwork") 856 857 // Filter docker ps on non existing network 858 out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") 859 containerOut := strings.TrimSpace(string(out)) 860 lines := strings.Split(containerOut, "\n") 861 862 // skip header 863 lines = lines[1:] 864 865 // ps output should have no containers 866 c.Assert(lines, checker.HasLen, 0) 867 868 // Filter docker ps on network bridge 869 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") 870 containerOut = strings.TrimSpace(string(out)) 871 872 lines = strings.Split(containerOut, "\n") 873 874 // skip header 875 lines = lines[1:] 876 877 // ps output should have only one container 878 c.Assert(lines, checker.HasLen, 1) 879 880 // Making sure onbridgenetwork is on the output 881 c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) 882 883 // Filter docker ps on networks bridge and none 884 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") 885 containerOut = strings.TrimSpace(string(out)) 886 887 lines = strings.Split(containerOut, "\n") 888 889 // skip header 890 lines = lines[1:] 891 892 //ps output should have both the containers 893 c.Assert(lines, checker.HasLen, 2) 894 895 // Making sure onbridgenetwork and onnonenetwork is on the output 896 c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) 897 c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) 898 899 nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") 900 901 // Filter by network ID 902 out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) 903 containerOut = strings.TrimSpace(string(out)) 904 905 c.Assert(containerOut, checker.Contains, "onbridgenetwork") 906 } 907 908 func (s *DockerSuite) TestPsByOrder(c *check.C) { 909 name1 := "xyz-abc" 910 out, err := runSleepingContainer(c, "--name", name1) 911 c.Assert(err, checker.NotNil) 912 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 913 container1 := strings.TrimSpace(out) 914 915 name2 := "xyz-123" 916 out, err = runSleepingContainer(c, "--name", name2) 917 c.Assert(err, checker.NotNil) 918 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 919 container2 := strings.TrimSpace(out) 920 921 name3 := "789-abc" 922 out, err = runSleepingContainer(c, "--name", name3) 923 c.Assert(err, checker.NotNil) 924 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 925 926 name4 := "789-123" 927 out, err = runSleepingContainer(c, "--name", name4) 928 c.Assert(err, checker.NotNil) 929 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 930 931 // Run multiple time should have the same result 932 out, err = dockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz") 933 c.Assert(err, checker.NotNil) 934 c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1)) 935 936 // Run multiple time should have the same result 937 out, err = dockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz") 938 c.Assert(err, checker.NotNil) 939 c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1)) 940 } 941 942 func (s *DockerSuite) TestPsFilterMissingArgErrorCode(c *check.C) { 943 _, errCode, _ := dockerCmdWithError("ps", "--filter") 944 c.Assert(errCode, checker.Equals, 125) 945 } 946 947 // Test case for 30291 948 func (s *DockerSuite) TestPsFormatTemplateWithArg(c *check.C) { 949 runSleepingContainer(c, "-d", "--name", "top", "--label", "some.label=label.foo-bar") 950 out, _ := dockerCmd(c, "ps", "--format", `{{.Names}} {{.Label "some.label"}}`) 951 c.Assert(strings.TrimSpace(out), checker.Equals, "top label.foo-bar") 952 }