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