github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+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 skip.If(c, RuntimeIsWindowsContainerd(), "FIXME. Hang on Windows + containerd combination") 231 existingContainers := ExistingContainerIDs(c) 232 // Test legacy no health check 233 out := runSleepingContainer(c, "--name=none_legacy") 234 containerID := strings.TrimSpace(out) 235 236 cli.WaitRun(c, containerID) 237 238 out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined() 239 containerOut := strings.TrimSpace(out) 240 assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected id %s, got %s for legacy none filter, output: %q", containerID, containerOut, out)) 241 242 // Test no health check specified explicitly 243 out = runSleepingContainer(c, "--name=none", "--no-healthcheck") 244 containerID = strings.TrimSpace(out) 245 246 cli.WaitRun(c, containerID) 247 248 out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined() 249 containerOut = strings.TrimSpace(out) 250 assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected id %s, got %s for none filter, output: %q", containerID, containerOut, out)) 251 252 // Test failing health check 253 out = runSleepingContainer(c, "--name=failing_container", "--health-cmd=exit 1", "--health-interval=1s") 254 containerID = strings.TrimSpace(out) 255 256 waitForHealthStatus(c, "failing_container", "starting", "unhealthy") 257 258 out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=unhealthy").Combined() 259 containerOut = strings.TrimSpace(out) 260 assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected containerID %s, got %s for unhealthy filter, output: %q", containerID, containerOut, out)) 261 262 // Check passing healthcheck 263 out = runSleepingContainer(c, "--name=passing_container", "--health-cmd=exit 0", "--health-interval=1s") 264 containerID = strings.TrimSpace(out) 265 266 waitForHealthStatus(c, "passing_container", "starting", "healthy") 267 268 out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined() 269 containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers)) 270 assert.Equal(c, containerOut, containerID, fmt.Sprintf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out)) 271 } 272 273 func (s *DockerSuite) TestPsListContainersFilterID(c *testing.T) { 274 // start container 275 out, _ := dockerCmd(c, "run", "-d", "busybox") 276 firstID := strings.TrimSpace(out) 277 278 // start another container 279 runSleepingContainer(c) 280 281 // filter containers by id 282 out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID) 283 containerOut := strings.TrimSpace(out) 284 assert.Equal(c, containerOut, firstID[:12], fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)) 285 } 286 287 func (s *DockerSuite) TestPsListContainersFilterName(c *testing.T) { 288 // start container 289 dockerCmd(c, "run", "--name=a_name_to_match", "busybox") 290 id := getIDByName(c, "a_name_to_match") 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 assert.Equal(c, containerOut, id[:12], fmt.Sprintf("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 *testing.T) { 310 existingContainers := ExistingContainerIDs(c) 311 312 // Build images 313 imageName1 := "images_ps_filter_test1" 314 buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox 315 LABEL match me 1`)) 316 imageID1 := getIDByName(c, imageName1) 317 318 imageName1Tagged := "images_ps_filter_test1:tag" 319 buildImageSuccessfully(c, imageName1Tagged, build.WithDockerfile(`FROM busybox 320 LABEL match me 1 tagged`)) 321 imageID1Tagged := getIDByName(c, imageName1Tagged) 322 323 imageName2 := "images_ps_filter_test2" 324 buildImageSuccessfully(c, imageName2, build.WithDockerfile(fmt.Sprintf(`FROM %s 325 LABEL match me 2`, imageName1))) 326 imageID2 := getIDByName(c, imageName2) 327 328 // start containers 329 dockerCmd(c, "run", "--name=first", "busybox", "echo", "hello") 330 firstID := getIDByName(c, "first") 331 332 // start another container 333 dockerCmd(c, "run", "--name=second", "busybox", "echo", "hello") 334 secondID := getIDByName(c, "second") 335 336 // start third container 337 dockerCmd(c, "run", "--name=third", imageName1, "echo", "hello") 338 thirdID := getIDByName(c, "third") 339 340 // start fourth container 341 dockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello") 342 fourthID := getIDByName(c, "fourth") 343 344 // start fifth container 345 dockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello") 346 fifthID := getIDByName(c, "fifth") 347 348 var filterTestSuite = []struct { 349 filterName string 350 expectedIDs []string 351 }{ 352 // non existent stuff 353 {"nonexistent", []string{}}, 354 {"nonexistent:tag", []string{}}, 355 // image 356 {"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}}, 357 {imageName1, []string{thirdID, fifthID}}, 358 {imageName2, []string{fifthID}}, 359 // image:tag 360 {fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}}, 361 {imageName1Tagged, []string{fourthID}}, 362 // short-id 363 {stringid.TruncateID(imageID1), []string{thirdID, fifthID}}, 364 {stringid.TruncateID(imageID2), []string{fifthID}}, 365 // full-id 366 {imageID1, []string{thirdID, fifthID}}, 367 {imageID1Tagged, []string{fourthID}}, 368 {imageID2, []string{fifthID}}, 369 } 370 371 var out string 372 for _, filter := range filterTestSuite { 373 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName) 374 checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs) 375 } 376 377 // Multiple ancestor filter 378 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged) 379 checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID}) 380 } 381 382 func checkPsAncestorFilterOutput(c *testing.T, out string, filterName string, expectedIDs []string) { 383 var actualIDs []string 384 if out != "" { 385 actualIDs = strings.Split(out[:len(out)-1], "\n") 386 } 387 sort.Strings(actualIDs) 388 sort.Strings(expectedIDs) 389 390 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)) 391 if len(expectedIDs) > 0 { 392 same := true 393 for i := range expectedIDs { 394 if actualIDs[i] != expectedIDs[i] { 395 c.Logf("%s, %s", actualIDs[i], expectedIDs[i]) 396 same = false 397 break 398 } 399 } 400 assert.Equal(c, same, true, fmt.Sprintf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs)) 401 } 402 } 403 404 func (s *DockerSuite) TestPsListContainersFilterLabel(c *testing.T) { 405 // start container 406 dockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox") 407 firstID := getIDByName(c, "first") 408 409 // start another container 410 dockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox") 411 secondID := getIDByName(c, "second") 412 413 // start third container 414 dockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox") 415 thirdID := getIDByName(c, "third") 416 417 // filter containers by exact match 418 out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me") 419 containerOut := strings.TrimSpace(out) 420 assert.Equal(c, containerOut, firstID, fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)) 421 422 // filter containers by two labels 423 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag") 424 containerOut = strings.TrimSpace(out) 425 assert.Equal(c, containerOut, firstID, fmt.Sprintf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)) 426 427 // filter containers by two labels, but expect not found because of AND behavior 428 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no") 429 containerOut = strings.TrimSpace(out) 430 assert.Equal(c, containerOut, "", fmt.Sprintf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)) 431 432 // filter containers by exact key 433 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match") 434 containerOut = strings.TrimSpace(out) 435 assert.Assert(c, strings.Contains(containerOut, firstID)) 436 assert.Assert(c, strings.Contains(containerOut, secondID)) 437 assert.Assert(c, !strings.Contains(containerOut, thirdID)) 438 } 439 440 func (s *DockerSuite) TestPsListContainersFilterExited(c *testing.T) { 441 // TODO Flaky on Windows CI [both RS1 and RS5] 442 // On slower machines the container may not have exited 443 // yet when we filter below by exit status/exit value. 444 skip.If(c, DaemonIsWindows(), "FLAKY on Windows, see #20819") 445 runSleepingContainer(c, "--name=sleep") 446 447 firstZero, _ := dockerCmd(c, "run", "-d", "busybox", "true") 448 secondZero, _ := dockerCmd(c, "run", "-d", "busybox", "true") 449 450 out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false") 451 assert.Assert(c, err != nil, "Should fail. out: %s", out) 452 firstNonZero := getIDByName(c, "nonzero1") 453 454 out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false") 455 assert.Assert(c, err != nil, "Should fail. out: %s", out) 456 secondNonZero := getIDByName(c, "nonzero2") 457 458 // filter containers by exited=0 459 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0") 460 assert.Assert(c, strings.Contains(out, strings.TrimSpace(firstZero))) 461 assert.Assert(c, strings.Contains(out, strings.TrimSpace(secondZero))) 462 assert.Assert(c, !strings.Contains(out, strings.TrimSpace(firstNonZero))) 463 assert.Assert(c, !strings.Contains(out, strings.TrimSpace(secondNonZero))) 464 out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1") 465 assert.Assert(c, strings.Contains(out, strings.TrimSpace(firstNonZero))) 466 assert.Assert(c, strings.Contains(out, strings.TrimSpace(secondNonZero))) 467 assert.Assert(c, !strings.Contains(out, strings.TrimSpace(firstZero))) 468 assert.Assert(c, !strings.Contains(out, strings.TrimSpace(secondZero))) 469 } 470 471 func (s *DockerSuite) TestPsRightTagName(c *testing.T) { 472 // TODO Investigate further why this fails on Windows to Windows CI 473 testRequires(c, DaemonIsLinux) 474 475 existingContainers := ExistingContainerNames(c) 476 477 tag := "asybox:shmatest" 478 dockerCmd(c, "tag", "busybox", tag) 479 480 var id1 string 481 out := runSleepingContainer(c) 482 id1 = strings.TrimSpace(out) 483 484 var id2 string 485 out = runSleepingContainerInImage(c, tag) 486 id2 = strings.TrimSpace(out) 487 488 var imageID string 489 out = inspectField(c, "busybox", "Id") 490 imageID = strings.TrimSpace(out) 491 492 var id3 string 493 out = runSleepingContainerInImage(c, imageID) 494 id3 = strings.TrimSpace(out) 495 496 out, _ = dockerCmd(c, "ps", "--no-trunc") 497 lines := strings.Split(strings.TrimSpace(out), "\n") 498 lines = RemoveLinesForExistingElements(lines, existingContainers) 499 // skip header 500 lines = lines[1:] 501 assert.Equal(c, len(lines), 3, "There should be 3 running container, got %d", len(lines)) 502 for _, line := range lines { 503 f := strings.Fields(line) 504 switch f[0] { 505 case id1: 506 assert.Equal(c, f[1], "busybox", fmt.Sprintf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])) 507 case id2: 508 assert.Equal(c, f[1], tag, fmt.Sprintf("Expected %s tag for id %s, got %s", tag, id2, f[1])) 509 case id3: 510 assert.Equal(c, f[1], imageID, fmt.Sprintf("Expected %s imageID for id %s, got %s", tag, id3, f[1])) 511 default: 512 c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3) 513 } 514 } 515 } 516 517 func (s *DockerSuite) TestPsListContainersFilterCreated(c *testing.T) { 518 // create a container 519 out, _ := dockerCmd(c, "create", "busybox") 520 cID := strings.TrimSpace(out) 521 shortCID := cID[:12] 522 523 // Make sure it DOESN'T show up w/o a '-a' for normal 'ps' 524 out, _ = dockerCmd(c, "ps", "-q") 525 assert.Assert(c, !strings.Contains(out, shortCID), "Should have not seen '%s' in ps output:\n%s", shortCID, out) 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 assert.Assert(c, strings.Contains(line, "Created"), "Missing 'Created' on '%s'", line) 536 } 537 538 assert.Equal(c, hits, 1, fmt.Sprintf("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 assert.Assert(c, strings.HasPrefix(cID, containerOut)) 544 } 545 546 // Test for GitHub issue #12595 547 func (s *DockerSuite) TestPsImageIDAfterUpdate(c *testing.T) { 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(result.Combined()), "\n") 567 lines = RemoveLinesForExistingElements(lines, existingContainers) 568 // skip header 569 lines = lines[1:] 570 assert.Equal(c, len(lines), 1) 571 572 for _, line := range lines { 573 f := strings.Fields(line) 574 assert.Equal(c, f[1], 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(result.Combined()), "\n") 584 lines = RemoveLinesForExistingElements(lines, existingContainers) 585 // skip header 586 lines = lines[1:] 587 assert.Equal(c, len(lines), 1) 588 589 for _, line := range lines { 590 f := strings.Fields(line) 591 assert.Equal(c, f[1], originalImageID) 592 } 593 594 } 595 596 func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *testing.T) { 597 testRequires(c, DaemonIsLinux) 598 dockerCmd(c, "run", "--name=foo", "-d", "-p", "6000:5000", "busybox", "top") 599 assert.Assert(c, waitRun("foo") == nil) 600 ports, _ := dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo") 601 expected := ":6000->5000/tcp" 602 assert.Assert(c, is.Contains(ports, expected), "Expected: %v, got: %v", expected, ports) 603 604 dockerCmd(c, "kill", "foo") 605 dockerCmd(c, "wait", "foo") 606 ports, _ = dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo") 607 assert.Equal(c, ports, "", "Should not got %v", expected) 608 } 609 610 func (s *DockerSuite) TestPsShowMounts(c *testing.T) { 611 existingContainers := ExistingContainerNames(c) 612 613 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 614 615 mp := prefix + slash + "test" 616 617 dockerCmd(c, "volume", "create", "ps-volume-test") 618 // volume mount containers 619 runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp) 620 assert.Assert(c, waitRun("volume-test-1") == nil) 621 runSleepingContainer(c, "--name=volume-test-2", "--volume", mp) 622 assert.Assert(c, waitRun("volume-test-2") == nil) 623 // bind mount container 624 var bindMountSource string 625 var bindMountDestination string 626 if DaemonIsWindows() { 627 bindMountSource = "c:\\" 628 bindMountDestination = "c:\\t" 629 } else { 630 bindMountSource = "/tmp" 631 bindMountDestination = "/t" 632 } 633 runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination) 634 assert.Assert(c, waitRun("bind-mount-test") == nil) 635 636 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}") 637 638 lines := strings.Split(strings.TrimSpace(out), "\n") 639 lines = RemoveLinesForExistingElements(lines, existingContainers) 640 assert.Equal(c, len(lines), 3) 641 642 fields := strings.Fields(lines[0]) 643 assert.Equal(c, len(fields), 2) 644 assert.Equal(c, fields[0], "bind-mount-test") 645 assert.Equal(c, fields[1], bindMountSource) 646 647 fields = strings.Fields(lines[1]) 648 assert.Equal(c, len(fields), 2) 649 650 anonymousVolumeID := fields[1] 651 652 fields = strings.Fields(lines[2]) 653 assert.Equal(c, fields[1], "ps-volume-test") 654 655 // filter by volume name 656 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test") 657 658 lines = strings.Split(strings.TrimSpace(out), "\n") 659 lines = RemoveLinesForExistingElements(lines, existingContainers) 660 assert.Equal(c, len(lines), 1) 661 662 fields = strings.Fields(lines[0]) 663 assert.Equal(c, fields[1], "ps-volume-test") 664 665 // empty results filtering by unknown volume 666 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist") 667 assert.Equal(c, len(strings.TrimSpace(out)), 0) 668 669 // filter by mount destination 670 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp) 671 672 lines = strings.Split(strings.TrimSpace(out), "\n") 673 lines = RemoveLinesForExistingElements(lines, existingContainers) 674 assert.Equal(c, len(lines), 2) 675 676 fields = strings.Fields(lines[0]) 677 assert.Equal(c, fields[1], anonymousVolumeID) 678 fields = strings.Fields(lines[1]) 679 assert.Equal(c, fields[1], "ps-volume-test") 680 681 // filter by bind mount source 682 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource) 683 684 lines = strings.Split(strings.TrimSpace(out), "\n") 685 lines = RemoveLinesForExistingElements(lines, existingContainers) 686 assert.Equal(c, len(lines), 1) 687 688 fields = strings.Fields(lines[0]) 689 assert.Equal(c, len(fields), 2) 690 assert.Equal(c, fields[0], "bind-mount-test") 691 assert.Equal(c, fields[1], bindMountSource) 692 693 // filter by bind mount destination 694 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination) 695 696 lines = strings.Split(strings.TrimSpace(out), "\n") 697 lines = RemoveLinesForExistingElements(lines, existingContainers) 698 assert.Equal(c, len(lines), 1) 699 700 fields = strings.Fields(lines[0]) 701 assert.Equal(c, len(fields), 2) 702 assert.Equal(c, fields[0], "bind-mount-test") 703 assert.Equal(c, fields[1], bindMountSource) 704 705 // empty results filtering by unknown mount point 706 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted") 707 assert.Equal(c, len(strings.TrimSpace(out)), 0) 708 } 709 710 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *testing.T) { 711 existing := ExistingContainerIDs(c) 712 713 // TODO default network on Windows is not called "bridge", and creating a 714 // custom network fails on Windows fails with "Error response from daemon: plugin not found") 715 testRequires(c, DaemonIsLinux) 716 717 // create some containers 718 runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") 719 runSleepingContainer(c, "--net=none", "--name=onnonenetwork") 720 721 // Filter docker ps on non existing network 722 out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") 723 containerOut := strings.TrimSpace(out) 724 lines := strings.Split(containerOut, "\n") 725 726 // skip header 727 lines = lines[1:] 728 729 // ps output should have no containers 730 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 0) 731 732 // Filter docker ps on network bridge 733 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") 734 containerOut = strings.TrimSpace(out) 735 736 lines = strings.Split(containerOut, "\n") 737 738 // skip header 739 lines = lines[1:] 740 741 // ps output should have only one container 742 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1) 743 744 // Making sure onbridgenetwork is on the output 745 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n") 746 // Filter docker ps on networks bridge and none 747 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") 748 containerOut = strings.TrimSpace(out) 749 750 lines = strings.Split(containerOut, "\n") 751 752 // skip header 753 lines = lines[1:] 754 755 // ps output should have both the containers 756 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 2) 757 758 // Making sure onbridgenetwork and onnonenetwork is on the output 759 assert.Assert(c, strings.Contains(containerOut, "onnonenetwork"), "Missing the container on none network\n") 760 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on bridge network\n") 761 nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") 762 763 // Filter by network ID 764 out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) 765 containerOut = strings.TrimSpace(out) 766 767 assert.Assert(c, is.Contains(containerOut, "onbridgenetwork")) 768 769 // Filter by partial network ID 770 partialnwID := nwID[0:4] 771 772 out, _ = dockerCmd(c, "ps", "--filter", "network="+partialnwID) 773 containerOut = strings.TrimSpace(out) 774 775 lines = strings.Split(containerOut, "\n") 776 777 // skip header 778 lines = lines[1:] 779 780 // ps output should have only one container 781 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1) 782 783 // Making sure onbridgenetwork is on the output 784 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n") 785 } 786 787 func (s *DockerSuite) TestPsByOrder(c *testing.T) { 788 out := runSleepingContainer(c, "--name", "xyz-abc") 789 container1 := strings.TrimSpace(out) 790 791 out = runSleepingContainer(c, "--name", "xyz-123") 792 container2 := strings.TrimSpace(out) 793 794 runSleepingContainer(c, "--name", "789-abc") 795 runSleepingContainer(c, "--name", "789-123") 796 797 // Run multiple time should have the same result 798 out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined() 799 assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%s\n%s", container2, container1)) 800 801 // Run multiple time should have the same result 802 out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined() 803 assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%s\n%s", container2, container1)) 804 } 805 806 func (s *DockerSuite) TestPsListContainersFilterPorts(c *testing.T) { 807 testRequires(c, DaemonIsLinux) 808 existingContainers := ExistingContainerIDs(c) 809 810 out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top") 811 id1 := strings.TrimSpace(out) 812 813 out, _ = dockerCmd(c, "run", "-d", "--expose=8080", "busybox", "top") 814 id2 := strings.TrimSpace(out) 815 816 out, _ = dockerCmd(c, "run", "-d", "-p", "1090:90", "busybox", "top") 817 id3 := strings.TrimSpace(out) 818 819 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q") 820 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 821 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 822 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 823 824 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-8080/udp") 825 assert.Assert(c, strings.TrimSpace(out) != id1) 826 assert.Assert(c, strings.TrimSpace(out) != id2) 827 assert.Assert(c, strings.TrimSpace(out) != id3) 828 829 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8081") 830 assert.Assert(c, strings.TrimSpace(out) != id1) 831 assert.Assert(c, strings.TrimSpace(out) != id2) 832 assert.Assert(c, strings.TrimSpace(out) != id3) 833 834 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-81") 835 assert.Assert(c, strings.TrimSpace(out) != id1) 836 assert.Assert(c, strings.TrimSpace(out) != id2) 837 assert.Assert(c, strings.TrimSpace(out) != id3) 838 839 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=80/tcp") 840 assert.Equal(c, strings.TrimSpace(out), id1) 841 assert.Assert(c, strings.TrimSpace(out) != id2) 842 assert.Assert(c, strings.TrimSpace(out) != id3) 843 844 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=1090") 845 assert.Assert(c, strings.TrimSpace(out) != id1) 846 assert.Assert(c, strings.TrimSpace(out) != id2) 847 assert.Equal(c, strings.TrimSpace(out), id3) 848 849 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp") 850 out = RemoveOutputForExistingElements(out, existingContainers) 851 assert.Assert(c, strings.TrimSpace(out) != id1) 852 assert.Equal(c, strings.TrimSpace(out), id2) 853 assert.Assert(c, strings.TrimSpace(out) != id3) 854 } 855 856 func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *testing.T) { 857 testRequires(c, DaemonIsLinux, MinimumAPIVersion("1.31")) 858 existingContainers := ExistingContainerNames(c) 859 860 dockerCmd(c, "create", "--name=aaa", "busybox", "top") 861 dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top") 862 863 out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}") 864 lines := strings.Split(strings.TrimSpace(out), "\n") 865 lines = RemoveLinesForExistingElements(lines, existingContainers) 866 expected := []string{"bbb", "aaa,bbb/aaa"} 867 var names []string 868 names = append(names, lines...) 869 assert.Assert(c, is.DeepEqual(names, expected), "Expected array with non-truncated names: %v, got: %v", expected, names) 870 871 dockerCmd(c, "rm", "bbb") 872 873 out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}") 874 out = RemoveOutputForExistingElements(out, existingContainers) 875 assert.Equal(c, strings.TrimSpace(out), "aaa") 876 }