1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/integration-cli/docker_cli_ps_test.go
Tianon Gravi f57fc03e3b Fix "docker ps" with no containers regression
The header row was not being printed when "docker ps" was invoked without containers thanks to the new format support, and we instead received a single blank line.

Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
2015-07-23 13:23:24 -07:00

556 lines
17 KiB
Go

package main
import (
"fmt"
"os/exec"
"reflect"
"strconv"
"strings"
"time"
"github.com/go-check/check"
)
func (s *DockerSuite) TestPsListContainers(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
firstID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
secondID := strings.TrimSpace(out)
// not long running
out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
thirdID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
fourthID := strings.TrimSpace(out)
// make sure the second is running
if err := waitRun(secondID); err != nil {
c.Fatalf("waiting for container failed: %v", err)
}
// make sure third one is not running
dockerCmd(c, "wait", thirdID)
// make sure the forth is running
if err := waitRun(fourthID); err != nil {
c.Fatalf("waiting for container failed: %v", err)
}
// all
out, _ = dockerCmd(c, "ps", "-a")
if !assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// running
out, _ = dockerCmd(c, "ps")
if !assertContainerList(out, []string{fourthID, secondID, firstID}) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// from here all flag '-a' is ignored
// limit
out, _ = dockerCmd(c, "ps", "-n=2", "-a")
expected := []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "-n=2")
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// since
out, _ = dockerCmd(c, "ps", "--since", firstID, "-a")
expected = []string{fourthID, thirdID, secondID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--since", firstID)
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// before
out, _ = dockerCmd(c, "ps", "--before", thirdID, "-a")
expected = []string{secondID, firstID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--before", thirdID)
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & before
out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-a")
expected = []string{thirdID, secondID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID)
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & limit
out, _ = dockerCmd(c, "ps", "--since", firstID, "-n=2", "-a")
expected = []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--since", firstID, "-n=2")
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
// before & limit
out, _ = dockerCmd(c, "ps", "--before", fourthID, "-n=1", "-a")
expected = []string{thirdID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--before", fourthID, "-n=1")
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-n=1", "-a")
expected = []string{thirdID}
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
out, _ = dockerCmd(c, "ps", "--since", firstID, "--before", fourthID, "-n=1")
if !assertContainerList(out, expected) {
c.Errorf("Container list is not in the correct order: %s", out)
}
}
func assertContainerList(out string, expected []string) bool {
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines)-1 != len(expected) {
return false
}
containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
for i := 0; i < len(expected); i++ {
foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
if foundID != expected[i][:12] {
return false
}
}
return true
}
func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
baseSizeIndex := strings.Index(baseLines[0], "SIZE")
baseFoundsize := baseLines[1][baseSizeIndex:]
baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
if err != nil {
c.Fatal(err)
}
name := "test_size"
out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
id, err := getIDByName(name)
if err != nil {
c.Fatal(err)
}
runCmd := exec.Command(dockerBinary, "ps", "-s", "-n=1")
wait := make(chan struct{})
go func() {
out, _, err = runCommandWithOutput(runCmd)
close(wait)
}()
select {
case <-wait:
case <-time.After(3 * time.Second):
c.Fatalf("Calling \"docker ps -s\" timed out!")
}
if err != nil {
c.Fatal(out, err)
}
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != 2 {
c.Fatalf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
}
sizeIndex := strings.Index(lines[0], "SIZE")
idIndex := strings.Index(lines[0], "CONTAINER ID")
foundID := lines[1][idIndex : idIndex+12]
if foundID != id[:12] {
c.Fatalf("Expected id %s, got %s", id[:12], foundID)
}
expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
foundSize := lines[1][sizeIndex:]
if !strings.Contains(foundSize, expectedSize) {
c.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
}
}
func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
// FIXME: this should test paused, but it makes things hang and its wonky
// this is because paused containers can't be controlled by signals
// start exited container
out, _ := dockerCmd(c, "run", "-d", "busybox")
firstID := strings.TrimSpace(out)
// make sure the exited cintainer is not running
dockerCmd(c, "wait", firstID)
// start running container
out, _ = dockerCmd(c, "run", "-itd", "busybox")
secondID := strings.TrimSpace(out)
// filter containers by exited
out, _ = dockerCmd(c, "ps", "-q", "--filter=status=exited")
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=status=running")
containerOut = strings.TrimSpace(out)
if containerOut != secondID[:12] {
c.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
}
out, _, _ = dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish")
if !strings.Contains(out, "Unrecognised filter value for status") {
c.Fatalf("Expected error response due to invalid status filter output: %q", out)
}
}
func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
// start container
out, _ := dockerCmd(c, "run", "-d", "busybox")
firstID := strings.TrimSpace(out)
// start another container
dockerCmd(c, "run", "-d", "busybox", "top")
// filter containers by id
out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
}
func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
// start container
out, _ := dockerCmd(c, "run", "-d", "--name=a_name_to_match", "busybox")
firstID := strings.TrimSpace(out)
// start another container
dockerCmd(c, "run", "-d", "--name=b_name_to_match", "busybox", "top")
// filter containers by name
out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=name=a_name_to_match")
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
}
func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
// start container
out, _ := dockerCmd(c, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
firstID := strings.TrimSpace(out)
// start another container
out, _ = dockerCmd(c, "run", "-d", "-l", "match=me too", "busybox")
secondID := strings.TrimSpace(out)
// start third container
out, _ = dockerCmd(c, "run", "-d", "-l", "nomatch=me", "busybox")
thirdID := strings.TrimSpace(out)
// filter containers by exact match
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
containerOut := strings.TrimSpace(out)
if containerOut != firstID {
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
}
// filter containers by two labels
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
containerOut = strings.TrimSpace(out)
if containerOut != firstID {
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
}
// filter containers by two labels, but expect not found because of AND behavior
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
containerOut = strings.TrimSpace(out)
if containerOut != "" {
c.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
}
// filter containers by exact key
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
containerOut = strings.TrimSpace(out)
if (!strings.Contains(containerOut, firstID) || !strings.Contains(containerOut, secondID)) || strings.Contains(containerOut, thirdID) {
c.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
}
}
func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
dockerCmd(c, "run", "-d", "--name", "top", "busybox", "top")
dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
firstZero, err := getIDByName("zero1")
if err != nil {
c.Fatal(err)
}
dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
secondZero, err := getIDByName("zero2")
if err != nil {
c.Fatal(err)
}
if out, _, err := dockerCmdWithError(c, "run", "--name", "nonzero1", "busybox", "false"); err == nil {
c.Fatal("Should fail.", out, err)
}
firstNonZero, err := getIDByName("nonzero1")
if err != nil {
c.Fatal(err)
}
if out, _, err := dockerCmdWithError(c, "run", "--name", "nonzero2", "busybox", "false"); err == nil {
c.Fatal("Should fail.", out, err)
}
secondNonZero, err := getIDByName("nonzero2")
if err != nil {
c.Fatal(err)
}
// filter containers by exited=0
out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
ids := strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
c.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
}
if ids[0] != secondZero {
c.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
}
if ids[1] != firstZero {
c.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
}
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
ids = strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
c.Fatalf("Should be 2 zero exited containers got %d", len(ids))
}
if ids[0] != secondNonZero {
c.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
}
if ids[1] != firstNonZero {
c.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
}
}
func (s *DockerSuite) TestPsRightTagName(c *check.C) {
tag := "asybox:shmatest"
dockerCmd(c, "tag", "busybox", tag)
var id1 string
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id1 = strings.TrimSpace(string(out))
var id2 string
out, _ = dockerCmd(c, "run", "-d", tag, "top")
id2 = strings.TrimSpace(string(out))
var imageID string
out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox")
imageID = strings.TrimSpace(string(out))
var id3 string
out, _ = dockerCmd(c, "run", "-d", imageID, "top")
id3 = strings.TrimSpace(string(out))
out, _ = dockerCmd(c, "ps", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// skip header
lines = lines[1:]
if len(lines) != 3 {
c.Fatalf("There should be 3 running container, got %d", len(lines))
}
for _, line := range lines {
f := strings.Fields(line)
switch f[0] {
case id1:
if f[1] != "busybox" {
c.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
}
case id2:
if f[1] != tag {
c.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
}
case id3:
if f[1] != imageID {
c.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
}
default:
c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
}
}
}
func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
dockerCmd(c, "run", "--name=first", "-d", "busybox", "top")
dockerCmd(c, "run", "--name=second", "--link=first:first", "-d", "busybox", "top")
out, _ := dockerCmd(c, "ps", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// strip header
lines = lines[1:]
expected := []string{"second", "first,second/first"}
var names []string
for _, l := range lines {
fields := strings.Fields(l)
names = append(names, fields[len(fields)-1])
}
if !reflect.DeepEqual(expected, names) {
c.Fatalf("Expected array: %v, got: %v", expected, names)
}
}
func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
portRange := "3800-3900"
dockerCmd(c, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top")
out, _ := dockerCmd(c, "ps")
// check that the port range is in the output
if !strings.Contains(string(out), portRange) {
c.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
}
}
func (s *DockerSuite) TestPsWithSize(c *check.C) {
dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top")
out, _ := dockerCmd(c, "ps", "--size")
if !strings.Contains(out, "virtual") {
c.Fatalf("docker ps with --size should show virtual size of container")
}
}
func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
// create a container
out, _ := dockerCmd(c, "create", "busybox")
cID := strings.TrimSpace(out)
shortCID := cID[:12]
// Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
out, _ = dockerCmd(c, "ps", "-q")
if strings.Contains(out, shortCID) {
c.Fatalf("Should have not seen '%s' in ps output:\n%s", shortCID, out)
}
// Make sure it DOES show up as 'Created' for 'ps -a'
out, _ = dockerCmd(c, "ps", "-a")
hits := 0
for _, line := range strings.Split(out, "\n") {
if !strings.Contains(line, shortCID) {
continue
}
hits++
if !strings.Contains(line, "Created") {
c.Fatalf("Missing 'Created' on '%s'", line)
}
}
if hits != 1 {
c.Fatalf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out)
}
// filter containers by 'create' - note, no -a needed
out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
containerOut := strings.TrimSpace(out)
if !strings.HasPrefix(cID, containerOut) {
c.Fatalf("Expected id %s, got %s for filter, out: %s", cID, containerOut, out)
}
}
func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
//create 2 containers and link them
dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
//use the new format capabilities to only list the names and --no-trunc to get all names
out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
expected := []string{"parent", "child,parent/linkedone"}
var names []string
for _, l := range lines {
names = append(names, l)
}
if !reflect.DeepEqual(expected, names) {
c.Fatalf("Expected array with non-truncated names: %v, got: %v", expected, names)
}
//now list without turning off truncation and make sure we only get the non-link names
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
lines = strings.Split(strings.TrimSpace(string(out)), "\n")
expected = []string{"parent", "child"}
var truncNames []string
for _, l := range lines {
truncNames = append(truncNames, l)
}
if !reflect.DeepEqual(expected, truncNames) {
c.Fatalf("Expected array with truncated names: %v, got: %v", expected, truncNames)
}
}
func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
// make sure no-container "docker ps" still prints the header row
out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
if out != "CONTAINER ID\n" {
c.Fatalf(`Expected 'CONTAINER ID\n', got %v`, out)
}
// verify that "docker ps" with a container still prints the header row also
dockerCmd(c, "run", "--name=test", "-d", "busybox", "top")
out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
if out != "NAMES\ntest\n" {
c.Fatalf(`Expected 'NAMES\ntest\n', got %v`, out)
}
}