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