Kaydet (Commit) 6b8dfe42 authored tarafından Joffrey F's avatar Joffrey F

Retrieve container logs before container exits / is removed

Signed-off-by: 's avatarJoffrey F <joffrey@docker.com>
üst 8cfd4cb3
...@@ -629,6 +629,9 @@ class ContainerCollection(Collection): ...@@ -629,6 +629,9 @@ class ContainerCollection(Collection):
(e.g. ``SIGINT``). (e.g. ``SIGINT``).
storage_opt (dict): Storage driver options per container as a storage_opt (dict): Storage driver options per container as a
key-value mapping. key-value mapping.
stream (bool): If true and ``detach`` is false, return a log
generator instead of a string. Ignored if ``detach`` is true.
Default: ``False``.
sysctls (dict): Kernel parameters to set in the container. sysctls (dict): Kernel parameters to set in the container.
tmpfs (dict): Temporary filesystems to mount, as a dictionary tmpfs (dict): Temporary filesystems to mount, as a dictionary
mapping a path inside the container to options for that path. mapping a path inside the container to options for that path.
...@@ -696,6 +699,7 @@ class ContainerCollection(Collection): ...@@ -696,6 +699,7 @@ class ContainerCollection(Collection):
""" """
if isinstance(image, Image): if isinstance(image, Image):
image = image.id image = image.id
stream = kwargs.pop('stream', False)
detach = kwargs.pop("detach", False) detach = kwargs.pop("detach", False)
if detach and remove: if detach and remove:
if version_gte(self.client.api._version, '1.25'): if version_gte(self.client.api._version, '1.25'):
...@@ -723,23 +727,28 @@ class ContainerCollection(Collection): ...@@ -723,23 +727,28 @@ class ContainerCollection(Collection):
if detach: if detach:
return container return container
exit_status = container.wait()
if exit_status != 0:
stdout = False
stderr = True
logging_driver = container.attrs['HostConfig']['LogConfig']['Type'] logging_driver = container.attrs['HostConfig']['LogConfig']['Type']
out = None
if logging_driver == 'json-file' or logging_driver == 'journald': if logging_driver == 'json-file' or logging_driver == 'journald':
out = container.logs(stdout=stdout, stderr=stderr) out = container.logs(
else: stdout=stdout, stderr=stderr, stream=True, follow=True
out = None )
exit_status = container.wait()
if exit_status != 0:
out = container.logs(stdout=False, stderr=True)
if remove: if remove:
container.remove() container.remove()
if exit_status != 0: if exit_status != 0:
raise ContainerError(container, exit_status, command, image, out) raise ContainerError(
return out container, exit_status, command, image, out
)
return out if stream or out is None else b''.join(
[line for line in out]
)
def create(self, image, command=None, **kwargs): def create(self, image, command=None, **kwargs):
""" """
......
import docker import docker
import tempfile import tempfile
from .base import BaseIntegrationTest, TEST_API_VERSION from .base import BaseIntegrationTest, TEST_API_VERSION
from ..helpers import random_name from ..helpers import random_name, requires_api_version
class ContainerCollectionTest(BaseIntegrationTest): class ContainerCollectionTest(BaseIntegrationTest):
...@@ -95,7 +95,7 @@ class ContainerCollectionTest(BaseIntegrationTest): ...@@ -95,7 +95,7 @@ class ContainerCollectionTest(BaseIntegrationTest):
"alpine", "echo hello", "alpine", "echo hello",
log_config=dict(type='none') log_config=dict(type='none')
) )
self.assertEqual(out, None) assert out is None
def test_run_with_json_file_driver(self): def test_run_with_json_file_driver(self):
client = docker.from_env(version=TEST_API_VERSION) client = docker.from_env(version=TEST_API_VERSION)
...@@ -104,7 +104,24 @@ class ContainerCollectionTest(BaseIntegrationTest): ...@@ -104,7 +104,24 @@ class ContainerCollectionTest(BaseIntegrationTest):
"alpine", "echo hello", "alpine", "echo hello",
log_config=dict(type='json-file') log_config=dict(type='json-file')
) )
self.assertEqual(out, b'hello\n') assert out == b'hello\n'
@requires_api_version('1.25')
def test_run_with_auto_remove(self):
client = docker.from_env(version=TEST_API_VERSION)
out = client.containers.run(
'alpine', 'echo hello', auto_remove=True
)
assert out == b'hello\n'
def test_run_with_streamed_logs(self):
client = docker.from_env(version=TEST_API_VERSION)
out = client.containers.run(
'alpine', 'sh -c "echo hello && echo world"', stream=True
)
logs = [line for line in out]
assert logs[0] == b'hello\n'
assert logs[1] == b'world\n'
def test_get(self): def test_get(self):
client = docker.from_env(version=TEST_API_VERSION) client = docker.from_env(version=TEST_API_VERSION)
......
...@@ -43,7 +43,7 @@ def make_fake_api_client(): ...@@ -43,7 +43,7 @@ def make_fake_api_client():
fake_api.get_fake_inspect_container()[1], fake_api.get_fake_inspect_container()[1],
'inspect_image.return_value': fake_api.get_fake_inspect_image()[1], 'inspect_image.return_value': fake_api.get_fake_inspect_image()[1],
'inspect_network.return_value': fake_api.get_fake_network()[1], 'inspect_network.return_value': fake_api.get_fake_network()[1],
'logs.return_value': 'hello world\n', 'logs.return_value': [b'hello world\n'],
'networks.return_value': fake_api.get_fake_network_list()[1], 'networks.return_value': fake_api.get_fake_network_list()[1],
'start.return_value': None, 'start.return_value': None,
'wait.return_value': 0, 'wait.return_value': 0,
......
...@@ -12,7 +12,7 @@ class ContainerCollectionTest(unittest.TestCase): ...@@ -12,7 +12,7 @@ class ContainerCollectionTest(unittest.TestCase):
client = make_fake_client() client = make_fake_client()
out = client.containers.run("alpine", "echo hello world") out = client.containers.run("alpine", "echo hello world")
assert out == 'hello world\n' assert out == b'hello world\n'
client.api.create_container.assert_called_with( client.api.create_container.assert_called_with(
image="alpine", image="alpine",
...@@ -24,9 +24,8 @@ class ContainerCollectionTest(unittest.TestCase): ...@@ -24,9 +24,8 @@ class ContainerCollectionTest(unittest.TestCase):
client.api.start.assert_called_with(FAKE_CONTAINER_ID) client.api.start.assert_called_with(FAKE_CONTAINER_ID)
client.api.wait.assert_called_with(FAKE_CONTAINER_ID) client.api.wait.assert_called_with(FAKE_CONTAINER_ID)
client.api.logs.assert_called_with( client.api.logs.assert_called_with(
FAKE_CONTAINER_ID, FAKE_CONTAINER_ID, stderr=False, stdout=True, stream=True,
stderr=False, follow=True
stdout=True
) )
def test_create_container_args(self): def test_create_container_args(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment