exec_test.go 3.7 KB

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