docker_cli_ps_test.go 35 KB

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