Skip to content

Commit 0a94e5a

Browse files
committed
Merge branch 'TomasTomecek-add-env-support-to-exec'
2 parents 67f12bd + c603002 commit 0a94e5a

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

docker/api/exec_api.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class ExecApiMixin(object):
88
@utils.minimum_version('1.15')
99
@utils.check_resource
1010
def exec_create(self, container, cmd, stdout=True, stderr=True,
11-
stdin=False, tty=False, privileged=False, user=''):
11+
stdin=False, tty=False, privileged=False, user='',
12+
environment=None):
1213
"""
1314
Sets up an exec instance in a running container.
1415
@@ -22,6 +23,9 @@ def exec_create(self, container, cmd, stdout=True, stderr=True,
2223
tty (bool): Allocate a pseudo-TTY. Default: False
2324
privileged (bool): Run as privileged.
2425
user (str): User to execute command as. Default: root
26+
environment (dict or list): A dictionary or a list of strings in
27+
the following format ``["PASSWORD=xxx"]`` or
28+
``{"PASSWORD": "xxx"}``.
2529
2630
Returns:
2731
(dict): A dictionary with an exec ``Id`` key.
@@ -31,17 +35,25 @@ def exec_create(self, container, cmd, stdout=True, stderr=True,
3135
If the server returns an error.
3236
"""
3337

34-
if privileged and utils.compare_version('1.19', self._version) < 0:
38+
if privileged and utils.version_lt(self._version, '1.19'):
3539
raise errors.InvalidVersion(
3640
'Privileged exec is not supported in API < 1.19'
3741
)
38-
if user and utils.compare_version('1.19', self._version) < 0:
42+
if user and utils.version_lt(self._version, '1.19'):
3943
raise errors.InvalidVersion(
4044
'User-specific exec is not supported in API < 1.19'
4145
)
46+
if environment is not None and utils.version_lt(self._version, '1.25'):
47+
raise errors.InvalidVersion(
48+
'Setting environment for exec is not supported in API < 1.25'
49+
)
50+
4251
if isinstance(cmd, six.string_types):
4352
cmd = utils.split_command(cmd)
4453

54+
if isinstance(environment, dict):
55+
environment = utils.utils.format_environment(environment)
56+
4557
data = {
4658
'Container': container,
4759
'User': user,
@@ -50,7 +62,8 @@ def exec_create(self, container, cmd, stdout=True, stderr=True,
5062
'AttachStdin': stdin,
5163
'AttachStdout': stdout,
5264
'AttachStderr': stderr,
53-
'Cmd': cmd
65+
'Cmd': cmd,
66+
'Env': environment,
5467
}
5568

5669
url = self._url('/containers/{0}/exec', container)
@@ -97,6 +110,7 @@ def exec_resize(self, exec_id, height=None, width=None):
97110
self._raise_for_status(res)
98111

99112
@utils.minimum_version('1.15')
113+
@utils.check_resource
100114
def exec_start(self, exec_id, detach=False, tty=False, stream=False,
101115
socket=False):
102116
"""
@@ -118,8 +132,6 @@ def exec_start(self, exec_id, detach=False, tty=False, stream=False,
118132
If the server returns an error.
119133
"""
120134
# we want opened socket if socket == True
121-
if isinstance(exec_id, dict):
122-
exec_id = exec_id.get('Id')
123135

124136
data = {
125137
'Tty': tty,

docker/models/containers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def diff(self):
125125

126126
def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
127127
privileged=False, user='', detach=False, stream=False,
128-
socket=False):
128+
socket=False, environment=None):
129129
"""
130130
Run a command inside this container. Similar to
131131
``docker exec``.
@@ -141,6 +141,9 @@ def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
141141
detach (bool): If true, detach from the exec command.
142142
Default: False
143143
stream (bool): Stream response data. Default: False
144+
environment (dict or list): A dictionary or a list of strings in
145+
the following format ``["PASSWORD=xxx"]`` or
146+
``{"PASSWORD": "xxx"}``.
144147
145148
Returns:
146149
(generator or str): If ``stream=True``, a generator yielding
@@ -152,7 +155,7 @@ def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
152155
"""
153156
resp = self.client.api.exec_create(
154157
self.id, cmd, stdout=stdout, stderr=stderr, stdin=stdin, tty=tty,
155-
privileged=privileged, user=user
158+
privileged=privileged, user=user, environment=environment
156159
)
157160
return self.client.api.exec_start(
158161
resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket

tests/integration/api_exec_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from docker.utils.socket import read_exactly
33

44
from .base import BaseAPIIntegrationTest, BUSYBOX
5+
from ..helpers import requires_api_version
56

67

78
class ExecTest(BaseAPIIntegrationTest):
@@ -121,3 +122,17 @@ def test_exec_inspect(self):
121122
exec_info = self.client.exec_inspect(exec_id)
122123
self.assertIn('ExitCode', exec_info)
123124
self.assertNotEqual(exec_info['ExitCode'], 0)
125+
126+
@requires_api_version('1.25')
127+
def test_exec_command_with_env(self):
128+
container = self.client.create_container(BUSYBOX, 'cat',
129+
detach=True, stdin_open=True)
130+
id = container['Id']
131+
self.client.start(id)
132+
self.tmp_containers.append(id)
133+
134+
res = self.client.exec_create(id, 'env', environment=["X=Y"])
135+
assert 'Id' in res
136+
137+
exec_log = self.client.exec_start(res)
138+
assert b'X=Y\n' in exec_log

tests/unit/models_containers_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ def test_exec_run(self):
366366
container.exec_run("echo hello world", privileged=True, stream=True)
367367
client.api.exec_create.assert_called_with(
368368
FAKE_CONTAINER_ID, "echo hello world", stdout=True, stderr=True,
369-
stdin=False, tty=False, privileged=True, user=''
369+
stdin=False, tty=False, privileged=True, user='', environment=None
370370
)
371371
client.api.exec_start.assert_called_with(
372372
FAKE_EXEC_ID, detach=False, tty=False, stream=True, socket=False

0 commit comments

Comments
 (0)