github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration-cli/docker_cli_ps_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/docker/docker/api/types/versions"
    11  	"github.com/docker/docker/integration-cli/checker"
    12  	"github.com/docker/docker/integration-cli/cli"
    13  	"github.com/docker/docker/integration-cli/cli/build"
    14  	"github.com/docker/docker/pkg/stringid"
    15  	"github.com/go-check/check"
    16  	"gotest.tools/icmd"
    17  )
    18  
    19  func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
    20  	existingContainers := ExistingContainerIDs(c)
    21  
    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(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))
    47  
    48  	// running
    49  	out, _ = dockerCmd(c, "ps")
    50  	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))
    51  
    52  	// limit
    53  	out, _ = dockerCmd(c, "ps", "-n=2", "-a")
    54  	expected := []string{fourthID, thirdID}
    55  	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))
    56  
    57  	out, _ = dockerCmd(c, "ps", "-n=2")
    58  	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(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))
    90  
    91  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
    92  	expected = []string{secondID}
    93  	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))
    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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(RemoveOutputForExistingElements(out, existingContainers), 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(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))
   116  
   117  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
   118  	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))
   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  func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
   141  	// Problematic on Windows as it doesn't report the size correctly @swernli
   142  	testRequires(c, DaemonIsLinux)
   143  	dockerCmd(c, "run", "-d", "busybox")
   144  
   145  	baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
   146  	baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
   147  	baseSizeIndex := strings.Index(baseLines[0], "SIZE")
   148  	baseFoundsize := baseLines[1][baseSizeIndex:]
   149  	baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, "B")[0])
   150  	c.Assert(err, checker.IsNil)
   151  
   152  	name := "test_size"
   153  	dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
   154  	id := getIDByName(c, name)
   155  
   156  	var result *icmd.Result
   157  
   158  	wait := make(chan struct{})
   159  	go func() {
   160  		result = icmd.RunCommand(dockerBinary, "ps", "-s", "-n=1")
   161  		close(wait)
   162  	}()
   163  	select {
   164  	case <-wait:
   165  	case <-time.After(3 * time.Second):
   166  		c.Fatalf("Calling \"docker ps -s\" timed out!")
   167  	}
   168  	result.Assert(c, icmd.Success)
   169  	lines := strings.Split(strings.Trim(result.Combined(), "\n "), "\n")
   170  	c.Assert(lines, checker.HasLen, 2, check.Commentf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines)))
   171  	sizeIndex := strings.Index(lines[0], "SIZE")
   172  	idIndex := strings.Index(lines[0], "CONTAINER ID")
   173  	foundID := lines[1][idIndex : idIndex+12]
   174  	c.Assert(foundID, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s", id[:12], foundID))
   175  	expectedSize := fmt.Sprintf("%dB", 2+baseBytes)
   176  	foundSize := lines[1][sizeIndex:]
   177  	c.Assert(foundSize, checker.Contains, expectedSize, check.Commentf("Expected size %q, got %q", expectedSize, foundSize))
   178  }
   179  
   180  func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
   181  	existingContainers := ExistingContainerIDs(c)
   182  
   183  	// start exited container
   184  	out := cli.DockerCmd(c, "run", "-d", "busybox").Combined()
   185  	firstID := strings.TrimSpace(out)
   186  
   187  	// make sure the exited container is not running
   188  	cli.DockerCmd(c, "wait", firstID)
   189  
   190  	// start running container
   191  	out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
   192  	secondID := strings.TrimSpace(out)
   193  
   194  	// filter containers by exited
   195  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited").Combined()
   196  	containerOut := strings.TrimSpace(out)
   197  	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, firstID)
   198  
   199  	out = cli.DockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running").Combined()
   200  	containerOut = strings.TrimSpace(out)
   201  	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, secondID)
   202  
   203  	result := cli.Docker(cli.Args("ps", "-a", "-q", "--filter=status=rubbish"), cli.WithTimeout(time.Second*60))
   204  	err := "Invalid filter 'status=rubbish'"
   205  	if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") {
   206  		err = "Unrecognised filter value for status: rubbish"
   207  	}
   208  	result.Assert(c, icmd.Expected{
   209  		ExitCode: 1,
   210  		Err:      err,
   211  	})
   212  	// Windows doesn't support pausing of containers
   213  	if testEnv.OSType != "windows" {
   214  		// pause running container
   215  		out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined()
   216  		pausedID := strings.TrimSpace(out)
   217  		cli.DockerCmd(c, "pause", pausedID)
   218  		// make sure the container is unpaused to let the daemon stop it properly
   219  		defer func() { cli.DockerCmd(c, "unpause", pausedID) }()
   220  
   221  		out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused").Combined()
   222  		containerOut = strings.TrimSpace(out)
   223  		c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, pausedID)
   224  	}
   225  }
   226  
   227  func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
   228  	existingContainers := ExistingContainerIDs(c)
   229  	// Test legacy no health check
   230  	out := runSleepingContainer(c, "--name=none_legacy")
   231  	containerID := strings.TrimSpace(out)
   232  
   233  	cli.WaitRun(c, containerID)
   234  
   235  	out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
   236  	containerOut := strings.TrimSpace(out)
   237  	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for legacy none filter, output: %q", containerID, containerOut, out))
   238  
   239  	// Test no health check specified explicitly
   240  	out = runSleepingContainer(c, "--name=none", "--no-healthcheck")
   241  	containerID = strings.TrimSpace(out)
   242  
   243  	cli.WaitRun(c, containerID)
   244  
   245  	out = cli.DockerCmd(c, "ps", "-q", "-l", "--no-trunc", "--filter=health=none").Combined()
   246  	containerOut = strings.TrimSpace(out)
   247  	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected id %s, got %s for none filter, output: %q", containerID, containerOut, out))
   248  
   249  	// Test failing health check
   250  	out = runSleepingContainer(c, "--name=failing_container", "--health-cmd=exit 1", "--health-interval=1s")
   251  	containerID = strings.TrimSpace(out)
   252  
   253  	waitForHealthStatus(c, "failing_container", "starting", "unhealthy")
   254  
   255  	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=unhealthy").Combined()
   256  	containerOut = strings.TrimSpace(out)
   257  	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for unhealthy filter, output: %q", containerID, containerOut, out))
   258  
   259  	// Check passing healthcheck
   260  	out = runSleepingContainer(c, "--name=passing_container", "--health-cmd=exit 0", "--health-interval=1s")
   261  	containerID = strings.TrimSpace(out)
   262  
   263  	waitForHealthStatus(c, "passing_container", "starting", "healthy")
   264  
   265  	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined()
   266  	containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers))
   267  	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out))
   268  }
   269  
   270  func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
   271  	// start container
   272  	out, _ := dockerCmd(c, "run", "-d", "busybox")
   273  	firstID := strings.TrimSpace(out)
   274  
   275  	// start another container
   276  	runSleepingContainer(c)
   277  
   278  	// filter containers by id
   279  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
   280  	containerOut := strings.TrimSpace(out)
   281  	c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
   282  }
   283  
   284  func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
   285  	// start container
   286  	dockerCmd(c, "run", "--name=a_name_to_match", "busybox")
   287  	id := getIDByName(c, "a_name_to_match")
   288  
   289  	// start another container
   290  	runSleepingContainer(c, "--name=b_name_to_match")
   291  
   292  	// filter containers by name
   293  	out, _ := dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
   294  	containerOut := strings.TrimSpace(out)
   295  	c.Assert(containerOut, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", id[:12], containerOut, out))
   296  }
   297  
   298  // Test for the ancestor filter for ps.
   299  // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
   300  //
   301  // What the test setups :
   302  // - Create 2 image based on busybox using the same repository but different tags
   303  // - Create an image based on the previous image (images_ps_filter_test2)
   304  // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
   305  // - Filter them out :P
   306  func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
   307  	existingContainers := ExistingContainerIDs(c)
   308  
   309  	// Build images
   310  	imageName1 := "images_ps_filter_test1"
   311  	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
   312  		 LABEL match me 1`))
   313  	imageID1 := getIDByName(c, imageName1)
   314  
   315  	imageName1Tagged := "images_ps_filter_test1:tag"
   316  	buildImageSuccessfully(c, imageName1Tagged, build.WithDockerfile(`FROM busybox
   317  		 LABEL match me 1 tagged`))
   318  	imageID1Tagged := getIDByName(c, imageName1Tagged)
   319  
   320  	imageName2 := "images_ps_filter_test2"
   321  	buildImageSuccessfully(c, imageName2, build.WithDockerfile(fmt.Sprintf(`FROM %s
   322  		 LABEL match me 2`, imageName1)))
   323  	imageID2 := getIDByName(c, imageName2)
   324  
   325  	// start containers
   326  	dockerCmd(c, "run", "--name=first", "busybox", "echo", "hello")
   327  	firstID := getIDByName(c, "first")
   328  
   329  	// start another container
   330  	dockerCmd(c, "run", "--name=second", "busybox", "echo", "hello")
   331  	secondID := getIDByName(c, "second")
   332  
   333  	// start third container
   334  	dockerCmd(c, "run", "--name=third", imageName1, "echo", "hello")
   335  	thirdID := getIDByName(c, "third")
   336  
   337  	// start fourth container
   338  	dockerCmd(c, "run", "--name=fourth", imageName1Tagged, "echo", "hello")
   339  	fourthID := getIDByName(c, "fourth")
   340  
   341  	// start fifth container
   342  	dockerCmd(c, "run", "--name=fifth", imageName2, "echo", "hello")
   343  	fifthID := getIDByName(c, "fifth")
   344  
   345  	var filterTestSuite = []struct {
   346  		filterName  string
   347  		expectedIDs []string
   348  	}{
   349  		// non existent stuff
   350  		{"nonexistent", []string{}},
   351  		{"nonexistent:tag", []string{}},
   352  		// image
   353  		{"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
   354  		{imageName1, []string{thirdID, fifthID}},
   355  		{imageName2, []string{fifthID}},
   356  		// image:tag
   357  		{fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
   358  		{imageName1Tagged, []string{fourthID}},
   359  		// short-id
   360  		{stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
   361  		{stringid.TruncateID(imageID2), []string{fifthID}},
   362  		// full-id
   363  		{imageID1, []string{thirdID, fifthID}},
   364  		{imageID1Tagged, []string{fourthID}},
   365  		{imageID2, []string{fifthID}},
   366  	}
   367  
   368  	var out string
   369  	for _, filter := range filterTestSuite {
   370  		out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
   371  		checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs)
   372  	}
   373  
   374  	// Multiple ancestor filter
   375  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
   376  	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
   377  }
   378  
   379  func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
   380  	var actualIDs []string
   381  	if out != "" {
   382  		actualIDs = strings.Split(out[:len(out)-1], "\n")
   383  	}
   384  	sort.Strings(actualIDs)
   385  	sort.Strings(expectedIDs)
   386  
   387  	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))
   388  	if len(expectedIDs) > 0 {
   389  		same := true
   390  		for i := range expectedIDs {
   391  			if actualIDs[i] != expectedIDs[i] {
   392  				c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
   393  				same = false
   394  				break
   395  			}
   396  		}
   397  		c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
   398  	}
   399  }
   400  
   401  func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
   402  	// start container
   403  	dockerCmd(c, "run", "--name=first", "-l", "match=me", "-l", "second=tag", "busybox")
   404  	firstID := getIDByName(c, "first")
   405  
   406  	// start another container
   407  	dockerCmd(c, "run", "--name=second", "-l", "match=me too", "busybox")
   408  	secondID := getIDByName(c, "second")
   409  
   410  	// start third container
   411  	dockerCmd(c, "run", "--name=third", "-l", "nomatch=me", "busybox")
   412  	thirdID := getIDByName(c, "third")
   413  
   414  	// filter containers by exact match
   415  	out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
   416  	containerOut := strings.TrimSpace(out)
   417  	c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   418  
   419  	// filter containers by two labels
   420  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
   421  	containerOut = strings.TrimSpace(out)
   422  	c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   423  
   424  	// filter containers by two labels, but expect not found because of AND behavior
   425  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
   426  	containerOut = strings.TrimSpace(out)
   427  	c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
   428  
   429  	// filter containers by exact key
   430  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
   431  	containerOut = strings.TrimSpace(out)
   432  	c.Assert(containerOut, checker.Contains, firstID)
   433  	c.Assert(containerOut, checker.Contains, secondID)
   434  	c.Assert(containerOut, checker.Not(checker.Contains), thirdID)
   435  }
   436  
   437  func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
   438  	runSleepingContainer(c, "--name=sleep")
   439  
   440  	dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
   441  	firstZero := getIDByName(c, "zero1")
   442  
   443  	dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
   444  	secondZero := getIDByName(c, "zero2")
   445  
   446  	out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
   447  	c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
   448  
   449  	firstNonZero := getIDByName(c, "nonzero1")
   450  
   451  	out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
   452  	c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
   453  	secondNonZero := getIDByName(c, "nonzero2")
   454  
   455  	// filter containers by exited=0
   456  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
   457  	ids := strings.Split(strings.TrimSpace(out), "\n")
   458  	c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out))
   459  	c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0]))
   460  	c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1]))
   461  
   462  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
   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", len(ids)))
   465  	c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0]))
   466  	c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1]))
   467  
   468  }
   469  
   470  func (s *DockerSuite) TestPsRightTagName(c *check.C) {
   471  	// TODO Investigate further why this fails on Windows to Windows CI
   472  	testRequires(c, DaemonIsLinux)
   473  
   474  	existingContainers := ExistingContainerNames(c)
   475  
   476  	tag := "asybox:shmatest"
   477  	dockerCmd(c, "tag", "busybox", tag)
   478  
   479  	var id1 string
   480  	out := runSleepingContainer(c)
   481  	id1 = strings.TrimSpace(string(out))
   482  
   483  	var id2 string
   484  	out = runSleepingContainerInImage(c, tag)
   485  	id2 = strings.TrimSpace(string(out))
   486  
   487  	var imageID string
   488  	out = inspectField(c, "busybox", "Id")
   489  	imageID = strings.TrimSpace(string(out))
   490  
   491  	var id3 string
   492  	out = runSleepingContainerInImage(c, imageID)
   493  	id3 = strings.TrimSpace(string(out))
   494  
   495  	out, _ = dockerCmd(c, "ps", "--no-trunc")
   496  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   497  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   498  	// skip header
   499  	lines = lines[1:]
   500  	c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines)))
   501  	for _, line := range lines {
   502  		f := strings.Fields(line)
   503  		switch f[0] {
   504  		case id1:
   505  			c.Assert(f[1], checker.Equals, "busybox", check.Commentf("Expected %s tag for id %s, got %s", "busybox", id1, f[1]))
   506  		case id2:
   507  			c.Assert(f[1], checker.Equals, tag, check.Commentf("Expected %s tag for id %s, got %s", tag, id2, f[1]))
   508  		case id3:
   509  			c.Assert(f[1], checker.Equals, imageID, check.Commentf("Expected %s imageID for id %s, got %s", tag, id3, f[1]))
   510  		default:
   511  			c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
   512  		}
   513  	}
   514  }
   515  
   516  func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
   517  	// create a container
   518  	out, _ := dockerCmd(c, "create", "busybox")
   519  	cID := strings.TrimSpace(out)
   520  	shortCID := cID[:12]
   521  
   522  	// Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
   523  	out, _ = dockerCmd(c, "ps", "-q")
   524  	c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out))
   525  
   526  	// Make sure it DOES show up as 'Created' for 'ps -a'
   527  	out, _ = dockerCmd(c, "ps", "-a")
   528  
   529  	hits := 0
   530  	for _, line := range strings.Split(out, "\n") {
   531  		if !strings.Contains(line, shortCID) {
   532  			continue
   533  		}
   534  		hits++
   535  		c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line))
   536  	}
   537  
   538  	c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
   539  
   540  	// filter containers by 'create' - note, no -a needed
   541  	out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
   542  	containerOut := strings.TrimSpace(out)
   543  	c.Assert(cID, checker.HasPrefix, containerOut)
   544  }
   545  
   546  // Test for GitHub issue #12595
   547  func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
   548  	// TODO: Investigate why this fails on Windows to Windows CI further.
   549  	testRequires(c, DaemonIsLinux)
   550  	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
   551  	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
   552  
   553  	existingContainers := ExistingContainerIDs(c)
   554  
   555  	icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
   556  
   557  	originalImageID := getIDByName(c, originalImageName)
   558  
   559  	result := icmd.RunCommand(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...)
   560  	result.Assert(c, icmd.Success)
   561  	containerID := strings.TrimSpace(result.Combined())
   562  
   563  	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
   564  	result.Assert(c, icmd.Success)
   565  
   566  	lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
   567  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   568  	// skip header
   569  	lines = lines[1:]
   570  	c.Assert(len(lines), checker.Equals, 1)
   571  
   572  	for _, line := range lines {
   573  		f := strings.Fields(line)
   574  		c.Assert(f[1], checker.Equals, originalImageName)
   575  	}
   576  
   577  	icmd.RunCommand(dockerBinary, "commit", containerID, updatedImageName).Assert(c, icmd.Success)
   578  	icmd.RunCommand(dockerBinary, "tag", updatedImageName, originalImageName).Assert(c, icmd.Success)
   579  
   580  	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
   581  	result.Assert(c, icmd.Success)
   582  
   583  	lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
   584  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   585  	// skip header
   586  	lines = lines[1:]
   587  	c.Assert(len(lines), checker.Equals, 1)
   588  
   589  	for _, line := range lines {
   590  		f := strings.Fields(line)
   591  		c.Assert(f[1], checker.Equals, originalImageID)
   592  	}
   593  
   594  }
   595  
   596  func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
   597  	testRequires(c, DaemonIsLinux)
   598  	dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top")
   599  	c.Assert(waitRun("foo"), checker.IsNil)
   600  	out, _ := dockerCmd(c, "ps")
   601  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   602  	expected := "0.0.0.0:5000->5000/tcp"
   603  	fields := strings.Fields(lines[1])
   604  	c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
   605  
   606  	dockerCmd(c, "kill", "foo")
   607  	dockerCmd(c, "wait", "foo")
   608  	out, _ = dockerCmd(c, "ps", "-l")
   609  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   610  	fields = strings.Fields(lines[1])
   611  	c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
   612  }
   613  
   614  func (s *DockerSuite) TestPsShowMounts(c *check.C) {
   615  	existingContainers := ExistingContainerNames(c)
   616  
   617  	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
   618  
   619  	mp := prefix + slash + "test"
   620  
   621  	dockerCmd(c, "volume", "create", "ps-volume-test")
   622  	// volume mount containers
   623  	runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
   624  	c.Assert(waitRun("volume-test-1"), checker.IsNil)
   625  	runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
   626  	c.Assert(waitRun("volume-test-2"), checker.IsNil)
   627  	// bind mount container
   628  	var bindMountSource string
   629  	var bindMountDestination string
   630  	if DaemonIsWindows() {
   631  		bindMountSource = "c:\\"
   632  		bindMountDestination = "c:\\t"
   633  	} else {
   634  		bindMountSource = "/tmp"
   635  		bindMountDestination = "/t"
   636  	}
   637  	runSleepingContainer(c, "--name=bind-mount-test", "-v", bindMountSource+":"+bindMountDestination)
   638  	c.Assert(waitRun("bind-mount-test"), checker.IsNil)
   639  
   640  	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
   641  
   642  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   643  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   644  	c.Assert(lines, checker.HasLen, 3)
   645  
   646  	fields := strings.Fields(lines[0])
   647  	c.Assert(fields, checker.HasLen, 2)
   648  	c.Assert(fields[0], checker.Equals, "bind-mount-test")
   649  	c.Assert(fields[1], checker.Equals, bindMountSource)
   650  
   651  	fields = strings.Fields(lines[1])
   652  	c.Assert(fields, checker.HasLen, 2)
   653  
   654  	anonymousVolumeID := fields[1]
   655  
   656  	fields = strings.Fields(lines[2])
   657  	c.Assert(fields[1], checker.Equals, "ps-volume-test")
   658  
   659  	// filter by volume name
   660  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
   661  
   662  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   663  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   664  	c.Assert(lines, checker.HasLen, 1)
   665  
   666  	fields = strings.Fields(lines[0])
   667  	c.Assert(fields[1], checker.Equals, "ps-volume-test")
   668  
   669  	// empty results filtering by unknown volume
   670  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist")
   671  	c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
   672  
   673  	// filter by mount destination
   674  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
   675  
   676  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   677  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   678  	c.Assert(lines, checker.HasLen, 2)
   679  
   680  	fields = strings.Fields(lines[0])
   681  	c.Assert(fields[1], checker.Equals, anonymousVolumeID)
   682  	fields = strings.Fields(lines[1])
   683  	c.Assert(fields[1], checker.Equals, "ps-volume-test")
   684  
   685  	// filter by bind mount source
   686  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource)
   687  
   688  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   689  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   690  	c.Assert(lines, checker.HasLen, 1)
   691  
   692  	fields = strings.Fields(lines[0])
   693  	c.Assert(fields, checker.HasLen, 2)
   694  	c.Assert(fields[0], checker.Equals, "bind-mount-test")
   695  	c.Assert(fields[1], checker.Equals, bindMountSource)
   696  
   697  	// filter by bind mount destination
   698  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination)
   699  
   700  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   701  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   702  	c.Assert(lines, checker.HasLen, 1)
   703  
   704  	fields = strings.Fields(lines[0])
   705  	c.Assert(fields, checker.HasLen, 2)
   706  	c.Assert(fields[0], checker.Equals, "bind-mount-test")
   707  	c.Assert(fields[1], checker.Equals, bindMountSource)
   708  
   709  	// empty results filtering by unknown mount point
   710  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted")
   711  	c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
   712  }
   713  
   714  func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
   715  	existing := ExistingContainerIDs(c)
   716  
   717  	// TODO default network on Windows is not called "bridge", and creating a
   718  	// custom network fails on Windows fails with "Error response from daemon: plugin not found")
   719  	testRequires(c, DaemonIsLinux)
   720  
   721  	// create some containers
   722  	runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork")
   723  	runSleepingContainer(c, "--net=none", "--name=onnonenetwork")
   724  
   725  	// Filter docker ps on non existing network
   726  	out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist")
   727  	containerOut := strings.TrimSpace(string(out))
   728  	lines := strings.Split(containerOut, "\n")
   729  
   730  	// skip header
   731  	lines = lines[1:]
   732  
   733  	// ps output should have no containers
   734  	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 0)
   735  
   736  	// Filter docker ps on network bridge
   737  	out, _ = dockerCmd(c, "ps", "--filter", "network=bridge")
   738  	containerOut = strings.TrimSpace(string(out))
   739  
   740  	lines = strings.Split(containerOut, "\n")
   741  
   742  	// skip header
   743  	lines = lines[1:]
   744  
   745  	// ps output should have only one container
   746  	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
   747  
   748  	// Making sure onbridgenetwork is on the output
   749  	c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
   750  
   751  	// Filter docker ps on networks bridge and none
   752  	out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none")
   753  	containerOut = strings.TrimSpace(string(out))
   754  
   755  	lines = strings.Split(containerOut, "\n")
   756  
   757  	// skip header
   758  	lines = lines[1:]
   759  
   760  	//ps output should have both the containers
   761  	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 2)
   762  
   763  	// Making sure onbridgenetwork and onnonenetwork is on the output
   764  	c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n"))
   765  	c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n"))
   766  
   767  	nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge")
   768  
   769  	// Filter by network ID
   770  	out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID)
   771  	containerOut = strings.TrimSpace(string(out))
   772  
   773  	c.Assert(containerOut, checker.Contains, "onbridgenetwork")
   774  
   775  	// Filter by partial network ID
   776  	partialnwID := string(nwID[0:4])
   777  
   778  	out, _ = dockerCmd(c, "ps", "--filter", "network="+partialnwID)
   779  	containerOut = strings.TrimSpace(string(out))
   780  
   781  	lines = strings.Split(containerOut, "\n")
   782  
   783  	// skip header
   784  	lines = lines[1:]
   785  
   786  	// ps output should have only one container
   787  	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
   788  
   789  	// Making sure onbridgenetwork is on the output
   790  	c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
   791  
   792  }
   793  
   794  func (s *DockerSuite) TestPsByOrder(c *check.C) {
   795  	out := runSleepingContainer(c, "--name", "xyz-abc")
   796  	container1 := strings.TrimSpace(out)
   797  
   798  	out = runSleepingContainer(c, "--name", "xyz-123")
   799  	container2 := strings.TrimSpace(out)
   800  
   801  	runSleepingContainer(c, "--name", "789-abc")
   802  	runSleepingContainer(c, "--name", "789-123")
   803  
   804  	// Run multiple time should have the same result
   805  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
   806  	c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1))
   807  
   808  	// Run multiple time should have the same result
   809  	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "-f", "name=xyz").Combined()
   810  	c.Assert(strings.TrimSpace(out), checker.Equals, fmt.Sprintf("%s\n%s", container2, container1))
   811  }
   812  
   813  func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
   814  	testRequires(c, DaemonIsLinux)
   815  	existingContainers := ExistingContainerIDs(c)
   816  
   817  	out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top")
   818  	id1 := strings.TrimSpace(out)
   819  
   820  	out, _ = dockerCmd(c, "run", "-d", "--expose=8080", "busybox", "top")
   821  	id2 := strings.TrimSpace(out)
   822  
   823  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q")
   824  	c.Assert(strings.TrimSpace(out), checker.Contains, id1)
   825  	c.Assert(strings.TrimSpace(out), checker.Contains, id2)
   826  
   827  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-8080/udp")
   828  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
   829  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
   830  
   831  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8081")
   832  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
   833  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
   834  
   835  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "publish=80-81")
   836  	c.Assert(strings.TrimSpace(out), checker.Equals, id1)
   837  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
   838  
   839  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=80/tcp")
   840  	c.Assert(strings.TrimSpace(out), checker.Equals, id1)
   841  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
   842  
   843  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp")
   844  	out = RemoveOutputForExistingElements(out, existingContainers)
   845  	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
   846  	c.Assert(strings.TrimSpace(out), checker.Equals, id2)
   847  }
   848  
   849  func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
   850  	testRequires(c, DaemonIsLinux, MinimumAPIVersion("1.31"))
   851  	existingContainers := ExistingContainerNames(c)
   852  
   853  	dockerCmd(c, "create", "--name=aaa", "busybox", "top")
   854  	dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top")
   855  
   856  	out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
   857  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   858  	lines = RemoveLinesForExistingElements(lines, existingContainers)
   859  	expected := []string{"bbb", "aaa,bbb/aaa"}
   860  	var names []string
   861  	names = append(names, lines...)
   862  	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names))
   863  
   864  	dockerCmd(c, "rm", "bbb")
   865  
   866  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
   867  	out = RemoveOutputForExistingElements(out, existingContainers)
   868  	c.Assert(strings.TrimSpace(out), checker.Equals, "aaa")
   869  }