Browse code

Merge pull request #35661 from ndeloof/8917

introduce `workingdir` option for docker exec

Vincent Demeester authored on 2017/12/06 20:40:25
Showing 5 changed files
... ...
@@ -7259,6 +7259,9 @@ paths:
7259 7259
               User:
7260 7260
                 type: "string"
7261 7261
                 description: "The user, and optionally, group to run the exec process inside the container. Format is one of: `user`, `user:group`, `uid`, or `uid:gid`."
7262
+              WorkingDir:
7263
+                type: "string"
7264
+                description: "The working directory for the exec process inside the container."
7262 7265
             example:
7263 7266
               AttachStdin: false
7264 7267
               AttachStdout: true
... ...
@@ -50,6 +50,7 @@ type ExecConfig struct {
50 50
 	Detach       bool     // Execute in detach mode
51 51
 	DetachKeys   string   // Escape keys for detach
52 52
 	Env          []string // Environment variables
53
+	WorkingDir   string   // Working directory
53 54
 	Cmd          []string // Execution commands and args
54 55
 }
55 56
 
... ...
@@ -122,6 +122,7 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str
122 122
 	execConfig.Tty = config.Tty
123 123
 	execConfig.Privileged = config.Privileged
124 124
 	execConfig.User = config.User
125
+	execConfig.WorkingDir = config.WorkingDir
125 126
 
126 127
 	linkedEnv, err := d.setupLinkedContainers(cntr)
127 128
 	if err != nil {
... ...
@@ -131,6 +132,9 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str
131 131
 	if len(execConfig.User) == 0 {
132 132
 		execConfig.User = cntr.Config.User
133 133
 	}
134
+	if len(execConfig.WorkingDir) == 0 {
135
+		execConfig.WorkingDir = cntr.Config.WorkingDir
136
+	}
134 137
 
135 138
 	d.registerExecCommand(cntr, execConfig)
136 139
 
... ...
@@ -211,7 +215,7 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
211 211
 		Args:     append([]string{ec.Entrypoint}, ec.Args...),
212 212
 		Env:      ec.Env,
213 213
 		Terminal: ec.Tty,
214
-		Cwd:      c.Config.WorkingDir,
214
+		Cwd:      ec.WorkingDir,
215 215
 	}
216 216
 	if p.Cwd == "" {
217 217
 		p.Cwd = "/"
... ...
@@ -31,6 +31,7 @@ type Config struct {
31 31
 	Tty          bool
32 32
 	Privileged   bool
33 33
 	User         string
34
+	WorkingDir   string
34 35
 	Env          []string
35 36
 	Pid          int
36 37
 }
37 38
new file mode 100644
... ...
@@ -0,0 +1,60 @@
0
+package container
1
+
2
+import (
3
+	"context"
4
+	"io/ioutil"
5
+	"testing"
6
+
7
+	"github.com/docker/docker/api/types"
8
+	"github.com/docker/docker/api/types/container"
9
+	"github.com/docker/docker/api/types/network"
10
+	"github.com/docker/docker/api/types/strslice"
11
+	"github.com/docker/docker/integration/util/request"
12
+	"github.com/stretchr/testify/require"
13
+)
14
+
15
+func TestExec(t *testing.T) {
16
+	defer setupTest(t)()
17
+	ctx := context.Background()
18
+	client := request.NewAPIClient(t)
19
+
20
+	container, err := client.ContainerCreate(ctx,
21
+		&container.Config{
22
+			Image:      "busybox",
23
+			Tty:        true,
24
+			WorkingDir: "/root",
25
+			Cmd:        strslice.StrSlice([]string{"top"}),
26
+		},
27
+		&container.HostConfig{},
28
+		&network.NetworkingConfig{},
29
+		"foo",
30
+	)
31
+	require.NoError(t, err)
32
+	err = client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{})
33
+	require.NoError(t, err)
34
+
35
+	id, err := client.ContainerExecCreate(ctx, container.ID,
36
+		types.ExecConfig{
37
+			WorkingDir:   "/tmp",
38
+			Env:          strslice.StrSlice([]string{"FOO=BAR"}),
39
+			AttachStdout: true,
40
+			Cmd:          strslice.StrSlice([]string{"sh", "-c", "env"}),
41
+		},
42
+	)
43
+	require.NoError(t, err)
44
+
45
+	resp, err := client.ContainerExecAttach(ctx, id.ID,
46
+		types.ExecStartCheck{
47
+			Detach: false,
48
+			Tty:    false,
49
+		},
50
+	)
51
+	require.NoError(t, err)
52
+	defer resp.Close()
53
+	r, err := ioutil.ReadAll(resp.Reader)
54
+	require.NoError(t, err)
55
+	out := string(r)
56
+	require.NoError(t, err)
57
+	require.Contains(t, out, "PWD=/tmp", "exec command not running in expected /tmp working directory")
58
+	require.Contains(t, out, "FOO=BAR", "exec command not running with expected environment variable FOO")
59
+}