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