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