github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration/container/exec_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "context" 5 "io/ioutil" 6 "testing" 7 "time" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/strslice" 11 "github.com/docker/docker/api/types/versions" 12 "github.com/docker/docker/integration/internal/container" 13 "gotest.tools/assert" 14 is "gotest.tools/assert/cmp" 15 "gotest.tools/skip" 16 ) 17 18 // TestExecWithCloseStdin adds case for moby#37870 issue. 19 func TestExecWithCloseStdin(t *testing.T) { 20 skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "broken in earlier versions") 21 defer setupTest(t)() 22 23 ctx := context.Background() 24 client := testEnv.APIClient() 25 26 // run top with detached mode 27 cID := container.Run(t, ctx, client) 28 29 expected := "closeIO" 30 execResp, err := client.ContainerExecCreate(ctx, cID, 31 types.ExecConfig{ 32 AttachStdin: true, 33 AttachStdout: true, 34 Cmd: strslice.StrSlice([]string{"sh", "-c", "cat && echo " + expected}), 35 }, 36 ) 37 assert.NilError(t, err) 38 39 resp, err := client.ContainerExecAttach(ctx, execResp.ID, 40 types.ExecStartCheck{ 41 Detach: false, 42 Tty: false, 43 }, 44 ) 45 assert.NilError(t, err) 46 defer resp.Close() 47 48 // close stdin to send EOF to cat 49 assert.NilError(t, resp.CloseWrite()) 50 51 var ( 52 waitCh = make(chan struct{}) 53 resCh = make(chan struct { 54 content string 55 err error 56 }) 57 ) 58 59 go func() { 60 close(waitCh) 61 defer close(resCh) 62 r, err := ioutil.ReadAll(resp.Reader) 63 64 resCh <- struct { 65 content string 66 err error 67 }{ 68 content: string(r), 69 err: err, 70 } 71 }() 72 73 <-waitCh 74 select { 75 case <-time.After(3 * time.Second): 76 t.Fatal("failed to read the content in time") 77 case got := <-resCh: 78 assert.NilError(t, got.err) 79 80 // NOTE: using Contains because no-tty's stream contains UX information 81 // like size, stream type. 82 assert.Assert(t, is.Contains(got.content, expected)) 83 } 84 } 85 86 func TestExec(t *testing.T) { 87 skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.35"), "broken in earlier versions") 88 skip.If(t, testEnv.OSType == "windows", "FIXME. Probably needs to wait for container to be in running state.") 89 defer setupTest(t)() 90 ctx := context.Background() 91 client := testEnv.APIClient() 92 93 cID := container.Run(t, ctx, client, container.WithTty(true), container.WithWorkingDir("/root")) 94 95 id, err := client.ContainerExecCreate(ctx, cID, 96 types.ExecConfig{ 97 WorkingDir: "/tmp", 98 Env: strslice.StrSlice([]string{"FOO=BAR"}), 99 AttachStdout: true, 100 Cmd: strslice.StrSlice([]string{"sh", "-c", "env"}), 101 }, 102 ) 103 assert.NilError(t, err) 104 105 resp, err := client.ContainerExecAttach(ctx, id.ID, 106 types.ExecStartCheck{ 107 Detach: false, 108 Tty: false, 109 }, 110 ) 111 assert.NilError(t, err) 112 defer resp.Close() 113 r, err := ioutil.ReadAll(resp.Reader) 114 assert.NilError(t, err) 115 out := string(r) 116 assert.NilError(t, err) 117 assert.Assert(t, is.Contains(out, "PWD=/tmp"), "exec command not running in expected /tmp working directory") 118 assert.Assert(t, is.Contains(out, "FOO=BAR"), "exec command not running with expected environment variable FOO") 119 } 120 121 func TestExecUser(t *testing.T) { 122 skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "broken in earlier versions") 123 skip.If(t, testEnv.OSType == "windows", "FIXME. Probably needs to wait for container to be in running state.") 124 defer setupTest(t)() 125 ctx := context.Background() 126 client := testEnv.APIClient() 127 128 cID := container.Run(t, ctx, client, container.WithTty(true), container.WithUser("1:1")) 129 130 result, err := container.Exec(ctx, client, cID, []string{"id"}) 131 assert.NilError(t, err) 132 133 assert.Assert(t, is.Contains(result.Stdout(), "uid=1(daemon) gid=1(daemon)"), "exec command not running as uid/gid 1") 134 }