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