Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ def events(self, since=None, until=None, filters=None, decode=None):
decode=decode)

def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
stream=False, tty=False):
stream=False, tty=False, exec_id=False):
if utils.compare_version('1.15', self._version) < 0:
raise errors.InvalidVersion('Exec is not supported in API < 1.15')
if isinstance(container, dict):
Expand All @@ -527,25 +527,34 @@ def execute(self, container, cmd, detach=False, stdout=True, stderr=True,

# create the command
url = self._url('/containers/{0}/exec'.format(container))
res = self._post_json(url, data=data)
self._raise_for_status(res)
cmd_res = self._post_json(url, data=data)
self._raise_for_status(cmd_res)

# start the command
cmd_id = res.json().get('Id')
cmd_id = cmd_res.json().get('Id')
res = self._post_json(self._url('/exec/{0}/start'.format(cmd_id)),
data=data, stream=stream)
self._raise_for_status(res)
if stream:
return self._multiplexed_response_stream_helper(res)
out = self._multiplexed_response_stream_helper(res)
elif six.PY3:
return bytes().join(
out = bytes().join(
[x for x in self._multiplexed_buffer_helper(res)]
)
else:
return str().join(
out = str().join(
[x for x in self._multiplexed_buffer_helper(res)]
)

if exec_id:
return out, cmd_res.json().get('Id')
else:
return out

def execute_inspect(self, exec_id):
res = self._get(self._url('/exec/{0}/json'.format(exec_id)))
return self._result(res, True)

def export(self, container):
if isinstance(container, dict):
container = container.get('Id')
Expand Down
19 changes: 18 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ function return a blocking generator you can iterate over to retrieve events as

```python
c.execute(container, cmd, detach=False, stdout=True, stderr=True,
stream=False, tty=False)
stream=False, tty=False, exec_id=False)
```

Execute a command in a running container.
Expand All @@ -279,6 +279,23 @@ running `inspect_container`), unique id or container name.
* stream (bool): indicates whether to return a generator which will yield
the streaming response in chunks.

* exec_id (bool) whether to return the execution id or not as a second value

## execute_inspect

```python
>>> _, exec_id = c.execute(container, cmd, exec_id=True)
>>> info = c.execute_inspect(exec_id)
```

Retrieve information about a previous execute call

**Params**:

* exec_id (str): an execution unique id

**Returns** (urllib3.response.HTTPResponse object): The response from the docker daemon

## export

Export the contents of a filesystem as a tar archive to STDOUT
Expand Down
15 changes: 15 additions & 0 deletions tests/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,21 @@ def runTest(self):
self.assertEqual(res, expected)


@unittest.skipIf(not EXEC_DRIVER_IS_NATIVE, 'Exec driver not native')
class TestExecuteCommandInspect(BaseTestCase):
def runTest(self):
container = self.client.create_container('busybox', 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)

_, exec_id = self.client.execute(id, ['sh', '-c', 'exit 5'],
exec_id=True)
res = self.client.execute_inspect(exec_id)
self.assertEqual(res['ExitCode'], 5)


class TestRunContainerStreaming(BaseTestCase):
def runTest(self):
container = self.client.create_container('busybox', '/bin/sh',
Expand Down