docker_cli_ps_test.go 35 KB

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