github.com/moby/docker@v26.1.3+incompatible/integration/container/exec_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "io" 5 "strings" 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/integration/internal/container" 12 "gotest.tools/v3/assert" 13 is "gotest.tools/v3/assert/cmp" 14 "gotest.tools/v3/skip" 15 ) 16 17 // TestExecWithCloseStdin adds case for moby#37870 issue. 18 func TestExecWithCloseStdin(t *testing.T) { 19 skip.If(t, testEnv.RuntimeIsWindowsContainerd(), "FIXME. Hang on Windows + containerd combination") 20 ctx := setupTest(t) 21 22 apiClient := testEnv.APIClient() 23 24 // run top with detached mode 25 cID := container.Run(ctx, t, apiClient) 26 27 expected := "closeIO" 28 execResp, err := apiClient.ContainerExecCreate(ctx, cID, 29 types.ExecConfig{ 30 AttachStdin: true, 31 AttachStdout: true, 32 Cmd: strslice.StrSlice([]string{"sh", "-c", "cat && echo " + expected}), 33 }, 34 ) 35 assert.NilError(t, err) 36 37 resp, err := apiClient.ContainerExecAttach(ctx, execResp.ID, 38 types.ExecStartCheck{ 39 Detach: false, 40 Tty: false, 41 }, 42 ) 43 assert.NilError(t, err) 44 defer resp.Close() 45 46 // close stdin to send EOF to cat 47 assert.NilError(t, resp.CloseWrite()) 48 49 var ( 50 waitCh = make(chan struct{}) 51 resCh = make(chan struct { 52 content string 53 err error 54 }, 1) 55 ) 56 57 go func() { 58 close(waitCh) 59 defer close(resCh) 60 r, err := io.ReadAll(resp.Reader) 61 62 resCh <- struct { 63 content string 64 err error 65 }{ 66 content: string(r), 67 err: err, 68 } 69 }() 70 71 <-waitCh 72 select { 73 case <-time.After(3 * time.Second): 74 t.Fatal("failed to read the content in time") 75 case got := <-resCh: 76 assert.NilError(t, got.err) 77 78 // NOTE: using Contains because no-tty's stream contains UX information 79 // like size, stream type. 80 assert.Assert(t, is.Contains(got.content, expected)) 81 } 82 } 83 84 func TestExec(t *testing.T) { 85 ctx := setupTest(t) 86 apiClient := testEnv.APIClient() 87 88 cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithWorkingDir("/root")) 89 90 id, err := apiClient.ContainerExecCreate(ctx, cID, 91 types.ExecConfig{ 92 WorkingDir: "/tmp", 93 Env: strslice.StrSlice([]string{"FOO=BAR"}), 94 AttachStdout: true, 95 Cmd: strslice.StrSlice([]string{"sh", "-c", "env"}), 96 }, 97 ) 98 assert.NilError(t, err) 99 100 inspect, err := apiClient.ContainerExecInspect(ctx, id.ID) 101 assert.NilError(t, err) 102 assert.Check(t, is.Equal(inspect.ExecID, id.ID)) 103 104 resp, err := apiClient.ContainerExecAttach(ctx, id.ID, 105 types.ExecStartCheck{ 106 Detach: false, 107 Tty: false, 108 }, 109 ) 110 assert.NilError(t, err) 111 defer resp.Close() 112 r, err := io.ReadAll(resp.Reader) 113 assert.NilError(t, err) 114 out := string(r) 115 assert.NilError(t, err) 116 expected := "PWD=/tmp" 117 if testEnv.DaemonInfo.OSType == "windows" { 118 expected = "PWD=C:/tmp" 119 } 120 assert.Assert(t, is.Contains(out, expected), "exec command not running in expected /tmp working directory") 121 assert.Assert(t, is.Contains(out, "FOO=BAR"), "exec command not running with expected environment variable FOO") 122 } 123 124 func TestExecUser(t *testing.T) { 125 skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME. Probably needs to wait for container to be in running state.") 126 ctx := setupTest(t) 127 apiClient := testEnv.APIClient() 128 129 cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithUser("1:1")) 130 131 result, err := container.Exec(ctx, apiClient, cID, []string{"id"}) 132 assert.NilError(t, err) 133 134 assert.Assert(t, is.Contains(result.Stdout(), "uid=1(daemon) gid=1(daemon)"), "exec command not running as uid/gid 1") 135 } 136 137 // Test that additional groups set with `--group-add` are kept on exec when the container 138 // also has a user set. 139 // (regression test for https://github.com/moby/moby/issues/46712) 140 func TestExecWithGroupAdd(t *testing.T) { 141 skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME. Probably needs to wait for container to be in running state.") 142 143 ctx := setupTest(t) 144 apiClient := testEnv.APIClient() 145 146 cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithUser("root:root"), container.WithAdditionalGroups("staff", "wheel", "audio", "777"), container.WithCmd("sleep", "5")) 147 148 result, err := container.Exec(ctx, apiClient, cID, []string{"id"}) 149 assert.NilError(t, err) 150 151 assert.Assert(t, 152 is.Equal(strings.TrimSpace(result.Stdout()), "uid=0(root) gid=0(root) groups=0(root),10(wheel),29(audio),50(staff),777"), 153 "exec command not keeping additional groups w/ user") 154 }