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