github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/integration/container/exec_test.go (about)

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