github.com/khulnasoft-lab/khulnasoft@v26.0.1-0.20240328202558-330a6f959fe0+incompatible/integration-cli/docker_cli_attach_test.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "context" 6 "fmt" 7 "io" 8 "os/exec" 9 "runtime" 10 "strings" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/docker/docker/integration-cli/cli" 16 "gotest.tools/v3/assert" 17 "gotest.tools/v3/icmd" 18 ) 19 20 const attachWait = 5 * time.Second 21 22 type DockerCLIAttachSuite struct { 23 ds *DockerSuite 24 } 25 26 func (s *DockerCLIAttachSuite) TearDownTest(ctx context.Context, c *testing.T) { 27 s.ds.TearDownTest(ctx, c) 28 } 29 30 func (s *DockerCLIAttachSuite) OnTimeout(c *testing.T) { 31 s.ds.OnTimeout(c) 32 } 33 34 func (s *DockerCLIAttachSuite) TestAttachMultipleAndRestart(c *testing.T) { 35 endGroup := &sync.WaitGroup{} 36 startGroup := &sync.WaitGroup{} 37 endGroup.Add(3) 38 startGroup.Add(3) 39 40 cli.DockerCmd(c, "run", "--name", "attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done") 41 cli.WaitRun(c, "attacher") 42 43 startDone := make(chan struct{}) 44 endDone := make(chan struct{}) 45 46 go func() { 47 endGroup.Wait() 48 close(endDone) 49 }() 50 51 go func() { 52 startGroup.Wait() 53 close(startDone) 54 }() 55 56 for i := 0; i < 3; i++ { 57 go func() { 58 cmd := exec.Command(dockerBinary, "attach", "attacher") 59 60 defer func() { 61 cmd.Wait() 62 endGroup.Done() 63 }() 64 65 out, err := cmd.StdoutPipe() 66 if err != nil { 67 c.Error(err) 68 } 69 defer out.Close() 70 71 if err := cmd.Start(); err != nil { 72 c.Error(err) 73 } 74 75 buf := make([]byte, 1024) 76 77 if _, err := out.Read(buf); err != nil && err != io.EOF { 78 c.Error(err) 79 } 80 81 startGroup.Done() 82 83 if !strings.Contains(string(buf), "hello") { 84 c.Errorf("unexpected output %s expected hello\n", string(buf)) 85 } 86 }() 87 } 88 89 select { 90 case <-startDone: 91 case <-time.After(attachWait): 92 c.Fatalf("Attaches did not initialize properly") 93 } 94 95 cli.DockerCmd(c, "kill", "attacher") 96 97 select { 98 case <-endDone: 99 case <-time.After(attachWait): 100 c.Fatalf("Attaches did not finish properly") 101 } 102 } 103 104 func (s *DockerCLIAttachSuite) TestAttachTTYWithoutStdin(c *testing.T) { 105 // TODO: Figure out how to get this running again reliable on Windows. 106 // It works by accident at the moment. Sometimes. I've gone back to v1.13.0 and see the same. 107 // On Windows, docker run -d -ti busybox causes the container to exit immediately. 108 // Obviously a year back when I updated the test, that was not the case. However, 109 // with this, and the test racing with the tear-down which panic's, sometimes CI 110 // will just fail and `MISS` all the other tests. For now, disabling it. Will 111 // open an issue to track re-enabling this and root-causing the problem. 112 testRequires(c, DaemonIsLinux) 113 out := cli.DockerCmd(c, "run", "-d", "-ti", "busybox").Stdout() 114 id := strings.TrimSpace(out) 115 cli.WaitRun(c, id) 116 117 done := make(chan error, 1) 118 go func() { 119 defer close(done) 120 121 cmd := exec.Command(dockerBinary, "attach", id) 122 if _, err := cmd.StdinPipe(); err != nil { 123 done <- err 124 return 125 } 126 127 expected := "the input device is not a TTY" 128 if runtime.GOOS == "windows" { 129 expected += ". If you are using mintty, try prefixing the command with 'winpty'" 130 } 131 result := icmd.RunCmd(icmd.Cmd{ 132 Command: cmd.Args, 133 Env: cmd.Env, 134 Dir: cmd.Dir, 135 Stdin: cmd.Stdin, 136 Stdout: cmd.Stdout, 137 }) 138 if result.Error == nil { 139 done <- fmt.Errorf("attach should have failed") 140 return 141 } else if !strings.Contains(result.Combined(), expected) { 142 done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected) 143 return 144 } 145 }() 146 147 select { 148 case err := <-done: 149 assert.NilError(c, err) 150 case <-time.After(attachWait): 151 c.Fatal("attach is running but should have failed") 152 } 153 } 154 155 func (s *DockerCLIAttachSuite) TestAttachDisconnect(c *testing.T) { 156 testRequires(c, DaemonIsLinux) 157 out := cli.DockerCmd(c, "run", "-di", "busybox", "/bin/cat").Stdout() 158 id := strings.TrimSpace(out) 159 160 cmd := exec.Command(dockerBinary, "attach", id) 161 stdin, err := cmd.StdinPipe() 162 if err != nil { 163 c.Fatal(err) 164 } 165 defer stdin.Close() 166 stdout, err := cmd.StdoutPipe() 167 assert.NilError(c, err) 168 defer stdout.Close() 169 assert.Assert(c, cmd.Start() == nil) 170 defer func() { 171 cmd.Process.Kill() 172 cmd.Wait() 173 }() 174 175 _, err = stdin.Write([]byte("hello\n")) 176 assert.NilError(c, err) 177 out, err = bufio.NewReader(stdout).ReadString('\n') 178 assert.NilError(c, err) 179 assert.Equal(c, strings.TrimSpace(out), "hello") 180 181 assert.Assert(c, stdin.Close() == nil) 182 183 // Expect container to still be running after stdin is closed 184 running := inspectField(c, id, "State.Running") 185 assert.Equal(c, running, "true") 186 } 187 188 func (s *DockerCLIAttachSuite) TestAttachPausedContainer(c *testing.T) { 189 testRequires(c, IsPausable) 190 runSleepingContainer(c, "-d", "--name=test") 191 cli.DockerCmd(c, "pause", "test") 192 193 result := cli.Docker(cli.Args("attach", "test")) 194 result.Assert(c, icmd.Expected{ 195 Error: "exit status 1", 196 ExitCode: 1, 197 Err: "You cannot attach to a paused container, unpause it first", 198 }) 199 }