github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/integration-cli/docker_cli_ps_test.go (about)

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