docker_cli_ps_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "os/exec"
  7. "path/filepath"
  8. "reflect"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "github.com/go-check/check"
  13. "sort"
  14. "github.com/docker/docker/pkg/stringid"
  15. )
  16. func (s *DockerSuite) TestPsListContainers(c *check.C) {
  17. out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  18. firstID := strings.TrimSpace(out)
  19. out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
  20. secondID := strings.TrimSpace(out)
  21. // not long running
  22. out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
  23. thirdID := strings.TrimSpace(out)
  24. out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
  25. fourthID := strings.TrimSpace(out)
  26. // make sure the second is running
  27. c.Assert(waitRun(secondID), check.IsNil)
  28. // make sure third one is not running
  29. dockerCmd(c, "wait", thirdID)
  30. // make sure the forth is running
  31. c.Assert(waitRun(fourthID), check.IsNil)
  32. // all
  33. out, _ = dockerCmd(c, "ps", "-a")
  34. if !assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}) {
  35. c.Errorf("Container list is not in the correct order: %s", out)
  36. }
  37. // running
  38. out, _ = dockerCmd(c, "ps")
  39. if !assertContainerList(out, []string{fourthID, secondID, firstID}) {
  40. c.Errorf("Container list is not in the correct order: %s", out)
  41. }
  42. // from here all flag '-a' is ignored
  43. // limit
  44. out, _ = dockerCmd(c, "ps", "-n=2", "-a")
  45. expected := []string{fourthID, thirdID}
  46. if !assertContainerList(out, expected) {
  47. c.Errorf("Container list is not in the correct order: %s", out)
  48. }
  49. out, _ = dockerCmd(c, "ps", "-n=2")
  50. if !assertContainerList(out, expected) {
  51. c.Errorf("Container list is not in the correct order: %s", out)
  52. }
  53. // since
  54. out, _ = dockerCmd(c, "ps", "--since", firstID, "-a")
  55. expected = []string{fourthID, thirdID, secondID}
  56. if !assertContainerList(out, expected) {
  57. c.Errorf("Container list is not in the correct order: %s", out)
  58. }
  59. out, _ = dockerCmd(c, "ps", "--since", firstID)
  60. if !assertContainerList(out, expected) {
  61. c.Errorf("Container list is not in the correct order: %s", out)
  62. }
  63. // before
  64. out, _ = dockerCmd(c, "ps", "--before", thirdID, "-a")
  65. expected = []string{secondID, firstID}
  66. if !assertContainerList(out, expected) {
  67. c.Errorf("Container list is not in the correct order: %s", out)
  68. }
  69. out, _ = dockerCmd(c, "ps", "--before", thirdID)
  70. if !assertContainerList(out, expected) {
  71. c.Errorf("Container list is not in the correct order: %s", out)
  72. }
  73. // since & before
  74. out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-a")
  75. expected = []string{thirdID, secondID}
  76. if !assertContainerList(out, expected) {
  77. c.Errorf("Container list is not in the correct order: %s", out)
  78. }
  79. out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID)
  80. if !assertContainerList(out, expected) {
  81. c.Errorf("Container list is not in the correct order: %s", out)
  82. }
  83. // since & limit
  84. out, _ = dockerCmd(c, "ps", "--since", firstID, "-n=2", "-a")
  85. expected = []string{fourthID, thirdID}
  86. if !assertContainerList(out, expected) {
  87. c.Errorf("Container list is not in the correct order: %s", out)
  88. }
  89. out, _ = dockerCmd(c, "ps", "--since", firstID, "-n=2")
  90. if !assertContainerList(out, expected) {
  91. c.Errorf("Container list is not in the correct order: %s", out)
  92. }
  93. // before & limit
  94. out, _ = dockerCmd(c, "ps", "--before", fourthID, "-n=1", "-a")
  95. expected = []string{thirdID}
  96. if !assertContainerList(out, expected) {
  97. c.Errorf("Container list is not in the correct order: %s", out)
  98. }
  99. out, _ = dockerCmd(c, "ps", "--before", fourthID, "-n=1")
  100. if !assertContainerList(out, expected) {
  101. c.Errorf("Container list is not in the correct order: %s", out)
  102. }
  103. out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-n=1", "-a")
  104. expected = []string{thirdID}
  105. if !assertContainerList(out, expected) {
  106. c.Errorf("Container list is not in the correct order: %s", out)
  107. }
  108. out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-n=1")
  109. if !assertContainerList(out, expected) {
  110. c.Errorf("Container list is not in the correct order: %s", out)
  111. }
  112. }
  113. func assertContainerList(out string, expected []string) bool {
  114. lines := strings.Split(strings.Trim(out, "\n "), "\n")
  115. if len(lines)-1 != len(expected) {
  116. return false
  117. }
  118. containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
  119. for i := 0; i < len(expected); i++ {
  120. foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
  121. if foundID != expected[i][:12] {
  122. return false
  123. }
  124. }
  125. return true
  126. }
  127. func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
  128. dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
  129. baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
  130. baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
  131. baseSizeIndex := strings.Index(baseLines[0], "SIZE")
  132. baseFoundsize := baseLines[1][baseSizeIndex:]
  133. baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
  134. if err != nil {
  135. c.Fatal(err)
  136. }
  137. name := "test_size"
  138. out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
  139. id, err := getIDByName(name)
  140. if err != nil {
  141. c.Fatal(err)
  142. }
  143. runCmd := exec.Command(dockerBinary, "ps", "-s", "-n=1")
  144. wait := make(chan struct{})
  145. go func() {
  146. out, _, err = runCommandWithOutput(runCmd)
  147. close(wait)
  148. }()
  149. select {
  150. case <-wait:
  151. case <-time.After(3 * time.Second):
  152. c.Fatalf("Calling \"docker ps -s\" timed out!")
  153. }
  154. if err != nil {
  155. c.Fatal(out, err)
  156. }
  157. lines := strings.Split(strings.Trim(out, "\n "), "\n")
  158. if len(lines) != 2 {
  159. c.Fatalf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
  160. }
  161. sizeIndex := strings.Index(lines[0], "SIZE")
  162. idIndex := strings.Index(lines[0], "CONTAINER ID")
  163. foundID := lines[1][idIndex : idIndex+12]
  164. if foundID != id[:12] {
  165. c.Fatalf("Expected id %s, got %s", id[:12], foundID)
  166. }
  167. expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
  168. foundSize := lines[1][sizeIndex:]
  169. if !strings.Contains(foundSize, expectedSize) {
  170. c.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
  171. }
  172. }
  173. func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
  174. // FIXME: this should test paused, but it makes things hang and its wonky
  175. // this is because paused containers can't be controlled by signals
  176. // start exited container
  177. out, _ := dockerCmd(c, "run", "-d", "busybox")
  178. firstID := strings.TrimSpace(out)
  179. // make sure the exited cintainer is not running
  180. dockerCmd(c, "wait", firstID)
  181. // start running container
  182. out, _ = dockerCmd(c, "run", "-itd", "busybox")
  183. secondID := strings.TrimSpace(out)
  184. // filter containers by exited
  185. out, _ = dockerCmd(c, "ps", "-q", "--filter=status=exited")
  186. containerOut := strings.TrimSpace(out)
  187. if containerOut != firstID[:12] {
  188. c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
  189. }
  190. out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=status=running")
  191. containerOut = strings.TrimSpace(out)
  192. if containerOut != secondID[:12] {
  193. c.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
  194. }
  195. out, _, _ = dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish")
  196. if !strings.Contains(out, "Unrecognised filter value for status") {
  197. c.Fatalf("Expected error response due to invalid status filter output: %q", out)
  198. }
  199. }
  200. func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
  201. // start container
  202. out, _ := dockerCmd(c, "run", "-d", "busybox")
  203. firstID := strings.TrimSpace(out)
  204. // start another container
  205. dockerCmd(c, "run", "-d", "busybox", "top")
  206. // filter containers by id
  207. out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
  208. containerOut := strings.TrimSpace(out)
  209. if containerOut != firstID[:12] {
  210. c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
  211. }
  212. }
  213. func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
  214. // start container
  215. out, _ := dockerCmd(c, "run", "-d", "--name=a_name_to_match", "busybox")
  216. firstID := strings.TrimSpace(out)
  217. // start another container
  218. dockerCmd(c, "run", "-d", "--name=b_name_to_match", "busybox", "top")
  219. // filter containers by name
  220. out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
  221. containerOut := strings.TrimSpace(out)
  222. if containerOut != firstID[:12] {
  223. c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
  224. }
  225. }
  226. // Test for the ancestor filter for ps.
  227. // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
  228. //
  229. // What the test setups :
  230. // - Create 2 image based on busybox using the same repository but different tags
  231. // - Create an image based on the previous image (images_ps_filter_test2)
  232. // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
  233. // - Filter them out :P
  234. func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
  235. // Build images
  236. imageName1 := "images_ps_filter_test1"
  237. imageID1, err := buildImage(imageName1,
  238. `FROM busybox
  239. LABEL match me 1`, true)
  240. c.Assert(err, check.IsNil)
  241. imageName1Tagged := "images_ps_filter_test1:tag"
  242. imageID1Tagged, err := buildImage(imageName1Tagged,
  243. `FROM busybox
  244. LABEL match me 1 tagged`, true)
  245. c.Assert(err, check.IsNil)
  246. imageName2 := "images_ps_filter_test2"
  247. imageID2, err := buildImage(imageName2,
  248. fmt.Sprintf(`FROM %s
  249. LABEL match me 2`, imageName1), true)
  250. c.Assert(err, check.IsNil)
  251. // start containers
  252. out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
  253. firstID := strings.TrimSpace(out)
  254. // start another container
  255. out, _ = dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
  256. secondID := strings.TrimSpace(out)
  257. // start third container
  258. out, _ = dockerCmd(c, "run", "-d", imageName1, "echo", "hello")
  259. thirdID := strings.TrimSpace(out)
  260. // start fourth container
  261. out, _ = dockerCmd(c, "run", "-d", imageName1Tagged, "echo", "hello")
  262. fourthID := strings.TrimSpace(out)
  263. // start fifth container
  264. out, _ = dockerCmd(c, "run", "-d", imageName2, "echo", "hello")
  265. fifthID := strings.TrimSpace(out)
  266. var filterTestSuite = []struct {
  267. filterName string
  268. expectedIDs []string
  269. }{
  270. // non existent stuff
  271. {"nonexistent", []string{}},
  272. {"nonexistent:tag", []string{}},
  273. // image
  274. {"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
  275. {imageName1, []string{thirdID, fifthID}},
  276. {imageName2, []string{fifthID}},
  277. // image:tag
  278. {fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
  279. {imageName1Tagged, []string{fourthID}},
  280. // short-id
  281. {stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
  282. {stringid.TruncateID(imageID2), []string{fifthID}},
  283. // full-id
  284. {imageID1, []string{thirdID, fifthID}},
  285. {imageID1Tagged, []string{fourthID}},
  286. {imageID2, []string{fifthID}},
  287. }
  288. for _, filter := range filterTestSuite {
  289. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
  290. checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs)
  291. }
  292. // Multiple ancestor filter
  293. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
  294. checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
  295. }
  296. func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
  297. actualIDs := []string{}
  298. if out != "" {
  299. actualIDs = strings.Split(out[:len(out)-1], "\n")
  300. }
  301. sort.Strings(actualIDs)
  302. sort.Strings(expectedIDs)
  303. if len(actualIDs) != len(expectedIDs) {
  304. c.Fatalf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs)
  305. }
  306. if len(expectedIDs) > 0 {
  307. same := true
  308. for i := range expectedIDs {
  309. if actualIDs[i] != expectedIDs[i] {
  310. c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
  311. same = false
  312. break
  313. }
  314. }
  315. if !same {
  316. c.Fatalf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs)
  317. }
  318. }
  319. }
  320. func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
  321. // start container
  322. out, _ := dockerCmd(c, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
  323. firstID := strings.TrimSpace(out)
  324. // start another container
  325. out, _ = dockerCmd(c, "run", "-d", "-l", "match=me too", "busybox")
  326. secondID := strings.TrimSpace(out)
  327. // start third container
  328. out, _ = dockerCmd(c, "run", "-d", "-l", "nomatch=me", "busybox")
  329. thirdID := strings.TrimSpace(out)
  330. // filter containers by exact match
  331. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
  332. containerOut := strings.TrimSpace(out)
  333. if containerOut != firstID {
  334. c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
  335. }
  336. // filter containers by two labels
  337. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
  338. containerOut = strings.TrimSpace(out)
  339. if containerOut != firstID {
  340. c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
  341. }
  342. // filter containers by two labels, but expect not found because of AND behavior
  343. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
  344. containerOut = strings.TrimSpace(out)
  345. if containerOut != "" {
  346. c.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
  347. }
  348. // filter containers by exact key
  349. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
  350. containerOut = strings.TrimSpace(out)
  351. if (!strings.Contains(containerOut, firstID) || !strings.Contains(containerOut, secondID)) || strings.Contains(containerOut, thirdID) {
  352. c.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
  353. }
  354. }
  355. func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
  356. dockerCmd(c, "run", "-d", "--name", "top", "busybox", "top")
  357. dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
  358. firstZero, err := getIDByName("zero1")
  359. if err != nil {
  360. c.Fatal(err)
  361. }
  362. dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
  363. secondZero, err := getIDByName("zero2")
  364. if err != nil {
  365. c.Fatal(err)
  366. }
  367. if out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false"); err == nil {
  368. c.Fatal("Should fail.", out, err)
  369. }
  370. firstNonZero, err := getIDByName("nonzero1")
  371. if err != nil {
  372. c.Fatal(err)
  373. }
  374. if out, _, err := dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false"); err == nil {
  375. c.Fatal("Should fail.", out, err)
  376. }
  377. secondNonZero, err := getIDByName("nonzero2")
  378. if err != nil {
  379. c.Fatal(err)
  380. }
  381. // filter containers by exited=0
  382. out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
  383. ids := strings.Split(strings.TrimSpace(out), "\n")
  384. if len(ids) != 2 {
  385. c.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
  386. }
  387. if ids[0] != secondZero {
  388. c.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
  389. }
  390. if ids[1] != firstZero {
  391. c.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
  392. }
  393. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
  394. ids = strings.Split(strings.TrimSpace(out), "\n")
  395. if len(ids) != 2 {
  396. c.Fatalf("Should be 2 zero exited containers got %d", len(ids))
  397. }
  398. if ids[0] != secondNonZero {
  399. c.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
  400. }
  401. if ids[1] != firstNonZero {
  402. c.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
  403. }
  404. }
  405. func (s *DockerSuite) TestPsRightTagName(c *check.C) {
  406. tag := "asybox:shmatest"
  407. dockerCmd(c, "tag", "busybox", tag)
  408. var id1 string
  409. out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  410. id1 = strings.TrimSpace(string(out))
  411. var id2 string
  412. out, _ = dockerCmd(c, "run", "-d", tag, "top")
  413. id2 = strings.TrimSpace(string(out))
  414. var imageID string
  415. out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox")
  416. imageID = strings.TrimSpace(string(out))
  417. var id3 string
  418. out, _ = dockerCmd(c, "run", "-d", imageID, "top")
  419. id3 = strings.TrimSpace(string(out))
  420. out, _ = dockerCmd(c, "ps", "--no-trunc")
  421. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  422. // skip header
  423. lines = lines[1:]
  424. if len(lines) != 3 {
  425. c.Fatalf("There should be 3 running container, got %d", len(lines))
  426. }
  427. for _, line := range lines {
  428. f := strings.Fields(line)
  429. switch f[0] {
  430. case id1:
  431. if f[1] != "busybox" {
  432. c.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
  433. }
  434. case id2:
  435. if f[1] != tag {
  436. c.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
  437. }
  438. case id3:
  439. if f[1] != imageID {
  440. c.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
  441. }
  442. default:
  443. c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
  444. }
  445. }
  446. }
  447. func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
  448. dockerCmd(c, "run", "--name=first", "-d", "busybox", "top")
  449. dockerCmd(c, "run", "--name=second", "--link=first:first", "-d", "busybox", "top")
  450. out, _ := dockerCmd(c, "ps", "--no-trunc")
  451. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  452. // strip header
  453. lines = lines[1:]
  454. expected := []string{"second", "first,second/first"}
  455. var names []string
  456. for _, l := range lines {
  457. fields := strings.Fields(l)
  458. names = append(names, fields[len(fields)-1])
  459. }
  460. if !reflect.DeepEqual(expected, names) {
  461. c.Fatalf("Expected array: %v, got: %v", expected, names)
  462. }
  463. }
  464. func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
  465. portRange := "3800-3900"
  466. dockerCmd(c, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top")
  467. out, _ := dockerCmd(c, "ps")
  468. // check that the port range is in the output
  469. if !strings.Contains(string(out), portRange) {
  470. c.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
  471. }
  472. }
  473. func (s *DockerSuite) TestPsWithSize(c *check.C) {
  474. dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top")
  475. out, _ := dockerCmd(c, "ps", "--size")
  476. if !strings.Contains(out, "virtual") {
  477. c.Fatalf("docker ps with --size should show virtual size of container")
  478. }
  479. }
  480. func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
  481. // create a container
  482. out, _ := dockerCmd(c, "create", "busybox")
  483. cID := strings.TrimSpace(out)
  484. shortCID := cID[:12]
  485. // Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
  486. out, _ = dockerCmd(c, "ps", "-q")
  487. if strings.Contains(out, shortCID) {
  488. c.Fatalf("Should have not seen '%s' in ps output:\n%s", shortCID, out)
  489. }
  490. // Make sure it DOES show up as 'Created' for 'ps -a'
  491. out, _ = dockerCmd(c, "ps", "-a")
  492. hits := 0
  493. for _, line := range strings.Split(out, "\n") {
  494. if !strings.Contains(line, shortCID) {
  495. continue
  496. }
  497. hits++
  498. if !strings.Contains(line, "Created") {
  499. c.Fatalf("Missing 'Created' on '%s'", line)
  500. }
  501. }
  502. if hits != 1 {
  503. c.Fatalf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out)
  504. }
  505. // filter containers by 'create' - note, no -a needed
  506. out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
  507. containerOut := strings.TrimSpace(out)
  508. if !strings.HasPrefix(cID, containerOut) {
  509. c.Fatalf("Expected id %s, got %s for filter, out: %s", cID, containerOut, out)
  510. }
  511. }
  512. func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
  513. //create 2 containers and link them
  514. dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
  515. dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
  516. //use the new format capabilities to only list the names and --no-trunc to get all names
  517. out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
  518. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  519. expected := []string{"parent", "child,parent/linkedone"}
  520. var names []string
  521. for _, l := range lines {
  522. names = append(names, l)
  523. }
  524. if !reflect.DeepEqual(expected, names) {
  525. c.Fatalf("Expected array with non-truncated names: %v, got: %v", expected, names)
  526. }
  527. //now list without turning off truncation and make sure we only get the non-link names
  528. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
  529. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  530. expected = []string{"parent", "child"}
  531. var truncNames []string
  532. for _, l := range lines {
  533. truncNames = append(truncNames, l)
  534. }
  535. if !reflect.DeepEqual(expected, truncNames) {
  536. c.Fatalf("Expected array with truncated names: %v, got: %v", expected, truncNames)
  537. }
  538. }
  539. func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
  540. // make sure no-container "docker ps" still prints the header row
  541. out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
  542. if out != "CONTAINER ID\n" {
  543. c.Fatalf(`Expected 'CONTAINER ID\n', got %v`, out)
  544. }
  545. // verify that "docker ps" with a container still prints the header row also
  546. dockerCmd(c, "run", "--name=test", "-d", "busybox", "top")
  547. out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
  548. if out != "NAMES\ntest\n" {
  549. c.Fatalf(`Expected 'NAMES\ntest\n', got %v`, out)
  550. }
  551. }
  552. func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
  553. config := `{
  554. "psFormat": "{{ .ID }} default"
  555. }`
  556. d, err := ioutil.TempDir("", "integration-cli-")
  557. c.Assert(err, check.IsNil)
  558. defer os.RemoveAll(d)
  559. err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
  560. c.Assert(err, check.IsNil)
  561. out, _ := dockerCmd(c, "run", "--name=test", "-d", "busybox", "top")
  562. id := strings.TrimSpace(out)
  563. out, _ = dockerCmd(c, "--config", d, "ps", "-q")
  564. if !strings.HasPrefix(id, strings.TrimSpace(out)) {
  565. c.Fatalf("Expected to print only the container id, got %v\n", out)
  566. }
  567. }
  568. // Test for GitHub issue #12595
  569. func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
  570. originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
  571. updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
  572. runCmd := exec.Command(dockerBinary, "tag", "busybox:latest", originalImageName)
  573. out, _, err := runCommandWithOutput(runCmd)
  574. c.Assert(err, check.IsNil)
  575. originalImageID, err := getIDByName(originalImageName)
  576. c.Assert(err, check.IsNil)
  577. runCmd = exec.Command(dockerBinary, "run", "-d", originalImageName, "top")
  578. out, _, err = runCommandWithOutput(runCmd)
  579. c.Assert(err, check.IsNil)
  580. containerID := strings.TrimSpace(out)
  581. linesOut, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
  582. c.Assert(err, check.IsNil)
  583. lines := strings.Split(strings.TrimSpace(string(linesOut)), "\n")
  584. // skip header
  585. lines = lines[1:]
  586. c.Assert(len(lines), check.Equals, 1)
  587. for _, line := range lines {
  588. f := strings.Fields(line)
  589. c.Assert(f[1], check.Equals, originalImageName)
  590. }
  591. runCmd = exec.Command(dockerBinary, "commit", containerID, updatedImageName)
  592. out, _, err = runCommandWithOutput(runCmd)
  593. c.Assert(err, check.IsNil)
  594. runCmd = exec.Command(dockerBinary, "tag", "-f", updatedImageName, originalImageName)
  595. out, _, err = runCommandWithOutput(runCmd)
  596. c.Assert(err, check.IsNil)
  597. linesOut, err = exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
  598. c.Assert(err, check.IsNil)
  599. lines = strings.Split(strings.TrimSpace(string(linesOut)), "\n")
  600. // skip header
  601. lines = lines[1:]
  602. c.Assert(len(lines), check.Equals, 1)
  603. for _, line := range lines {
  604. f := strings.Fields(line)
  605. c.Assert(f[1], check.Equals, originalImageID)
  606. }
  607. }