github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/integration-cli/docker_cli_ps_test.go (about)

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