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