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