github.com/portworx/docker@v1.12.1/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/pkg/integration/checker"
    14  	"github.com/go-check/check"
    15  )
    16  
    17  const attachWait = 5 * time.Second
    18  
    19  func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
    20  	testRequires(c, DaemonIsLinux)
    21  
    22  	endGroup := &sync.WaitGroup{}
    23  	startGroup := &sync.WaitGroup{}
    24  	endGroup.Add(3)
    25  	startGroup.Add(3)
    26  
    27  	err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
    28  	c.Assert(err, check.IsNil)
    29  
    30  	startDone := make(chan struct{})
    31  	endDone := make(chan struct{})
    32  
    33  	go func() {
    34  		endGroup.Wait()
    35  		close(endDone)
    36  	}()
    37  
    38  	go func() {
    39  		startGroup.Wait()
    40  		close(startDone)
    41  	}()
    42  
    43  	for i := 0; i < 3; i++ {
    44  		go func() {
    45  			cmd := exec.Command(dockerBinary, "attach", "attacher")
    46  
    47  			defer func() {
    48  				cmd.Wait()
    49  				endGroup.Done()
    50  			}()
    51  
    52  			out, err := cmd.StdoutPipe()
    53  			if err != nil {
    54  				c.Fatal(err)
    55  			}
    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  	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  	testRequires(c, DaemonIsLinux)
    92  	out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
    93  
    94  	id := strings.TrimSpace(out)
    95  	c.Assert(waitRun(id), check.IsNil)
    96  
    97  	done := make(chan error)
    98  	go func() {
    99  		defer close(done)
   100  
   101  		cmd := exec.Command(dockerBinary, "attach", id)
   102  		if _, err := cmd.StdinPipe(); err != nil {
   103  			done <- err
   104  			return
   105  		}
   106  
   107  		expected := "the input device is not a TTY"
   108  		if runtime.GOOS == "windows" {
   109  			expected += ".  If you are using mintty, try prefixing the command with 'winpty'"
   110  		}
   111  		if out, _, err := runCommandWithOutput(cmd); err == nil {
   112  			done <- fmt.Errorf("attach should have failed")
   113  			return
   114  		} else if !strings.Contains(out, expected) {
   115  			done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
   116  			return
   117  		}
   118  	}()
   119  
   120  	select {
   121  	case err := <-done:
   122  		c.Assert(err, check.IsNil)
   123  	case <-time.After(attachWait):
   124  		c.Fatal("attach is running but should have failed")
   125  	}
   126  }
   127  
   128  func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
   129  	testRequires(c, DaemonIsLinux)
   130  	out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
   131  	id := strings.TrimSpace(out)
   132  
   133  	cmd := exec.Command(dockerBinary, "attach", id)
   134  	stdin, err := cmd.StdinPipe()
   135  	if err != nil {
   136  		c.Fatal(err)
   137  	}
   138  	defer stdin.Close()
   139  	stdout, err := cmd.StdoutPipe()
   140  	c.Assert(err, check.IsNil)
   141  	defer stdout.Close()
   142  	c.Assert(cmd.Start(), check.IsNil)
   143  	defer cmd.Process.Kill()
   144  
   145  	_, err = stdin.Write([]byte("hello\n"))
   146  	c.Assert(err, check.IsNil)
   147  	out, err = bufio.NewReader(stdout).ReadString('\n')
   148  	c.Assert(err, check.IsNil)
   149  	c.Assert(strings.TrimSpace(out), check.Equals, "hello")
   150  
   151  	c.Assert(stdin.Close(), check.IsNil)
   152  
   153  	// Expect container to still be running after stdin is closed
   154  	running := inspectField(c, id, "State.Running")
   155  	c.Assert(running, check.Equals, "true")
   156  }
   157  
   158  func (s *DockerSuite) TestAttachPausedContainer(c *check.C) {
   159  	testRequires(c, DaemonIsLinux) // Containers cannot be paused on Windows
   160  	defer unpauseAllContainers()
   161  	dockerCmd(c, "run", "-d", "--name=test", "busybox", "top")
   162  	dockerCmd(c, "pause", "test")
   163  	out, _, err := dockerCmdWithError("attach", "test")
   164  	c.Assert(err, checker.NotNil, check.Commentf(out))
   165  	c.Assert(out, checker.Contains, "You cannot attach to a paused container, unpause it first")
   166  }