docker_cli_ps_test.go 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. package main
  2. import (
  3. "fmt"
  4. "sort"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/docker/docker/integration-cli/checker"
  9. "github.com/docker/docker/integration-cli/cli"
  10. "github.com/docker/docker/integration-cli/cli/build"
  11. "github.com/docker/docker/pkg/stringid"
  12. "github.com/go-check/check"
  13. "github.com/gotestyourself/gotestyourself/icmd"
  14. )
  15. func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
  16. existingContainers := ExistingContainerIDs(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(RemoveOutputForExistingElements(out, existingContainers), []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(RemoveOutputForExistingElements(out, existingContainers), []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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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) TestPsListContainersSize(c *check.C) {
  105. // Problematic on Windows as it doesn't report the size correctly @swernli
  106. testRequires(c, DaemonIsLinux)
  107. dockerCmd(c, "run", "-d", "busybox")
  108. baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
  109. baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
  110. baseSizeIndex := strings.Index(baseLines[0], "SIZE")
  111. baseFoundsize := baseLines[1][baseSizeIndex:]
  112. baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, "B")[0])
  113. c.Assert(err, checker.IsNil)
  114. name := "test_size"
  115. dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
  116. id := getIDByName(c, name)
  117. var result *icmd.Result
  118. wait := make(chan struct{})
  119. go func() {
  120. result = icmd.RunCommand(dockerBinary, "ps", "-s", "-n=1")
  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. result.Assert(c, icmd.Success)
  129. lines := strings.Split(strings.Trim(result.Combined(), "\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("%dB", (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. existingContainers := ExistingContainerIDs(c)
  141. // start exited container
  142. out := cli.DockerCmd(c, "run", "-d", "busybox").Combined()
  143. firstID := strings.TrimSpace(out)
  144. // make sure the exited container is not running
  145. cli.DockerCmd(c, "wait", firstID)
  146. // start running container
  147. out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
  148. secondID := strings.TrimSpace(out)
  149. // filter containers by exited
  150. out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited").Combined()
  151. containerOut := strings.TrimSpace(out)
  152. c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, firstID)
  153. out = cli.DockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running").Combined()
  154. containerOut = strings.TrimSpace(out)
  155. c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, secondID)
  156. result := cli.Docker(cli.Args("ps", "-a", "-q", "--filter=status=rubbish"), cli.WithTimeout(time.Second*60))
  157. result.Assert(c, icmd.Expected{
  158. ExitCode: 1,
  159. Err: "Invalid filter 'status=rubbish'",
  160. })
  161. // Windows doesn't support pausing of containers
  162. if testEnv.OSType != "windows" {
  163. // pause running container
  164. out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
  165. pausedID := strings.TrimSpace(out)
  166. cli.DockerCmd(c, "pause", pausedID)
  167. // make sure the container is unpaused to let the daemon stop it properly
  168. defer func() { cli.DockerCmd(c, "unpause", pausedID) }()
  169. out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused").Combined()
  170. containerOut = strings.TrimSpace(out)
  171. c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, pausedID)
  172. }
  173. }
  174. func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
  175. existingContainers := ExistingContainerIDs(c)
  176. // Test legacy no health check
  177. out := runSleepingContainer(c, "--name=none_legacy")
  178. containerID := strings.TrimSpace(out)
  179. cli.WaitRun(c, containerID)
  180. out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
  181. containerOut := strings.TrimSpace(out)
  182. c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for legacy none filter, output: %q", containerID, containerOut, out))
  183. // Test no health check specified explicitly
  184. out = runSleepingContainer(c, "--name=none", "--no-healthcheck")
  185. containerID = strings.TrimSpace(out)
  186. cli.WaitRun(c, containerID)
  187. out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
  188. containerOut = strings.TrimSpace(out)
  189. c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for none filter, output: %q", containerID, containerOut, out))
  190. // Test failing health check
  191. out = runSleepingContainer(c, "--name=failing_container", "--health-cmd=exit 1", "--health-interval=1s")
  192. containerID = strings.TrimSpace(out)
  193. waitForHealthStatus(c, "failing_container", "starting", "unhealthy")
  194. out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=unhealthy").Combined()
  195. containerOut = strings.TrimSpace(out)
  196. c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for unhealthy filter, output: %q", containerID, containerOut, out))
  197. // Check passing healthcheck
  198. out = runSleepingContainer(c, "--name=passing_container", "--health-cmd=exit 0", "--health-interval=1s")
  199. containerID = strings.TrimSpace(out)
  200. waitForHealthStatus(c, "passing_container", "starting", "healthy")
  201. out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined()
  202. containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers))
  203. c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out))
  204. }
  205. func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
  206. // start container
  207. out, _ := dockerCmd(c, "run", "-d", "busybox")
  208. firstID := strings.TrimSpace(out)
  209. // start another container
  210. runSleepingContainer(c)
  211. // filter containers by id
  212. out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
  213. containerOut := strings.TrimSpace(out)
  214. c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
  215. }
  216. func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
  217. // start container
  218. dockerCmd(c, "run", "--name=a_name_to_match", "busybox")
  219. id := getIDByName(c, "a_name_to_match")
  220. // start another container
  221. runSleepingContainer(c, "--name=b_name_to_match")
  222. // filter containers by name
  223. out, _ := dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
  224. containerOut := strings.TrimSpace(out)
  225. c.Assert(containerOut, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", id[:12], containerOut, out))
  226. }
  227. // Test for the ancestor filter for ps.
  228. // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
  229. //
  230. // What the test setups :
  231. // - Create 2 image based on busybox using the same repository but different tags
  232. // - Create an image based on the previous image (images_ps_filter_test2)
  233. // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
  234. // - Filter them out :P
  235. func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
  236. existingContainers := ExistingContainerIDs(c)
  237. // Build images
  238. imageName1 := "images_ps_filter_test1"
  239. buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
  240. LABEL match me 1`))
  241. imageID1 := getIDByName(c, imageName1)
  242. imageName1Tagged := "images_ps_filter_test1:tag"
  243. buildImageSuccessfully(c, imageName1Tagged, build.WithDockerfile(`FROM busybox
  244. LABEL match me 1 tagged`))
  245. imageID1Tagged := getIDByName(c, imageName1Tagged)
  246. imageName2 := "images_ps_filter_test2"
  247. buildImageSuccessfully(c, imageName2, build.WithDockerfile(fmt.Sprintf(`FROM %s
  248. LABEL match me 2`, imageName1)))
  249. imageID2 := getIDByName(c, imageName2)
  250. // start containers
  251. dockerCmd(c, "run", "--name=first", "busybox", "echo", "hello")
  252. firstID := getIDByName(c, "first")
  253. // start another container
  254. dockerCmd(c, "run", "--name=second", "busybox", "echo", "hello")
  255. secondID := getIDByName(c, "second")
  256. // start third container
  257. dockerCmd(c, "run", "--name=third", imageName1, "echo", "hello")
  258. thirdID := getIDByName(c, "third")
  259. // start fourth container
  260. dockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello")
  261. fourthID := getIDByName(c, "fourth")
  262. // start fifth container
  263. dockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello")
  264. fifthID := getIDByName(c, "fifth")
  265. var filterTestSuite = []struct {
  266. filterName string
  267. expectedIDs []string
  268. }{
  269. // non existent stuff
  270. {"nonexistent", []string{}},
  271. {"nonexistent:tag", []string{}},
  272. // image
  273. {"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
  274. {imageName1, []string{thirdID, fifthID}},
  275. {imageName2, []string{fifthID}},
  276. // image:tag
  277. {fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
  278. {imageName1Tagged, []string{fourthID}},
  279. // short-id
  280. {stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
  281. {stringid.TruncateID(imageID2), []string{fifthID}},
  282. // full-id
  283. {imageID1, []string{thirdID, fifthID}},
  284. {imageID1Tagged, []string{fourthID}},
  285. {imageID2, []string{fifthID}},
  286. }
  287. var out string
  288. for _, filter := range filterTestSuite {
  289. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
  290. checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs)
  291. }
  292. // Multiple ancestor filter
  293. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
  294. checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
  295. }
  296. func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
  297. actualIDs := []string{}
  298. if out != "" {
  299. actualIDs = strings.Split(out[:len(out)-1], "\n")
  300. }
  301. sort.Strings(actualIDs)
  302. sort.Strings(expectedIDs)
  303. 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))
  304. if len(expectedIDs) > 0 {
  305. same := true
  306. for i := range expectedIDs {
  307. if actualIDs[i] != expectedIDs[i] {
  308. c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
  309. same = false
  310. break
  311. }
  312. }
  313. c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
  314. }
  315. }
  316. func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
  317. // start container
  318. dockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox")
  319. firstID := getIDByName(c, "first")
  320. // start another container
  321. dockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox")
  322. secondID := getIDByName(c, "second")
  323. // start third container
  324. dockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox")
  325. thirdID := getIDByName(c, "third")
  326. // filter containers by exact match
  327. out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
  328. containerOut := strings.TrimSpace(out)
  329. c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
  330. // filter containers by two labels
  331. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
  332. containerOut = strings.TrimSpace(out)
  333. c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
  334. // filter containers by two labels, but expect not found because of AND behavior
  335. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
  336. containerOut = strings.TrimSpace(out)
  337. c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
  338. // filter containers by exact key
  339. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
  340. containerOut = strings.TrimSpace(out)
  341. c.Assert(containerOut, checker.Contains, firstID)
  342. c.Assert(containerOut, checker.Contains, secondID)
  343. c.Assert(containerOut, checker.Not(checker.Contains), thirdID)
  344. }
  345. func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
  346. runSleepingContainer(c, "--name=sleep")
  347. dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
  348. firstZero := getIDByName(c, "zero1")
  349. dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
  350. secondZero := getIDByName(c, "zero2")
  351. out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
  352. c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
  353. firstNonZero := getIDByName(c, "nonzero1")
  354. out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
  355. c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
  356. secondNonZero := getIDByName(c, "nonzero2")
  357. // filter containers by exited=0
  358. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
  359. ids := strings.Split(strings.TrimSpace(out), "\n")
  360. c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out))
  361. c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0]))
  362. c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1]))
  363. out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
  364. ids = strings.Split(strings.TrimSpace(out), "\n")
  365. c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d", len(ids)))
  366. c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0]))
  367. c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1]))
  368. }
  369. func (s *DockerSuite) TestPsRightTagName(c *check.C) {
  370. // TODO Investigate further why this fails on Windows to Windows CI
  371. testRequires(c, DaemonIsLinux)
  372. existingContainers := ExistingContainerNames(c)
  373. tag := "asybox:shmatest"
  374. dockerCmd(c, "tag", "busybox", tag)
  375. var id1 string
  376. out := runSleepingContainer(c)
  377. id1 = strings.TrimSpace(string(out))
  378. var id2 string
  379. out = runSleepingContainerInImage(c, tag)
  380. id2 = strings.TrimSpace(string(out))
  381. var imageID string
  382. out = inspectField(c, "busybox", "Id")
  383. imageID = strings.TrimSpace(string(out))
  384. var id3 string
  385. out = runSleepingContainerInImage(c, imageID)
  386. id3 = strings.TrimSpace(string(out))
  387. out, _ = dockerCmd(c, "ps", "--no-trunc")
  388. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  389. lines = RemoveLinesForExistingElements(lines, existingContainers)
  390. // skip header
  391. lines = lines[1:]
  392. c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines)))
  393. for _, line := range lines {
  394. f := strings.Fields(line)
  395. switch f[0] {
  396. case id1:
  397. c.Assert(f[1], checker.Equals, "busybox", check.Commentf("Expected %s tag for id %s, got %s", "busybox", id1, f[1]))
  398. case id2:
  399. c.Assert(f[1], checker.Equals, tag, check.Commentf("Expected %s tag for id %s, got %s", tag, id2, f[1]))
  400. case id3:
  401. c.Assert(f[1], checker.Equals, imageID, check.Commentf("Expected %s imageID for id %s, got %s", tag, id3, f[1]))
  402. default:
  403. c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
  404. }
  405. }
  406. }
  407. func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
  408. // create a container
  409. out, _ := dockerCmd(c, "create", "busybox")
  410. cID := strings.TrimSpace(out)
  411. shortCID := cID[:12]
  412. // Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
  413. out, _ = dockerCmd(c, "ps", "-q")
  414. c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out))
  415. // Make sure it DOES show up as 'Created' for 'ps -a'
  416. out, _ = dockerCmd(c, "ps", "-a")
  417. hits := 0
  418. for _, line := range strings.Split(out, "\n") {
  419. if !strings.Contains(line, shortCID) {
  420. continue
  421. }
  422. hits++
  423. c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line))
  424. }
  425. c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
  426. // filter containers by 'create' - note, no -a needed
  427. out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
  428. containerOut := strings.TrimSpace(out)
  429. c.Assert(cID, checker.HasPrefix, containerOut)
  430. }
  431. // Test for GitHub issue #12595
  432. func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
  433. // TODO: Investigate why this fails on Windows to Windows CI further.
  434. testRequires(c, DaemonIsLinux)
  435. originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
  436. updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
  437. existingContainers := ExistingContainerIDs(c)
  438. icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
  439. originalImageID := getIDByName(c, originalImageName)
  440. result := icmd.RunCommand(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...)
  441. result.Assert(c, icmd.Success)
  442. containerID := strings.TrimSpace(result.Combined())
  443. result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
  444. result.Assert(c, icmd.Success)
  445. lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
  446. lines = RemoveLinesForExistingElements(lines, existingContainers)
  447. // skip header
  448. lines = lines[1:]
  449. c.Assert(len(lines), checker.Equals, 1)
  450. for _, line := range lines {
  451. f := strings.Fields(line)
  452. c.Assert(f[1], checker.Equals, originalImageName)
  453. }
  454. icmd.RunCommand(dockerBinary, "commit", containerID, updatedImageName).Assert(c, icmd.Success)
  455. icmd.RunCommand(dockerBinary, "tag", updatedImageName, originalImageName).Assert(c, icmd.Success)
  456. result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
  457. result.Assert(c, icmd.Success)
  458. lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
  459. lines = RemoveLinesForExistingElements(lines, existingContainers)
  460. // skip header
  461. lines = lines[1:]
  462. c.Assert(len(lines), checker.Equals, 1)
  463. for _, line := range lines {
  464. f := strings.Fields(line)
  465. c.Assert(f[1], checker.Equals, originalImageID)
  466. }
  467. }
  468. func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
  469. testRequires(c, DaemonIsLinux)
  470. dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top")
  471. c.Assert(waitRun("foo"), checker.IsNil)
  472. out, _ := dockerCmd(c, "ps")
  473. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  474. expected := "0.0.0.0:5000->5000/tcp"
  475. fields := strings.Fields(lines[1])
  476. c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
  477. dockerCmd(c, "kill", "foo")
  478. dockerCmd(c, "wait", "foo")
  479. out, _ = dockerCmd(c, "ps", "-l")
  480. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  481. fields = strings.Fields(lines[1])
  482. c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
  483. }
  484. func (s *DockerSuite) TestPsShowMounts(c *check.C) {
  485. existingContainers := ExistingContainerNames(c)
  486. prefix, slash := getPrefixAndSlashFromDaemonPlatform()
  487. mp := prefix + slash + "test"
  488. dockerCmd(c, "volume", "create", "ps-volume-test")
  489. // volume mount containers
  490. runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
  491. c.Assert(waitRun("volume-test-1"), checker.IsNil)
  492. runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
  493. c.Assert(waitRun("volume-test-2"), checker.IsNil)
  494. // bind mount container
  495. var bindMountSource string
  496. var bindMountDestination string
  497. if DaemonIsWindows() {
  498. bindMountSource = "c:\\"
  499. bindMountDestination = "c:\\t"
  500. } else {
  501. bindMountSource = "/tmp"
  502. bindMountDestination = "/t"
  503. }
  504. runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination)
  505. c.Assert(waitRun("bind-mount-test"), checker.IsNil)
  506. out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
  507. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  508. lines = RemoveLinesForExistingElements(lines, existingContainers)
  509. c.Assert(lines, checker.HasLen, 3)
  510. fields := strings.Fields(lines[0])
  511. c.Assert(fields, checker.HasLen, 2)
  512. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  513. c.Assert(fields[1], checker.Equals, bindMountSource)
  514. fields = strings.Fields(lines[1])
  515. c.Assert(fields, checker.HasLen, 2)
  516. anonymousVolumeID := fields[1]
  517. fields = strings.Fields(lines[2])
  518. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  519. // filter by volume name
  520. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
  521. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  522. lines = RemoveLinesForExistingElements(lines, existingContainers)
  523. c.Assert(lines, checker.HasLen, 1)
  524. fields = strings.Fields(lines[0])
  525. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  526. // empty results filtering by unknown volume
  527. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist")
  528. c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
  529. // filter by mount destination
  530. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
  531. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  532. lines = RemoveLinesForExistingElements(lines, existingContainers)
  533. c.Assert(lines, checker.HasLen, 2)
  534. fields = strings.Fields(lines[0])
  535. c.Assert(fields[1], checker.Equals, anonymousVolumeID)
  536. fields = strings.Fields(lines[1])
  537. c.Assert(fields[1], checker.Equals, "ps-volume-test")
  538. // filter by bind mount source
  539. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource)
  540. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  541. lines = RemoveLinesForExistingElements(lines, existingContainers)
  542. c.Assert(lines, checker.HasLen, 1)
  543. fields = strings.Fields(lines[0])
  544. c.Assert(fields, checker.HasLen, 2)
  545. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  546. c.Assert(fields[1], checker.Equals, bindMountSource)
  547. // filter by bind mount destination
  548. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination)
  549. lines = strings.Split(strings.TrimSpace(string(out)), "\n")
  550. lines = RemoveLinesForExistingElements(lines, existingContainers)
  551. c.Assert(lines, checker.HasLen, 1)
  552. fields = strings.Fields(lines[0])
  553. c.Assert(fields, checker.HasLen, 2)
  554. c.Assert(fields[0], checker.Equals, "bind-mount-test")
  555. c.Assert(fields[1], checker.Equals, bindMountSource)
  556. // empty results filtering by unknown mount point
  557. out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted")
  558. c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
  559. }
  560. func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
  561. existing := ExistingContainerIDs(c)
  562. // TODO default network on Windows is not called "bridge", and creating a
  563. // custom network fails on Windows fails with "Error response from daemon: plugin not found")
  564. testRequires(c, DaemonIsLinux)
  565. // create some containers
  566. runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork")
  567. runSleepingContainer(c, "--net=none", "--name=onnonenetwork")
  568. // Filter docker ps on non existing network
  569. out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist")
  570. containerOut := strings.TrimSpace(string(out))
  571. lines := strings.Split(containerOut, "\n")
  572. // skip header
  573. lines = lines[1:]
  574. // ps output should have no containers
  575. c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 0)
  576. // Filter docker ps on network bridge
  577. out, _ = dockerCmd(c, "ps", "--filter", "network=bridge")
  578. containerOut = strings.TrimSpace(string(out))
  579. lines = strings.Split(containerOut, "\n")
  580. // skip header
  581. lines = lines[1:]
  582. // ps output should have only one container
  583. c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
  584. // Making sure onbridgenetwork is on the output
  585. c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
  586. // Filter docker ps on networks bridge and none
  587. out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none")
  588. containerOut = strings.TrimSpace(string(out))
  589. lines = strings.Split(containerOut, "\n")
  590. // skip header
  591. lines = lines[1:]
  592. //ps output should have both the containers
  593. c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 2)
  594. // Making sure onbridgenetwork and onnonenetwork is on the output
  595. c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n"))
  596. c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n"))
  597. nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge")
  598. // Filter by network ID
  599. out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID)
  600. containerOut = strings.TrimSpace(string(out))
  601. c.Assert(containerOut, checker.Contains, "onbridgenetwork")
  602. // Filter by partial network ID
  603. partialnwID := string(nwID[0:4])
  604. out, _ = dockerCmd(c, "ps", "--filter", "network="+partialnwID)
  605. containerOut = strings.TrimSpace(string(out))
  606. lines = strings.Split(containerOut, "\n")
  607. // skip header
  608. lines = lines[1:]
  609. // ps output should have only one container
  610. c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
  611. // Making sure onbridgenetwork is on the output
  612. c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
  613. }
  614. func (s *DockerSuite) TestPsByOrder(c *check.C) {
  615. name1 := "xyz-abc"
  616. out := runSleepingContainer(c, "--name", name1)
  617. container1 := strings.TrimSpace(out)
  618. name2 := "xyz-123"
  619. out = runSleepingContainer(c, "--name", name2)
  620. container2 := strings.TrimSpace(out)
  621. name3 := "789-abc"
  622. out = runSleepingContainer(c, "--name", name3)
  623. name4 := "789-123"
  624. out = runSleepingContainer(c, "--name", name4)
  625. // Run multiple time should have the same result
  626. out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
  627. c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1))
  628. // Run multiple time should have the same result
  629. out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
  630. c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1))
  631. }
  632. func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
  633. testRequires(c, DaemonIsLinux)
  634. existingContainers := ExistingContainerIDs(c)
  635. out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top")
  636. id1 := strings.TrimSpace(out)
  637. out, _ = dockerCmd(c, "run", "-d", "--expose=8080", "busybox", "top")
  638. id2 := strings.TrimSpace(out)
  639. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q")
  640. c.Assert(strings.TrimSpace(out), checker.Contains, id1)
  641. c.Assert(strings.TrimSpace(out), checker.Contains, id2)
  642. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-8080/udp")
  643. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
  644. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
  645. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8081")
  646. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
  647. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
  648. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-81")
  649. c.Assert(strings.TrimSpace(out), checker.Equals, id1)
  650. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
  651. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=80/tcp")
  652. c.Assert(strings.TrimSpace(out), checker.Equals, id1)
  653. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
  654. out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp")
  655. out = RemoveOutputForExistingElements(out, existingContainers)
  656. c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
  657. c.Assert(strings.TrimSpace(out), checker.Equals, id2)
  658. }
  659. func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
  660. testRequires(c, DaemonIsLinux)
  661. existingContainers := ExistingContainerNames(c)
  662. dockerCmd(c, "create", "--name=aaa", "busybox", "top")
  663. dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top")
  664. out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
  665. lines := strings.Split(strings.TrimSpace(string(out)), "\n")
  666. lines = RemoveLinesForExistingElements(lines, existingContainers)
  667. expected := []string{"bbb", "aaa,bbb/aaa"}
  668. var names []string
  669. names = append(names, lines...)
  670. c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names))
  671. dockerCmd(c, "rm", "bbb")
  672. out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
  673. out = RemoveOutputForExistingElements(out, existingContainers)
  674. c.Assert(strings.TrimSpace(out), checker.Equals, "aaa")
  675. }