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