github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/integration-cli/docker_cli_ps_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"sort"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/docker/docker/pkg/integration/checker"
    15  	"github.com/docker/docker/pkg/stringid"
    16  	"github.com/go-check/check"
    17  )
    18  
    19  func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
    20  	testRequires(c, DaemonIsLinux)
    21  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
    22  	firstID := strings.TrimSpace(out)
    23  
    24  	out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
    25  	secondID := strings.TrimSpace(out)
    26  
    27  	// not long running
    28  	out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
    29  	thirdID := strings.TrimSpace(out)
    30  
    31  	out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
    32  	fourthID := strings.TrimSpace(out)
    33  
    34  	// make sure the second is running
    35  	c.Assert(waitRun(secondID), checker.IsNil)
    36  
    37  	// make sure third one is not running
    38  	dockerCmd(c, "wait", thirdID)
    39  
    40  	// make sure the forth is running
    41  	c.Assert(waitRun(fourthID), checker.IsNil)
    42  
    43  	// all
    44  	out, _ = dockerCmd(c, "ps", "-a")
    45  	c.Assert(assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}), checker.Equals, true, check.Commentf("ALL: Container list is not in the correct order: \n%s", out))
    46  
    47  	// running
    48  	out, _ = dockerCmd(c, "ps")
    49  	c.Assert(assertContainerList(out, []string{fourthID, secondID, firstID}), checker.Equals, true, check.Commentf("RUNNING: Container list is not in the correct order: \n%s", out))
    50  
    51  	// limit
    52  	out, _ = dockerCmd(c, "ps", "-n=2", "-a")
    53  	expected := []string{fourthID, thirdID}
    54  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
    55  
    56  	out, _ = dockerCmd(c, "ps", "-n=2")
    57  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
    58  
    59  	// filter since
    60  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a")
    61  	expected = []string{fourthID, thirdID, secondID}
    62  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
    63  
    64  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID)
    65  	expected = []string{fourthID, secondID}
    66  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
    67  
    68  	// filter before
    69  	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-a")
    70  	expected = []string{thirdID, secondID, firstID}
    71  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
    72  
    73  	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID)
    74  	expected = []string{secondID, firstID}
    75  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out))
    76  
    77  	// filter since & before
    78  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a")
    79  	expected = []string{thirdID, secondID}
    80  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
    81  
    82  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
    83  	expected = []string{secondID}
    84  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter: Container list is not in the correct order: \n%s", out))
    85  
    86  	// filter since & limit
    87  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a")
    88  	expected = []string{fourthID, thirdID}
    89  
    90  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
    91  
    92  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2")
    93  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
    94  
    95  	// filter before & limit
    96  	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a")
    97  	expected = []string{thirdID}
    98  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
    99  
   100  	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1")
   101  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
   102  
   103  	// filter since & filter before & limit
   104  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a")
   105  	expected = []string{thirdID}
   106  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
   107  
   108  	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
   109  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
   110  
   111  }
   112  
   113  // FIXME remove this for 1.12 as --since and --before are deprecated
   114  func (s *DockerSuite) TestPsListContainersDeprecatedSinceAndBefore(c *check.C) {
   115  	out, _ := runSleepingContainer(c, "-d")
   116  	firstID := strings.TrimSpace(out)
   117  
   118  	out, _ = runSleepingContainer(c, "-d")
   119  	secondID := strings.TrimSpace(out)
   120  
   121  	// not long running
   122  	out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
   123  	thirdID := strings.TrimSpace(out)
   124  
   125  	out, _ = runSleepingContainer(c, "-d")
   126  	fourthID := strings.TrimSpace(out)
   127  
   128  	// make sure the second is running
   129  	c.Assert(waitRun(secondID), checker.IsNil)
   130  
   131  	// make sure third one is not running
   132  	dockerCmd(c, "wait", thirdID)
   133  
   134  	// make sure the forth is running
   135  	c.Assert(waitRun(fourthID), checker.IsNil)
   136  
   137  	// since
   138  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "-a")
   139  	expected := []string{fourthID, thirdID, secondID}
   140  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   141  
   142  	out, _ = dockerCmd(c, "ps", "--since="+firstID)
   143  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE: Container list is not in the correct order: %v \n%s", expected, out))
   144  
   145  	// before
   146  	out, _ = dockerCmd(c, "ps", "--before="+thirdID, "-a")
   147  	expected = []string{secondID, firstID}
   148  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   149  
   150  	out, _ = dockerCmd(c, "ps", "--before="+thirdID)
   151  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE: Container list is not in the correct order: %v \n%s", expected, out))
   152  
   153  	// since & before
   154  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "--before="+fourthID, "-a")
   155  	expected = []string{thirdID, secondID}
   156  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   157  
   158  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "--before="+fourthID)
   159  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE: Container list is not in the correct order: %v \n%s", expected, out))
   160  
   161  	// since & limit
   162  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "-n=2", "-a")
   163  	expected = []string{fourthID, thirdID}
   164  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, LIMIT & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   165  
   166  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "-n=2")
   167  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, LIMIT: Container list is not in the correct order: %v \n%s", expected, out))
   168  
   169  	// before & limit
   170  	out, _ = dockerCmd(c, "ps", "--before="+fourthID, "-n=1", "-a")
   171  	expected = []string{thirdID}
   172  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE, LIMIT & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   173  
   174  	out, _ = dockerCmd(c, "ps", "--before="+fourthID, "-n=1")
   175  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE, LIMIT: Container list is not in the correct order: %v \n%s", expected, out))
   176  
   177  	// since & before & limit
   178  	out, _ = dockerCmd(c, "ps", "--since="+firstID, "--before="+fourthID, "-n=1", "-a")
   179  	expected = []string{thirdID}
   180  	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE, LIMIT & ALL: Container list is not in the correct order: %v \n%s", expected, out))
   181  
   182  }
   183  
   184  func assertContainerList(out string, expected []string) bool {
   185  	lines := strings.Split(strings.Trim(out, "\n "), "\n")
   186  	// FIXME remove this for 1.12 as --since and --before are deprecated
   187  	// This is here to remove potential Warning: lines (printed out with deprecated flags)
   188  	for i := 0; i < 2; i++ {
   189  		if strings.Contains(lines[0], "Warning:") {
   190  			lines = lines[1:]
   191  		}
   192  	}
   193  
   194  	if len(lines)-1 != len(expected) {
   195  		return false
   196  	}
   197  
   198  	containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
   199  	for i := 0; i < len(expected); i++ {
   200  		foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
   201  		if foundID != expected[i][:12] {
   202  			return false
   203  		}
   204  	}
   205  
   206  	return true
   207  }
   208  
   209  func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
   210  	testRequires(c, DaemonIsLinux)
   211  	dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
   212  
   213  	baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
   214  	baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
   215  	baseSizeIndex := strings.Index(baseLines[0], "SIZE")
   216  	baseFoundsize := baseLines[1][baseSizeIndex:]
   217  	baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
   218  	c.Assert(err, checker.IsNil)
   219  
   220  	name := "test_size"
   221  	out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
   222  	id, err := getIDByName(name)
   223  	c.Assert(err, checker.IsNil)
   224  
   225  	runCmd := exec.Command(dockerBinary, "ps", "-s", "-n=1")
   226  
   227  	wait := make(chan struct{})
   228  	go func() {
   229  		out, _, err = runCommandWithOutput(runCmd)
   230  		close(wait)
   231  	}()
   232  	select {
   233  	case <-wait:
   234  	case <-time.After(3 * time.Second):
   235  		c.Fatalf("Calling \"docker ps -s\" timed out!")
   236  	}
   237  	c.Assert(err, checker.IsNil)
   238  	lines := strings.Split(strings.Trim(out, "\n "), "\n")
   239  	c.Assert(lines, checker.HasLen, 2, check.Commentf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines)))
   240  	sizeIndex := strings.Index(lines[0], "SIZE")
   241  	idIndex := strings.Index(lines[0], "CONTAINER ID")
   242  	foundID := lines[1][idIndex : idIndex+12]
   243  	c.Assert(foundID, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s", id[:12], foundID))
   244  	expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
   245  	foundSize := lines[1][sizeIndex:]
   246  	c.Assert(foundSize, checker.Contains, expectedSize, check.Commentf("Expected size %q, got %q", expectedSize, foundSize))
   247  
   248  }
   249  
   250  func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
   251  	testRequires(c, DaemonIsLinux)
   252  
   253  	// start exited container
   254  	out, _ := dockerCmd(c, "run", "-d", "busybox")
   255  	firstID := strings.TrimSpace(out)
   256  
   257  	// make sure the exited container is not running
   258  	dockerCmd(c, "wait", firstID)
   259  
   260  	// start running container
   261  	out, _ = dockerCmd(c, "run", "-itd", "busybox")
   262  	secondID := strings.TrimSpace(out)
   263  
   264  	// filter containers by exited
   265  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited")
   266  	containerOut := strings.TrimSpace(out)
   267  	c.Assert(containerOut, checker.Equals, firstID)
   268  
   269  	out, _ = dockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running")
   270  	containerOut = strings.TrimSpace(out)
   271  	c.Assert(containerOut, checker.Equals, secondID)
   272  
   273  	out, _, _ = dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish")
   274  	c.Assert(out, checker.Contains, "Unrecognised filter value for status", check.Commentf("Expected error response due to invalid status filter output: %q", out))
   275  
   276  	// pause running container
   277  	out, _ = dockerCmd(c, "run", "-itd", "busybox")
   278  	pausedID := strings.TrimSpace(out)
   279  	dockerCmd(c, "pause", pausedID)
   280  	// make sure the container is unpaused to let the daemon stop it properly
   281  	defer func() { dockerCmd(c, "unpause", pausedID) }()
   282  
   283  	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused")
   284  	containerOut = strings.TrimSpace(out)
   285  	c.Assert(containerOut, checker.Equals, pausedID)
   286  }
   287  
   288  func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
   289  	testRequires(c, DaemonIsLinux)
   290  	// start container
   291  	out, _ := dockerCmd(c, "run", "-d", "busybox")
   292  	firstID := strings.TrimSpace(out)
   293  
   294  	// start another container
   295  	dockerCmd(c, "run", "-d", "busybox", "top")
   296  
   297  	// filter containers by id
   298  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
   299  	containerOut := strings.TrimSpace(out)
   300  	c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
   301  
   302  }
   303  
   304  func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
   305  	testRequires(c, DaemonIsLinux)
   306  	// start container
   307  	out, _ := dockerCmd(c, "run", "-d", "--name=a_name_to_match", "busybox")
   308  	firstID := strings.TrimSpace(out)
   309  
   310  	// start another container
   311  	dockerCmd(c, "run", "-d", "--name=b_name_to_match", "busybox", "top")
   312  
   313  	// filter containers by name
   314  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
   315  	containerOut := strings.TrimSpace(out)
   316  	c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
   317  
   318  }
   319  
   320  // Test for the ancestor filter for ps.
   321  // There is also the same test but with image:tag@digest in docker_cli_by_digest_test.go
   322  //
   323  // What the test setups :
   324  // - Create 2 image based on busybox using the same repository but different tags
   325  // - Create an image based on the previous image (images_ps_filter_test2)
   326  // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
   327  // - Filter them out :P
   328  func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
   329  	testRequires(c, DaemonIsLinux)
   330  	// Build images
   331  	imageName1 := "images_ps_filter_test1"
   332  	imageID1, err := buildImage(imageName1,
   333  		`FROM busybox
   334  		 LABEL match me 1`, true)
   335  	c.Assert(err, checker.IsNil)
   336  
   337  	imageName1Tagged := "images_ps_filter_test1:tag"
   338  	imageID1Tagged, err := buildImage(imageName1Tagged,
   339  		`FROM busybox
   340  		 LABEL match me 1 tagged`, true)
   341  	c.Assert(err, checker.IsNil)
   342  
   343  	imageName2 := "images_ps_filter_test2"
   344  	imageID2, err := buildImage(imageName2,
   345  		fmt.Sprintf(`FROM %s
   346  		 LABEL match me 2`, imageName1), true)
   347  	c.Assert(err, checker.IsNil)
   348  
   349  	// start containers
   350  	out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
   351  	firstID := strings.TrimSpace(out)
   352  
   353  	// start another container
   354  	out, _ = dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
   355  	secondID := strings.TrimSpace(out)
   356  
   357  	// start third container
   358  	out, _ = dockerCmd(c, "run", "-d", imageName1, "echo", "hello")
   359  	thirdID := strings.TrimSpace(out)
   360  
   361  	// start fourth container
   362  	out, _ = dockerCmd(c, "run", "-d", imageName1Tagged, "echo", "hello")
   363  	fourthID := strings.TrimSpace(out)
   364  
   365  	// start fifth container
   366  	out, _ = dockerCmd(c, "run", "-d", imageName2, "echo", "hello")
   367  	fifthID := strings.TrimSpace(out)
   368  
   369  	var filterTestSuite = []struct {
   370  		filterName  string
   371  		expectedIDs []string
   372  	}{
   373  		// non existent stuff
   374  		{"nonexistent", []string{}},
   375  		{"nonexistent:tag", []string{}},
   376  		// image
   377  		{"busybox", []string{firstID, secondID, thirdID, fourthID, fifthID}},
   378  		{imageName1, []string{thirdID, fifthID}},
   379  		{imageName2, []string{fifthID}},
   380  		// image:tag
   381  		{fmt.Sprintf("%s:latest", imageName1), []string{thirdID, fifthID}},
   382  		{imageName1Tagged, []string{fourthID}},
   383  		// short-id
   384  		{stringid.TruncateID(imageID1), []string{thirdID, fifthID}},
   385  		{stringid.TruncateID(imageID2), []string{fifthID}},
   386  		// full-id
   387  		{imageID1, []string{thirdID, fifthID}},
   388  		{imageID1Tagged, []string{fourthID}},
   389  		{imageID2, []string{fifthID}},
   390  	}
   391  
   392  	for _, filter := range filterTestSuite {
   393  		out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
   394  		checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs)
   395  	}
   396  
   397  	// Multiple ancestor filter
   398  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
   399  	checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
   400  }
   401  
   402  func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
   403  	actualIDs := []string{}
   404  	if out != "" {
   405  		actualIDs = strings.Split(out[:len(out)-1], "\n")
   406  	}
   407  	sort.Strings(actualIDs)
   408  	sort.Strings(expectedIDs)
   409  
   410  	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))
   411  	if len(expectedIDs) > 0 {
   412  		same := true
   413  		for i := range expectedIDs {
   414  			if actualIDs[i] != expectedIDs[i] {
   415  				c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
   416  				same = false
   417  				break
   418  			}
   419  		}
   420  		c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
   421  	}
   422  }
   423  
   424  func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
   425  	testRequires(c, DaemonIsLinux)
   426  	// start container
   427  	out, _ := dockerCmd(c, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
   428  	firstID := strings.TrimSpace(out)
   429  
   430  	// start another container
   431  	out, _ = dockerCmd(c, "run", "-d", "-l", "match=me too", "busybox")
   432  	secondID := strings.TrimSpace(out)
   433  
   434  	// start third container
   435  	out, _ = dockerCmd(c, "run", "-d", "-l", "nomatch=me", "busybox")
   436  	thirdID := strings.TrimSpace(out)
   437  
   438  	// filter containers by exact match
   439  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
   440  	containerOut := strings.TrimSpace(out)
   441  	c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   442  
   443  	// filter containers by two labels
   444  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
   445  	containerOut = strings.TrimSpace(out)
   446  	c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
   447  
   448  	// filter containers by two labels, but expect not found because of AND behavior
   449  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
   450  	containerOut = strings.TrimSpace(out)
   451  	c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
   452  
   453  	// filter containers by exact key
   454  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
   455  	containerOut = strings.TrimSpace(out)
   456  	c.Assert(containerOut, checker.Contains, firstID)
   457  	c.Assert(containerOut, checker.Contains, secondID)
   458  	c.Assert(containerOut, checker.Not(checker.Contains), thirdID)
   459  }
   460  
   461  func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
   462  	testRequires(c, DaemonIsLinux)
   463  	dockerCmd(c, "run", "-d", "--name", "top", "busybox", "top")
   464  
   465  	dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
   466  	firstZero, err := getIDByName("zero1")
   467  	c.Assert(err, checker.IsNil)
   468  
   469  	dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
   470  	secondZero, err := getIDByName("zero2")
   471  	c.Assert(err, checker.IsNil)
   472  
   473  	out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
   474  	c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
   475  
   476  	firstNonZero, err := getIDByName("nonzero1")
   477  	c.Assert(err, checker.IsNil)
   478  
   479  	out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
   480  	c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
   481  	secondNonZero, err := getIDByName("nonzero2")
   482  	c.Assert(err, checker.IsNil)
   483  
   484  	// filter containers by exited=0
   485  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
   486  	ids := strings.Split(strings.TrimSpace(out), "\n")
   487  	c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out))
   488  	c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0]))
   489  	c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1]))
   490  
   491  	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
   492  	ids = strings.Split(strings.TrimSpace(out), "\n")
   493  	c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d", len(ids)))
   494  	c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0]))
   495  	c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1]))
   496  
   497  }
   498  
   499  func (s *DockerSuite) TestPsRightTagName(c *check.C) {
   500  	testRequires(c, DaemonIsLinux)
   501  	tag := "asybox:shmatest"
   502  	dockerCmd(c, "tag", "busybox", tag)
   503  
   504  	var id1 string
   505  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   506  	id1 = strings.TrimSpace(string(out))
   507  
   508  	var id2 string
   509  	out, _ = dockerCmd(c, "run", "-d", tag, "top")
   510  	id2 = strings.TrimSpace(string(out))
   511  
   512  	var imageID string
   513  	out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox")
   514  	imageID = strings.TrimSpace(string(out))
   515  
   516  	var id3 string
   517  	out, _ = dockerCmd(c, "run", "-d", imageID, "top")
   518  	id3 = strings.TrimSpace(string(out))
   519  
   520  	out, _ = dockerCmd(c, "ps", "--no-trunc")
   521  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   522  	// skip header
   523  	lines = lines[1:]
   524  	c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines)))
   525  	for _, line := range lines {
   526  		f := strings.Fields(line)
   527  		switch f[0] {
   528  		case id1:
   529  			c.Assert(f[1], checker.Equals, "busybox", check.Commentf("Expected %s tag for id %s, got %s", "busybox", id1, f[1]))
   530  		case id2:
   531  			c.Assert(f[1], checker.Equals, tag, check.Commentf("Expected %s tag for id %s, got %s", tag, id2, f[1]))
   532  		case id3:
   533  			c.Assert(f[1], checker.Equals, imageID, check.Commentf("Expected %s imageID for id %s, got %s", tag, id3, f[1]))
   534  		default:
   535  			c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
   536  		}
   537  	}
   538  }
   539  
   540  func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
   541  	testRequires(c, DaemonIsLinux)
   542  	dockerCmd(c, "run", "--name=first", "-d", "busybox", "top")
   543  	dockerCmd(c, "run", "--name=second", "--link=first:first", "-d", "busybox", "top")
   544  
   545  	out, _ := dockerCmd(c, "ps", "--no-trunc")
   546  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   547  	// strip header
   548  	lines = lines[1:]
   549  	expected := []string{"second", "first,second/first"}
   550  	var names []string
   551  	for _, l := range lines {
   552  		fields := strings.Fields(l)
   553  		names = append(names, fields[len(fields)-1])
   554  	}
   555  	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array: %v, got: %v", expected, names))
   556  }
   557  
   558  func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
   559  	testRequires(c, DaemonIsLinux)
   560  	portRange := "3800-3900"
   561  	dockerCmd(c, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top")
   562  
   563  	out, _ := dockerCmd(c, "ps")
   564  
   565  	c.Assert(string(out), checker.Contains, portRange, check.Commentf("docker ps output should have had the port range %q: %s", portRange, string(out)))
   566  
   567  }
   568  
   569  func (s *DockerSuite) TestPsWithSize(c *check.C) {
   570  	testRequires(c, DaemonIsLinux)
   571  	dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top")
   572  
   573  	out, _ := dockerCmd(c, "ps", "--size")
   574  	c.Assert(out, checker.Contains, "virtual", check.Commentf("docker ps with --size should show virtual size of container"))
   575  }
   576  
   577  func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
   578  	testRequires(c, DaemonIsLinux)
   579  	// create a container
   580  	out, _ := dockerCmd(c, "create", "busybox")
   581  	cID := strings.TrimSpace(out)
   582  	shortCID := cID[:12]
   583  
   584  	// Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
   585  	out, _ = dockerCmd(c, "ps", "-q")
   586  	c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out))
   587  
   588  	// Make sure it DOES show up as 'Created' for 'ps -a'
   589  	out, _ = dockerCmd(c, "ps", "-a")
   590  
   591  	hits := 0
   592  	for _, line := range strings.Split(out, "\n") {
   593  		if !strings.Contains(line, shortCID) {
   594  			continue
   595  		}
   596  		hits++
   597  		c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line))
   598  	}
   599  
   600  	c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
   601  
   602  	// filter containers by 'create' - note, no -a needed
   603  	out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
   604  	containerOut := strings.TrimSpace(out)
   605  	c.Assert(cID, checker.HasPrefix, containerOut)
   606  }
   607  
   608  func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
   609  	testRequires(c, DaemonIsLinux)
   610  	//create 2 containers and link them
   611  	dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
   612  	dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
   613  
   614  	//use the new format capabilities to only list the names and --no-trunc to get all names
   615  	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
   616  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   617  	expected := []string{"parent", "child,parent/linkedone"}
   618  	var names []string
   619  	for _, l := range lines {
   620  		names = append(names, l)
   621  	}
   622  	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names))
   623  
   624  	//now list without turning off truncation and make sure we only get the non-link names
   625  	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
   626  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   627  	expected = []string{"parent", "child"}
   628  	var truncNames []string
   629  	for _, l := range lines {
   630  		truncNames = append(truncNames, l)
   631  	}
   632  	c.Assert(expected, checker.DeepEquals, truncNames, check.Commentf("Expected array with truncated names: %v, got: %v", expected, truncNames))
   633  
   634  }
   635  
   636  func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
   637  	testRequires(c, DaemonIsLinux)
   638  	// make sure no-container "docker ps" still prints the header row
   639  	out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
   640  	c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
   641  
   642  	// verify that "docker ps" with a container still prints the header row also
   643  	dockerCmd(c, "run", "--name=test", "-d", "busybox", "top")
   644  	out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
   645  	c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
   646  }
   647  
   648  func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
   649  	testRequires(c, DaemonIsLinux)
   650  	config := `{
   651  		"psFormat": "default {{ .ID }}"
   652  }`
   653  	d, err := ioutil.TempDir("", "integration-cli-")
   654  	c.Assert(err, checker.IsNil)
   655  	defer os.RemoveAll(d)
   656  
   657  	err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
   658  	c.Assert(err, checker.IsNil)
   659  
   660  	out, _ := dockerCmd(c, "run", "--name=test", "-d", "busybox", "top")
   661  	id := strings.TrimSpace(out)
   662  
   663  	out, _ = dockerCmd(c, "--config", d, "ps", "-q")
   664  	c.Assert(id, checker.HasPrefix, strings.TrimSpace(out), check.Commentf("Expected to print only the container id, got %v\n", out))
   665  }
   666  
   667  // Test for GitHub issue #12595
   668  func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
   669  	testRequires(c, DaemonIsLinux)
   670  
   671  	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
   672  	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
   673  
   674  	runCmd := exec.Command(dockerBinary, "tag", "busybox:latest", originalImageName)
   675  	out, _, err := runCommandWithOutput(runCmd)
   676  	c.Assert(err, checker.IsNil)
   677  
   678  	originalImageID, err := getIDByName(originalImageName)
   679  	c.Assert(err, checker.IsNil)
   680  
   681  	runCmd = exec.Command(dockerBinary, "run", "-d", originalImageName, "top")
   682  	out, _, err = runCommandWithOutput(runCmd)
   683  	c.Assert(err, checker.IsNil)
   684  	containerID := strings.TrimSpace(out)
   685  
   686  	linesOut, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
   687  	c.Assert(err, checker.IsNil)
   688  
   689  	lines := strings.Split(strings.TrimSpace(string(linesOut)), "\n")
   690  	// skip header
   691  	lines = lines[1:]
   692  	c.Assert(len(lines), checker.Equals, 1)
   693  
   694  	for _, line := range lines {
   695  		f := strings.Fields(line)
   696  		c.Assert(f[1], checker.Equals, originalImageName)
   697  	}
   698  
   699  	runCmd = exec.Command(dockerBinary, "commit", containerID, updatedImageName)
   700  	out, _, err = runCommandWithOutput(runCmd)
   701  	c.Assert(err, checker.IsNil)
   702  
   703  	runCmd = exec.Command(dockerBinary, "tag", "-f", updatedImageName, originalImageName)
   704  	out, _, err = runCommandWithOutput(runCmd)
   705  	c.Assert(err, checker.IsNil)
   706  
   707  	linesOut, err = exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
   708  	c.Assert(err, checker.IsNil)
   709  
   710  	lines = strings.Split(strings.TrimSpace(string(linesOut)), "\n")
   711  	// skip header
   712  	lines = lines[1:]
   713  	c.Assert(len(lines), checker.Equals, 1)
   714  
   715  	for _, line := range lines {
   716  		f := strings.Fields(line)
   717  		c.Assert(f[1], checker.Equals, originalImageID)
   718  	}
   719  
   720  }
   721  
   722  func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
   723  	dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top")
   724  	c.Assert(waitRun("foo"), checker.IsNil)
   725  	out, _ := dockerCmd(c, "ps")
   726  	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
   727  	expected := "0.0.0.0:5000->5000/tcp"
   728  	fields := strings.Fields(lines[1])
   729  	c.Assert(fields[len(fields)-2], checker.Equals, expected, check.Commentf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
   730  
   731  	dockerCmd(c, "kill", "foo")
   732  	dockerCmd(c, "wait", "foo")
   733  	out, _ = dockerCmd(c, "ps", "-l")
   734  	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
   735  	fields = strings.Fields(lines[1])
   736  	c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
   737  }