github.com/kaisenlinux/docker@v0.0.0-20230510090727-ea55db55fac7/engine/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", "6000:5000", "busybox", "top") 598 assert.Assert(c, waitRun("foo") == nil) 599 ports, _ := dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo") 600 expected := ":6000->5000/tcp" 601 assert.Assert(c, is.Contains(ports, expected), "Expected: %v, got: %v", expected, ports) 602 603 dockerCmd(c, "kill", "foo") 604 dockerCmd(c, "wait", "foo") 605 ports, _ = dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo") 606 assert.Equal(c, ports, "", "Should not got %v", expected) 607 } 608 609 func (s *DockerSuite) TestPsShowMounts(c *testing.T) { 610 existingContainers := ExistingContainerNames(c) 611 612 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 613 614 mp := prefix + slash + "test" 615 616 dockerCmd(c, "volume", "create", "ps-volume-test") 617 // volume mount containers 618 runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp) 619 assert.Assert(c, waitRun("volume-test-1") == nil) 620 runSleepingContainer(c, "--name=volume-test-2", "--volume", mp) 621 assert.Assert(c, waitRun("volume-test-2") == nil) 622 // bind mount container 623 var bindMountSource string 624 var bindMountDestination string 625 if DaemonIsWindows() { 626 bindMountSource = "c:\\" 627 bindMountDestination = "c:\\t" 628 } else { 629 bindMountSource = "/tmp" 630 bindMountDestination = "/t" 631 } 632 runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination) 633 assert.Assert(c, waitRun("bind-mount-test") == nil) 634 635 out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}") 636 637 lines := strings.Split(strings.TrimSpace(out), "\n") 638 lines = RemoveLinesForExistingElements(lines, existingContainers) 639 assert.Equal(c, len(lines), 3) 640 641 fields := strings.Fields(lines[0]) 642 assert.Equal(c, len(fields), 2) 643 assert.Equal(c, fields[0], "bind-mount-test") 644 assert.Equal(c, fields[1], bindMountSource) 645 646 fields = strings.Fields(lines[1]) 647 assert.Equal(c, len(fields), 2) 648 649 anonymousVolumeID := fields[1] 650 651 fields = strings.Fields(lines[2]) 652 assert.Equal(c, fields[1], "ps-volume-test") 653 654 // filter by volume name 655 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test") 656 657 lines = strings.Split(strings.TrimSpace(out), "\n") 658 lines = RemoveLinesForExistingElements(lines, existingContainers) 659 assert.Equal(c, len(lines), 1) 660 661 fields = strings.Fields(lines[0]) 662 assert.Equal(c, fields[1], "ps-volume-test") 663 664 // empty results filtering by unknown volume 665 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist") 666 assert.Equal(c, len(strings.TrimSpace(out)), 0) 667 668 // filter by mount destination 669 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp) 670 671 lines = strings.Split(strings.TrimSpace(out), "\n") 672 lines = RemoveLinesForExistingElements(lines, existingContainers) 673 assert.Equal(c, len(lines), 2) 674 675 fields = strings.Fields(lines[0]) 676 assert.Equal(c, fields[1], anonymousVolumeID) 677 fields = strings.Fields(lines[1]) 678 assert.Equal(c, fields[1], "ps-volume-test") 679 680 // filter by bind mount source 681 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource) 682 683 lines = strings.Split(strings.TrimSpace(out), "\n") 684 lines = RemoveLinesForExistingElements(lines, existingContainers) 685 assert.Equal(c, len(lines), 1) 686 687 fields = strings.Fields(lines[0]) 688 assert.Equal(c, len(fields), 2) 689 assert.Equal(c, fields[0], "bind-mount-test") 690 assert.Equal(c, fields[1], bindMountSource) 691 692 // filter by bind mount destination 693 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination) 694 695 lines = strings.Split(strings.TrimSpace(out), "\n") 696 lines = RemoveLinesForExistingElements(lines, existingContainers) 697 assert.Equal(c, len(lines), 1) 698 699 fields = strings.Fields(lines[0]) 700 assert.Equal(c, len(fields), 2) 701 assert.Equal(c, fields[0], "bind-mount-test") 702 assert.Equal(c, fields[1], bindMountSource) 703 704 // empty results filtering by unknown mount point 705 out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted") 706 assert.Equal(c, len(strings.TrimSpace(out)), 0) 707 } 708 709 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *testing.T) { 710 existing := ExistingContainerIDs(c) 711 712 // TODO default network on Windows is not called "bridge", and creating a 713 // custom network fails on Windows fails with "Error response from daemon: plugin not found") 714 testRequires(c, DaemonIsLinux) 715 716 // create some containers 717 runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") 718 runSleepingContainer(c, "--net=none", "--name=onnonenetwork") 719 720 // Filter docker ps on non existing network 721 out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") 722 containerOut := strings.TrimSpace(out) 723 lines := strings.Split(containerOut, "\n") 724 725 // skip header 726 lines = lines[1:] 727 728 // ps output should have no containers 729 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 0) 730 731 // Filter docker ps on network bridge 732 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") 733 containerOut = strings.TrimSpace(out) 734 735 lines = strings.Split(containerOut, "\n") 736 737 // skip header 738 lines = lines[1:] 739 740 // ps output should have only one container 741 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1) 742 743 // Making sure onbridgenetwork is on the output 744 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n") 745 // Filter docker ps on networks bridge and none 746 out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") 747 containerOut = strings.TrimSpace(out) 748 749 lines = strings.Split(containerOut, "\n") 750 751 // skip header 752 lines = lines[1:] 753 754 // ps output should have both the containers 755 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 2) 756 757 // Making sure onbridgenetwork and onnonenetwork is on the output 758 assert.Assert(c, strings.Contains(containerOut, "onnonenetwork"), "Missing the container on none network\n") 759 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on bridge network\n") 760 nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") 761 762 // Filter by network ID 763 out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) 764 containerOut = strings.TrimSpace(out) 765 766 assert.Assert(c, is.Contains(containerOut, "onbridgenetwork")) 767 768 // Filter by partial network ID 769 partialnwID := nwID[0:4] 770 771 out, _ = dockerCmd(c, "ps", "--filter", "network="+partialnwID) 772 containerOut = strings.TrimSpace(out) 773 774 lines = strings.Split(containerOut, "\n") 775 776 // skip header 777 lines = lines[1:] 778 779 // ps output should have only one container 780 assert.Equal(c, len(RemoveLinesForExistingElements(lines, existing)), 1) 781 782 // Making sure onbridgenetwork is on the output 783 assert.Assert(c, strings.Contains(containerOut, "onbridgenetwork"), "Missing the container on network\n") 784 } 785 786 func (s *DockerSuite) TestPsByOrder(c *testing.T) { 787 out := runSleepingContainer(c, "--name", "xyz-abc") 788 container1 := strings.TrimSpace(out) 789 790 out = runSleepingContainer(c, "--name", "xyz-123") 791 container2 := strings.TrimSpace(out) 792 793 runSleepingContainer(c, "--name", "789-abc") 794 runSleepingContainer(c, "--name", "789-123") 795 796 // Run multiple time should have the same result 797 out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined() 798 assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%s\n%s", container2, container1)) 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 805 func (s *DockerSuite) TestPsListContainersFilterPorts(c *testing.T) { 806 testRequires(c, DaemonIsLinux) 807 existingContainers := ExistingContainerIDs(c) 808 809 out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top") 810 id1 := strings.TrimSpace(out) 811 812 out, _ = dockerCmd(c, "run", "-d", "--expose=8080", "busybox", "top") 813 id2 := strings.TrimSpace(out) 814 815 out, _ = dockerCmd(c, "run", "-d", "-p", "1090:90", "busybox", "top") 816 id3 := strings.TrimSpace(out) 817 818 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q") 819 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 820 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 821 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 822 823 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-8080/udp") 824 assert.Assert(c, strings.TrimSpace(out) != id1) 825 assert.Assert(c, strings.TrimSpace(out) != id2) 826 assert.Assert(c, strings.TrimSpace(out) != id3) 827 828 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8081") 829 assert.Assert(c, strings.TrimSpace(out) != id1) 830 assert.Assert(c, strings.TrimSpace(out) != id2) 831 assert.Assert(c, strings.TrimSpace(out) != id3) 832 833 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-81") 834 assert.Assert(c, strings.TrimSpace(out) != id1) 835 assert.Assert(c, strings.TrimSpace(out) != id2) 836 assert.Assert(c, strings.TrimSpace(out) != id3) 837 838 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=80/tcp") 839 assert.Equal(c, strings.TrimSpace(out), id1) 840 assert.Assert(c, strings.TrimSpace(out) != id2) 841 assert.Assert(c, strings.TrimSpace(out) != id3) 842 843 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=1090") 844 assert.Assert(c, strings.TrimSpace(out) != id1) 845 assert.Assert(c, strings.TrimSpace(out) != id2) 846 assert.Equal(c, strings.TrimSpace(out), id3) 847 848 out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp") 849 out = RemoveOutputForExistingElements(out, existingContainers) 850 assert.Assert(c, strings.TrimSpace(out) != id1) 851 assert.Equal(c, strings.TrimSpace(out), id2) 852 assert.Assert(c, strings.TrimSpace(out) != id3) 853 } 854 855 func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *testing.T) { 856 testRequires(c, DaemonIsLinux, MinimumAPIVersion("1.31")) 857 existingContainers := ExistingContainerNames(c) 858 859 dockerCmd(c, "create", "--name=aaa", "busybox", "top") 860 dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top") 861 862 out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}") 863 lines := strings.Split(strings.TrimSpace(out), "\n") 864 lines = RemoveLinesForExistingElements(lines, existingContainers) 865 expected := []string{"bbb", "aaa,bbb/aaa"} 866 var names []string 867 names = append(names, lines...) 868 assert.Assert(c, is.DeepEqual(names, expected), "Expected array with non-truncated names: %v, got: %v", expected, names) 869 870 dockerCmd(c, "rm", "bbb") 871 872 out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}") 873 out = RemoveOutputForExistingElements(out, existingContainers) 874 assert.Equal(c, strings.TrimSpace(out), "aaa") 875 }