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