docker_cli_ps_test.go 36 KB

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