github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_ps_test.go (about)

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