docker_cli_ps_test.go 26 KB

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