docker_cli_ps_test.go 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  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 (s *DockerSuite) TestPsListContainersBase(c *check.C) {
  17. out, _ := runSleepingContainer(c, "-d")
  18. firstID := strings.TrimSpace(out)
  19. out, _ = runSleepingContainer(c, "-d")
  20. secondID := strings.TrimSpace(out)
  21. // not long running
  22. out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
  23. thirdID := strings.TrimSpace(out)
  24. out, _ = runSleepingContainer(c, "-d")
  25. fourthID := strings.TrimSpace(out)
  26. // make sure the second is running
  27. c.Assert(waitRun(secondID), checker.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), checker.IsNil)
  32. // all
  33. out, _ = dockerCmd(c, "ps", "-a")
  34. 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))
  35. // running
  36. out, _ = dockerCmd(c, "ps")
  37. 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))
  38. // limit
  39. out, _ = dockerCmd(c, "ps", "-n=2", "-a")
  40. expected := []string{fourthID, thirdID}
  41. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
  42. out, _ = dockerCmd(c, "ps", "-n=2")
  43. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
  44. // filter since
  45. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a")
  46. expected = []string{fourthID, thirdID, secondID}
  47. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
  48. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID)
  49. expected = []string{fourthID, secondID}
  50. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
  51. out, _ = dockerCmd(c, "ps", "-f", "since="+thirdID)
  52. expected = []string{fourthID}
  53. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
  54. // filter before
  55. out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-a")
  56. expected = []string{thirdID, secondID, firstID}
  57. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
  58. out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID)
  59. expected = []string{secondID, firstID}
  60. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out))
  61. out, _ = dockerCmd(c, "ps", "-f", "before="+thirdID)
  62. expected = []string{secondID, firstID}
  63. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: 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 filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
  68. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
  69. expected = []string{secondID}
  70. 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))
  71. // filter since & limit
  72. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a")
  73. expected = []string{fourthID, thirdID}
  74. 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))
  75. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2")
  76. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
  77. // filter before & limit
  78. out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a")
  79. expected = []string{thirdID}
  80. 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))
  81. out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1")
  82. c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
  83. // filter since & filter before & limit
  84. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a")
  85. expected = []string{thirdID}
  86. 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))
  87. out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
  88. 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))
  89. }
  90. func assertContainerList(out string, expected []string) bool {
  91. lines := strings.Split(strings.Trim(out, "\n "), "\n")
  92. if len(lines)-1 != len(expected) {
  93. return false
  94. }
  95. containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
  96. for i := 0; i < len(expected); i++ {
  97. foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
  98. if foundID != expected[i][:12] {
  99. return false
  100. }
  101. }
  102. return true
  103. }
  104. func (s *DockerSuite) TestPsListContainersInvalidFilterName(c *check.C) {
  105. out, _, err := dockerCmdWithError("ps", "-f", "invalidFilter=test")
  106. c.Assert(err, checker.NotNil)
  107. c.Assert(out, checker.Contains, "Invalid filter")
  108. }
  109. func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
  110. // Problematic on Windows as it doesn't report the size correctly @swernli
  111. testRequires(c, DaemonIsLinux)
  112. dockerCmd(c, "run", "-d", "busybox")
  113. baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
  114. baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
  115. baseSizeIndex := strings.Index(baseLines[0], "SIZE")
  116. baseFoundsize := baseLines[1][baseSizeIndex:]
  117. baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
  118. c.Assert(err, checker.IsNil)
  119. name := "test_size"
  120. dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
  121. id, err := getIDByName(name)
  122. c.Assert(err, checker.IsNil)
  123. runCmd := exec.Command(dockerBinary, "ps", "-s", "-n=1")
  124. var out string
  125. wait := make(chan struct{})
  126. go func() {
  127. out, _, err = runCommandWithOutput(runCmd)
  128. close(wait)
  129. }()
  130. select {
  131. case <-wait:
  132. case <-time.After(3 * time.Second):
  133. c.Fatalf("Calling \"docker ps -s\" timed out!")
  134. }
  135. c.Assert(err, checker.IsNil)
  136. lines := strings.Split(strings.Trim(out, "\n "), "\n")
  137. c.Assert(lines, checker.HasLen, 2, check.Commentf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines)))
  138. sizeIndex := strings.Index(lines[0], "SIZE")
  139. idIndex := strings.Index(lines[0], "CONTAINER ID")
  140. foundID := lines[1][idIndex : idIndex+12]
  141. c.Assert(foundID, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s", id[:12], foundID))
  142. expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
  143. foundSize := lines[1][sizeIndex:]
  144. c.Assert(foundSize, checker.Contains, expectedSize, check.Commentf("Expected size %q, got %q", expectedSize, foundSize))
  145. }
  146. func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
  147. // start exited container
  148. out, _ := dockerCmd(c, "run", "-d", "busybox")
  149. firstID := strings.TrimSpace(out)
  150. // make sure the exited container is not running
  151. dockerCmd(c, "wait", firstID)
  152. // start running container
  153. out, _ = dockerCmd(c, "run", "-itd", "busybox")
  154. secondID := strings.TrimSpace(out)
  155. // filter containers by exited
  156. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited")
  157. containerOut := strings.TrimSpace(out)
  158. c.Assert(containerOut, checker.Equals, firstID)
  159. out, _ = dockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running")
  160. containerOut = strings.TrimSpace(out)
  161. c.Assert(containerOut, checker.Equals, secondID)
  162. out, _, _ = dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish")
  163. c.Assert(out, checker.Contains, "Unrecognised filter value for status", check.Commentf("Expected error response due to invalid status filter output: %q", out))
  164. // Windows doesn't support pausing of containers
  165. if daemonPlatform != "windows" {
  166. // pause running container
  167. out, _ = dockerCmd(c, "run", "-itd", "busybox")
  168. pausedID := strings.TrimSpace(out)
  169. dockerCmd(c, "pause", pausedID)
  170. // make sure the container is unpaused to let the daemon stop it properly
  171. defer func() { dockerCmd(c, "unpause", pausedID) }()
  172. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused")
  173. containerOut = strings.TrimSpace(out)
  174. c.Assert(containerOut, checker.Equals, pausedID)
  175. }
  176. }
  177. func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
  178. // start container
  179. out, _ := dockerCmd(c, "run", "-d", "busybox")
  180. firstID := strings.TrimSpace(out)
  181. // start another container
  182. runSleepingContainer(c)
  183. // filter containers by id
  184. out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
  185. containerOut := strings.TrimSpace(out)
  186. c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
  187. }
  188. func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
  189. // start container
  190. dockerCmd(c, "run", "--name=a_name_to_match", "busybox")
  191. id, err := getIDByName("a_name_to_match")
  192. c.Assert(err, check.IsNil)
  193. // start another container
  194. runSleepingContainer(c, "--name=b_name_to_match")
  195. // filter containers by name
  196. out, _ := dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
  197. containerOut := strings.TrimSpace(out)
  198. c.Assert(containerOut, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", id[:12], containerOut, out))
  199. }
  200. // Test for the ancestor filter for ps.
  201. // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
  202. //
  203. // What the test setups :
  204. // - Create 2 image based on busybox using the same repository but different tags
  205. // - Create an image based on the previous image (images_ps_filter_test2)
  206. // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
  207. // - Filter them out :P
  208. func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
  209. // Build images
  210. imageName1 := "images_ps_filter_test1"
  211. imageID1, err := buildImage(imageName1,
  212. `FROM busybox
  213. LABEL match me 1`, true)
  214. c.Assert(err, checker.IsNil)
  215. imageName1Tagged := "images_ps_filter_test1:tag"
  216. imageID1Tagged, err := buildImage(imageName1Tagged,
  217. `FROM busybox
  218. LABEL match me 1 tagged`, true)
  219. c.Assert(err, checker.IsNil)
  220. imageName2 := "images_ps_filter_test2"
  221. imageID2, err := buildImage(imageName2,
  222. fmt.Sprintf(`FROM %s
  223. LABEL match me 2`, imageName1), true)
  224. c.Assert(err, checker.IsNil)
  225. // start containers
  226. dockerCmd(c, "run", "--name=first", "busybox", "echo", "hello")
  227. firstID, err := getIDByName("first")
  228. c.Assert(err, check.IsNil)
  229. // start another container
  230. dockerCmd(c, "run", "--name=second", "busybox", "echo", "hello")
  231. secondID, err := getIDByName("second")
  232. c.Assert(err, check.IsNil)
  233. // start third container
  234. dockerCmd(c, "run", "--name=third", imageName1, "echo", "hello")
  235. thirdID, err := getIDByName("third")
  236. c.Assert(err, check.IsNil)
  237. // start fourth container
  238. dockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello")
  239. fourthID, err := getIDByName("fourth")
  240. c.Assert(err, check.IsNil)
  241. // start fifth container
  242. dockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello")
  243. fifthID, err := getIDByName("fifth")
  244. c.Assert(err, check.IsNil)
  245. var filterTestSuite = []struct {
  246. filterName string
  247. expectedIDs []string
  248. }{
  249. // non existent stuff
  250. {"nonexistent", []string{}},
  251. {"nonexistent:tag", []string{}},
  252. // image
  253. {"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
  254. {imageName1, []string{thirdID, fifthID}},
  255. {imageName2, []string{fifthID}},
  256. // image:tag
  257. {fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
  258. {imageName1Tagged, []string{fourthID}},
  259. // short-id
  260. {stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
  261. {stringid.TruncateID(imageID2), []string{fifthID}},
  262. // full-id
  263. {imageID1, []string{thirdID, fifthID}},
  264. {imageID1Tagged, []string{fourthID}},
  265. {imageID2, []string{fifthID}},
  266. }
  267. var out string
  268. for _, filter := range filterTestSuite {
  269. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
  270. checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs)
  271. }
  272. // Multiple ancestor filter
  273. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
  274. checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
  275. }
  276. func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
  277. actualIDs := []string{}
  278. if out != "" {
  279. actualIDs = strings.Split(out[:len(out)-1], "\n")
  280. }
  281. sort.Strings(actualIDs)
  282. sort.Strings(expectedIDs)
  283. 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))
  284. if len(expectedIDs) > 0 {
  285. same := true
  286. for i := range expectedIDs {
  287. if actualIDs[i] != expectedIDs[i] {
  288. c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
  289. same = false
  290. break
  291. }
  292. }
  293. c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
  294. }
  295. }
  296. func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
  297. // start container
  298. dockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox")
  299. firstID, err := getIDByName("first")
  300. c.Assert(err, check.IsNil)
  301. // start another container
  302. dockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox")
  303. secondID, err := getIDByName("second")
  304. c.Assert(err, check.IsNil)
  305. // start third container
  306. dockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox")
  307. thirdID, err := getIDByName("third")
  308. c.Assert(err, check.IsNil)
  309. // filter containers by exact match
  310. out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
  311. containerOut := strings.TrimSpace(out)
  312. c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
  313. // filter containers by two labels
  314. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
  315. containerOut = strings.TrimSpace(out)
  316. c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
  317. // filter containers by two labels, but expect not found because of AND behavior
  318. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
  319. containerOut = strings.TrimSpace(out)
  320. c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
  321. // filter containers by exact key
  322. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
  323. containerOut = strings.TrimSpace(out)
  324. c.Assert(containerOut, checker.Contains, firstID)
  325. c.Assert(containerOut, checker.Contains, secondID)
  326. c.Assert(containerOut, checker.Not(checker.Contains), thirdID)
  327. }
  328. func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
  329. runSleepingContainer(c, "--name=sleep")
  330. dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
  331. firstZero, err := getIDByName("zero1")
  332. c.Assert(err, checker.IsNil)
  333. dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
  334. secondZero, err := getIDByName("zero2")
  335. c.Assert(err, checker.IsNil)
  336. out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
  337. c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
  338. firstNonZero, err := getIDByName("nonzero1")
  339. c.Assert(err, checker.IsNil)
  340. out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
  341. c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
  342. secondNonZero, err := getIDByName("nonzero2")
  343. c.Assert(err, checker.IsNil)
  344. // filter containers by exited=0
  345. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
  346. ids := strings.Split(strings.TrimSpace(out), "\n")
  347. c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out))
  348. c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0]))
  349. c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1]))
  350. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
  351. ids = strings.Split(strings.TrimSpace(out), "\n")
  352. c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d", len(ids)))
  353. c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0]))
  354. c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1]))
  355. }
  356. func (s *DockerSuite) TestPsRightTagName(c *check.C) {
  357. // TODO Investigate further why this fails on Windows to Windows CI
  358. testRequires(c, DaemonIsLinux)
  359. tag := "asybox:shmatest"
  360. dockerCmd(c, "tag", "busybox", tag)
  361. var id1 string
  362. out, _ := runSleepingContainer(c)
  363. id1 = strings.TrimSpace(string(out))
  364. var id2 string
  365. out, _ = runSleepingContainerInImage(c, tag)
  366. id2 = strings.TrimSpace(string(out))
  367. var imageID string
  368. out = inspectField(c, "busybox", "Id")
  369. imageID = strings.TrimSpace(string(out))
  370. var id3 string
  371. out, _ = runSleepingContainerInImage(c, imageID)
  372. id3 = strings.TrimSpace(string(out))
  373. out, _ = dockerCmd(c, "ps", "--no-trunc")
  374. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  375. // skip header
  376. lines = lines[1:]
  377. c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines)))
  378. for _, line := range lines {
  379. f := strings.Fields(line)
  380. switch f[0] {
  381. case id1:
  382. c.Assert(f[1], checker.Equals, "busybox", check.Commentf("Expected %s tag for id %s, got %s", "busybox", id1, f[1]))
  383. case id2:
  384. c.Assert(f[1], checker.Equals, tag, check.Commentf("Expected %s tag for id %s, got %s", tag, id2, f[1]))
  385. case id3:
  386. c.Assert(f[1], checker.Equals, imageID, check.Commentf("Expected %s imageID for id %s, got %s", tag, id3, f[1]))
  387. default:
  388. c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
  389. }
  390. }
  391. }
  392. func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
  393. // Problematic on Windows as it doesn't support links as of Jan 2016
  394. testRequires(c, DaemonIsLinux)
  395. runSleepingContainer(c, "--name=first")
  396. runSleepingContainer(c, "--name=second", "--link=first:first")
  397. out, _ := dockerCmd(c, "ps", "--no-trunc")
  398. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  399. // strip header
  400. lines = lines[1:]
  401. expected := []string{"second", "first,second/first"}
  402. var names []string
  403. for _, l := range lines {
  404. fields := strings.Fields(l)
  405. names = append(names, fields[len(fields)-1])
  406. }
  407. c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array: %v, got: %v", expected, names))
  408. }
  409. func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
  410. // Problematic on Windows as it doesn't support port ranges as of Jan 2016
  411. testRequires(c, DaemonIsLinux)
  412. portRange := "3850-3900"
  413. dockerCmd(c, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top")
  414. out, _ := dockerCmd(c, "ps")
  415. c.Assert(string(out), checker.Contains, portRange, check.Commentf("docker ps output should have had the port range %q: %s", portRange, string(out)))
  416. }
  417. func (s *DockerSuite) TestPsWithSize(c *check.C) {
  418. // Problematic on Windows as it doesn't report the size correctly @swernli
  419. testRequires(c, DaemonIsLinux)
  420. dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top")
  421. out, _ := dockerCmd(c, "ps", "--size")
  422. c.Assert(out, checker.Contains, "virtual", check.Commentf("docker ps with --size should show virtual size of container"))
  423. }
  424. func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
  425. // create a container
  426. out, _ := dockerCmd(c, "create", "busybox")
  427. cID := strings.TrimSpace(out)
  428. shortCID := cID[:12]
  429. // Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
  430. out, _ = dockerCmd(c, "ps", "-q")
  431. c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out))
  432. // Make sure it DOES show up as 'Created' for 'ps -a'
  433. out, _ = dockerCmd(c, "ps", "-a")
  434. hits := 0
  435. for _, line := range strings.Split(out, "\n") {
  436. if !strings.Contains(line, shortCID) {
  437. continue
  438. }
  439. hits++
  440. c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line))
  441. }
  442. c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
  443. // filter containers by 'create' - note, no -a needed
  444. out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
  445. containerOut := strings.TrimSpace(out)
  446. c.Assert(cID, checker.HasPrefix, containerOut)
  447. }
  448. func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
  449. // Problematic on Windows as it doesn't support link as of Jan 2016
  450. testRequires(c, DaemonIsLinux)
  451. //create 2 containers and link them
  452. dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
  453. dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
  454. //use the new format capabilities to only list the names and --no-trunc to get all names
  455. out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
  456. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  457. expected := []string{"parent", "child,parent/linkedone"}
  458. var names []string
  459. for _, l := range lines {
  460. names = append(names, l)
  461. }
  462. c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names))
  463. //now list without turning off truncation and make sure we only get the non-link names
  464. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
  465. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  466. expected = []string{"parent", "child"}
  467. var truncNames []string
  468. for _, l := range lines {
  469. truncNames = append(truncNames, l)
  470. }
  471. c.Assert(expected, checker.DeepEquals, truncNames, check.Commentf("Expected array with truncated names: %v, got: %v", expected, truncNames))
  472. }
  473. // Test for GitHub issue #21772
  474. func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) {
  475. runSleepingContainer(c, "--name=test1")
  476. runSleepingContainer(c, "--name=test2")
  477. //use the new format capabilities to list the names twice
  478. out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Names}}")
  479. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  480. expected := []string{"test2 test2", "test1 test1"}
  481. var names []string
  482. for _, l := range lines {
  483. names = append(names, l)
  484. }
  485. c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with names displayed twice: %v, got: %v", expected, names))
  486. }
  487. func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
  488. // make sure no-container "docker ps" still prints the header row
  489. out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
  490. c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
  491. // verify that "docker ps" with a container still prints the header row also
  492. runSleepingContainer(c, "--name=test")
  493. out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
  494. c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
  495. }
  496. func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
  497. config := `{
  498. "psFormat": "default {{ .ID }}"
  499. }`
  500. d, err := ioutil.TempDir("", "integration-cli-")
  501. c.Assert(err, checker.IsNil)
  502. defer os.RemoveAll(d)
  503. err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
  504. c.Assert(err, checker.IsNil)
  505. out, _ := runSleepingContainer(c, "--name=test")
  506. id := strings.TrimSpace(out)
  507. out, _ = dockerCmd(c, "--config", d, "ps", "-q")
  508. c.Assert(id, checker.HasPrefix, strings.TrimSpace(out), check.Commentf("Expected to print only the container id, got %v\n", out))
  509. }
  510. // Test for GitHub issue #12595
  511. func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
  512. // TODO: Investigate why this fails on Windows to Windows CI further.
  513. testRequires(c, DaemonIsLinux)
  514. originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
  515. updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
  516. runCmd := exec.Command(dockerBinary, "tag", "busybox:latest", originalImageName)
  517. out, _, err := runCommandWithOutput(runCmd)
  518. c.Assert(err, checker.IsNil)
  519. originalImageID, err := getIDByName(originalImageName)
  520. c.Assert(err, checker.IsNil)
  521. runCmd = exec.Command(dockerBinary, append([]string{"run", "-d", originalImageName}, defaultSleepCommand...)...)
  522. out, _, err = runCommandWithOutput(runCmd)
  523. c.Assert(err, checker.IsNil)
  524. containerID := strings.TrimSpace(out)
  525. linesOut, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
  526. c.Assert(err, checker.IsNil)
  527. lines := strings.Split(strings.TrimSpace(string(linesOut)), "\n")
  528. // skip header
  529. lines = lines[1:]
  530. c.Assert(len(lines), checker.Equals, 1)
  531. for _, line := range lines {
  532. f := strings.Fields(line)
  533. c.Assert(f[1], checker.Equals, originalImageName)
  534. }
  535. runCmd = exec.Command(dockerBinary, "commit", containerID, updatedImageName)
  536. out, _, err = runCommandWithOutput(runCmd)
  537. c.Assert(err, checker.IsNil)
  538. runCmd = exec.Command(dockerBinary, "tag", updatedImageName, originalImageName)
  539. out, _, err = runCommandWithOutput(runCmd)
  540. c.Assert(err, checker.IsNil)
  541. linesOut, err = exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
  542. c.Assert(err, checker.IsNil)
  543. lines = strings.Split(strings.TrimSpace(string(linesOut)), "\n")
  544. // skip header
  545. lines = lines[1:]
  546. c.Assert(len(lines), checker.Equals, 1)
  547. for _, line := range lines {
  548. f := strings.Fields(line)
  549. c.Assert(f[1], checker.Equals, originalImageID)
  550. }
  551. }
  552. func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
  553. testRequires(c, DaemonIsLinux)
  554. dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top")
  555. c.Assert(waitRun("foo"), checker.IsNil)
  556. out, _ := dockerCmd(c, "ps")
  557. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  558. expected := "0.0.0.0:5000->5000/tcp"
  559. fields := strings.Fields(lines[1])
  560. c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
  561. dockerCmd(c, "kill", "foo")
  562. dockerCmd(c, "wait", "foo")
  563. out, _ = dockerCmd(c, "ps", "-l")
  564. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  565. fields = strings.Fields(lines[1])
  566. c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
  567. }
  568. func (s *DockerSuite) TestPsShowMounts(c *check.C) {
  569. prefix, slash := getPrefixAndSlashFromDaemonPlatform()
  570. mp := prefix + slash + "test"
  571. dockerCmd(c, "volume", "create", "--name", "ps-volume-test")
  572. // volume mount containers
  573. runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
  574. c.Assert(waitRun("volume-test-1"), checker.IsNil)
  575. runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
  576. c.Assert(waitRun("volume-test-2"), checker.IsNil)
  577. // bind mount container
  578. var bindMountSource string
  579. var bindMountDestination string
  580. if DaemonIsWindows.Condition() {
  581. bindMountSource = "c:\\"
  582. bindMountDestination = "c:\\t"
  583. } else {
  584. bindMountSource = "/tmp"
  585. bindMountDestination = "/t"
  586. }
  587. runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination)
  588. c.Assert(waitRun("bind-mount-test"), checker.IsNil)
  589. out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
  590. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  591. c.Assert(lines, checker.HasLen, 3)
  592. fields := strings.Fields(lines[0])
  593. c.Assert(fields, checker.HasLen, 2)
  594. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  595. c.Assert(fields[1], checker.Equals, bindMountSource)
  596. fields = strings.Fields(lines[1])
  597. c.Assert(fields, checker.HasLen, 2)
  598. annonymounsVolumeID := fields[1]
  599. fields = strings.Fields(lines[2])
  600. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  601. // filter by volume name
  602. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
  603. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  604. c.Assert(lines, checker.HasLen, 1)
  605. fields = strings.Fields(lines[0])
  606. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  607. // empty results filtering by unknown volume
  608. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist")
  609. c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
  610. // filter by mount destination
  611. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
  612. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  613. c.Assert(lines, checker.HasLen, 2)
  614. fields = strings.Fields(lines[0])
  615. c.Assert(fields[1], checker.Equals, annonymounsVolumeID)
  616. fields = strings.Fields(lines[1])
  617. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  618. // filter by bind mount source
  619. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource)
  620. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  621. c.Assert(lines, checker.HasLen, 1)
  622. fields = strings.Fields(lines[0])
  623. c.Assert(fields, checker.HasLen, 2)
  624. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  625. c.Assert(fields[1], checker.Equals, bindMountSource)
  626. // filter by bind mount destination
  627. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination)
  628. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  629. c.Assert(lines, checker.HasLen, 1)
  630. fields = strings.Fields(lines[0])
  631. c.Assert(fields, checker.HasLen, 2)
  632. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  633. c.Assert(fields[1], checker.Equals, bindMountSource)
  634. // empty results filtering by unknown mount point
  635. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted")
  636. c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
  637. }
  638. func (s *DockerSuite) TestPsFormatSize(c *check.C) {
  639. testRequires(c, DaemonIsLinux)
  640. runSleepingContainer(c)
  641. out, _ := dockerCmd(c, "ps", "--format", "table {{.Size}}")
  642. lines := strings.Split(out, "\n")
  643. c.Assert(lines[1], checker.Not(checker.Equals), "0 B", check.Commentf("Should not display a size of 0 B"))
  644. out, _ = dockerCmd(c, "ps", "--size", "--format", "table {{.Size}}")
  645. lines = strings.Split(out, "\n")
  646. c.Assert(lines[0], checker.Equals, "SIZE", check.Commentf("Should only have one size column"))
  647. out, _ = dockerCmd(c, "ps", "--size", "--format", "raw")
  648. lines = strings.Split(out, "\n")
  649. c.Assert(lines[8], checker.HasPrefix, "size:", check.Commentf("Size should be appended on a newline"))
  650. }
  651. func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
  652. // TODO default network on Windows is not called "bridge", and creating a
  653. // custom network fails on Windows fails with "Error response from daemon: plugin not found")
  654. testRequires(c, DaemonIsLinux)
  655. // create some containers
  656. runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork")
  657. runSleepingContainer(c, "--net=none", "--name=onnonenetwork")
  658. // Filter docker ps on non existing network
  659. out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist")
  660. containerOut := strings.TrimSpace(string(out))
  661. lines := strings.Split(containerOut, "\n")
  662. // skip header
  663. lines = lines[1:]
  664. // ps output should have no containers
  665. c.Assert(lines, checker.HasLen, 0)
  666. // Filter docker ps on network bridge
  667. out, _ = dockerCmd(c, "ps", "--filter", "network=bridge")
  668. containerOut = strings.TrimSpace(string(out))
  669. lines = strings.Split(containerOut, "\n")
  670. // skip header
  671. lines = lines[1:]
  672. // ps output should have only one container
  673. c.Assert(lines, checker.HasLen, 1)
  674. // Making sure onbridgenetwork is on the output
  675. c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
  676. // Filter docker ps on networks bridge and none
  677. out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none")
  678. containerOut = strings.TrimSpace(string(out))
  679. lines = strings.Split(containerOut, "\n")
  680. // skip header
  681. lines = lines[1:]
  682. //ps output should have both the containers
  683. c.Assert(lines, checker.HasLen, 2)
  684. // Making sure onbridgenetwork and onnonenetwork is on the output
  685. c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n"))
  686. c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n"))
  687. nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge")
  688. // Filter by network ID
  689. out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID)
  690. containerOut = strings.TrimSpace(string(out))
  691. c.Assert(containerOut, checker.Contains, "onbridgenetwork")
  692. }