github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_attach_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os/exec"
     8  	"runtime"
     9  	"strings"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/docker/docker/integration-cli/cli"
    14  	icmd "github.com/docker/docker/pkg/testutil/cmd"
    15  	"github.com/go-check/check"
    16  )
    17  
    18  const attachWait = 5 * time.Second
    19  
    20  func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
    21  	endGroup := &sync.WaitGroup{}
    22  	startGroup := &sync.WaitGroup{}
    23  	endGroup.Add(3)
    24  	startGroup.Add(3)
    25  
    26  	cli.DockerCmd(c, "run", "--name", "attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
    27  	cli.WaitRun(c, "attacher")
    28  
    29  	startDone := make(chan struct{})
    30  	endDone := make(chan struct{})
    31  
    32  	go func() {
    33  		endGroup.Wait()
    34  		close(endDone)
    35  	}()
    36  
    37  	go func() {
    38  		startGroup.Wait()
    39  		close(startDone)
    40  	}()
    41  
    42  	for i := 0; i < 3; i++ {
    43  		go func() {
    44  			cmd := exec.Command(dockerBinary, "attach", "attacher")
    45  
    46  			defer func() {
    47  				cmd.Wait()
    48  				endGroup.Done()
    49  			}()
    50  
    51  			out, err := cmd.StdoutPipe()
    52  			if err != nil {
    53  				c.Fatal(err)
    54  			}
    55  			defer out.Close()
    56  
    57  			if err := cmd.Start(); err != nil {
    58  				c.Fatal(err)
    59  			}
    60  
    61  			buf := make([]byte, 1024)
    62  
    63  			if _, err := out.Read(buf); err != nil && err != io.EOF {
    64  				c.Fatal(err)
    65  			}
    66  
    67  			startGroup.Done()
    68  
    69  			if !strings.Contains(string(buf), "hello") {
    70  				c.Fatalf("unexpected output %s expected hello\n", string(buf))
    71  			}
    72  		}()
    73  	}
    74  
    75  	select {
    76  	case <-startDone:
    77  	case <-time.After(attachWait):
    78  		c.Fatalf("Attaches did not initialize properly")
    79  	}
    80  
    81  	cli.DockerCmd(c, "kill", "attacher")
    82  
    83  	select {
    84  	case <-endDone:
    85  	case <-time.After(attachWait):
    86  		c.Fatalf("Attaches did not finish properly")
    87  	}
    88  }
    89  
    90  func (s *DockerSuite) TestAttachTTYWithoutStdin(c *check.C) {
    91  	out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
    92  
    93  	id := strings.TrimSpace(out)
    94  	c.Assert(waitRun(id), check.IsNil)
    95  
    96  	done := make(chan error)
    97  	go func() {
    98  		defer close(done)
    99  
   100  		cmd := exec.Command(dockerBinary, "attach", id)
   101  		if _, err := cmd.StdinPipe(); err != nil {
   102  			done <- err
   103  			return
   104  		}
   105  
   106  		expected := "the input device is not a TTY"
   107  		if runtime.GOOS == "windows" {
   108  			expected += ".  If you are using mintty, try prefixing the command with 'winpty'"
   109  		}
   110  		if out, _, err := runCommandWithOutput(cmd); err == nil {
   111  			done <- fmt.Errorf("attach should have failed")
   112  			return
   113  		} else if !strings.Contains(out, expected) {
   114  			done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
   115  			return
   116  		}
   117  	}()
   118  
   119  	select {
   120  	case err := <-done:
   121  		c.Assert(err, check.IsNil)
   122  	case <-time.After(attachWait):
   123  		c.Fatal("attach is running but should have failed")
   124  	}
   125  }
   126  
   127  func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
   128  	testRequires(c, DaemonIsLinux)
   129  	out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
   130  	id := strings.TrimSpace(out)
   131  
   132  	cmd := exec.Command(dockerBinary, "attach", id)
   133  	stdin, err := cmd.StdinPipe()
   134  	if err != nil {
   135  		c.Fatal(err)
   136  	}
   137  	defer stdin.Close()
   138  	stdout, err := cmd.StdoutPipe()
   139  	c.Assert(err, check.IsNil)
   140  	defer stdout.Close()
   141  	c.Assert(cmd.Start(), check.IsNil)
   142  	defer cmd.Process.Kill()
   143  
   144  	_, err = stdin.Write([]byte("hello\n"))
   145  	c.Assert(err, check.IsNil)
   146  	out, err = bufio.NewReader(stdout).ReadString('\n')
   147  	c.Assert(err, check.IsNil)
   148  	c.Assert(strings.TrimSpace(out), check.Equals, "hello")
   149  
   150  	c.Assert(stdin.Close(), check.IsNil)
   151  
   152  	// Expect container to still be running after stdin is closed
   153  	running := inspectField(c, id, "State.Running")
   154  	c.Assert(running, check.Equals, "true")
   155  }
   156  
   157  func (s *DockerSuite) TestAttachPausedContainer(c *check.C) {
   158  	testRequires(c, IsPausable)
   159  	runSleepingContainer(c, "-d", "--name=test")
   160  	dockerCmd(c, "pause", "test")
   161  
   162  	result := dockerCmdWithResult("attach", "test")
   163  	c.Assert(result, icmd.Matches, icmd.Expected{
   164  		Error:    "exit status 1",
   165  		ExitCode: 1,
   166  		Err:      "You cannot attach to a paused container, unpause it first",
   167  	})
   168  }