Skip to content

Commit 4a2db82

Browse files
author
Viacheslav Boiko
committed
Support the 'since' option in the 'containers/<id>/logs' endpoint
Signed-off-by: Viacheslav Boiko <[email protected]>
1 parent 7884ab9 commit 4a2db82

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

docker/api/container.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import six
22
import warnings
3+
from datetime import datetime
34

45
from .. import errors
56
from .. import utils
@@ -163,7 +164,7 @@ def kill(self, container, signal=None):
163164

164165
@utils.check_resource
165166
def logs(self, container, stdout=True, stderr=True, stream=False,
166-
timestamps=False, tail='all'):
167+
timestamps=False, tail='all', since=None):
167168
if utils.compare_version('1.11', self._version) >= 0:
168169
params = {'stderr': stderr and 1 or 0,
169170
'stdout': stdout and 1 or 0,
@@ -174,6 +175,17 @@ def logs(self, container, stdout=True, stderr=True, stream=False,
174175
if tail != 'all' and (not isinstance(tail, int) or tail <= 0):
175176
tail = 'all'
176177
params['tail'] = tail
178+
179+
if since is not None:
180+
if utils.compare_version('1.19', self._version) < 0:
181+
raise errors.InvalidVersion(
182+
'since is not supported in API < 1.19'
183+
)
184+
else:
185+
if isinstance(since, datetime):
186+
params['since'] = utils.datetime_to_timestamp(since)
187+
elif (isinstance(since, int) and since > 0):
188+
params['since'] = since
177189
url = self._url("/containers/{0}/logs", container)
178190
res = self._get(url, params=params, stream=stream)
179191
return self._get_result(container, stream, res)

docker/utils/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from .utils import (
22
compare_version, convert_port_bindings, convert_volume_binds,
33
mkbuildcontext, tar, exclude_paths, parse_repository_tag, parse_host,
4-
kwargs_from_env, convert_filters, create_host_config,
4+
kwargs_from_env, convert_filters, datetime_to_timestamp, create_host_config,
55
create_container_config, parse_bytes, ping_registry, parse_env_file,
66
version_lt, version_gte
77
) # flake8: noqa

docs/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ Sets up an exec instance in a running container.
325325
* cmd (str or list): Command to be executed
326326
* stdout (bool): Attach to stdout of the exec command if true. Default: True
327327
* stderr (bool): Attach to stderr of the exec command if true. Default: True
328+
* since (UTC datetime or int): Output logs from this timestamp. Default: `None` (all logs are given)
328329
* tty (bool): Allocate a pseudo-TTY. Default: False
329330
* user (str): User to execute command as. Default: root
330331

tests/test.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,7 @@ def test_log_streaming(self):
14391439
)
14401440

14411441
def test_log_tail(self):
1442+
14421443
with mock.patch('docker.Client.inspect_container',
14431444
fake_inspect_container):
14441445
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
@@ -1453,6 +1454,39 @@ def test_log_tail(self):
14531454
stream=False
14541455
)
14551456

1457+
def test_log_since(self):
1458+
ts = 809222400
1459+
with mock.patch('docker.Client.inspect_container',
1460+
fake_inspect_container):
1461+
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
1462+
since=ts)
1463+
1464+
fake_request.assert_called_with(
1465+
'GET',
1466+
url_prefix + 'containers/3cc2351ab11b/logs',
1467+
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
1468+
'tail': 'all', 'since': ts},
1469+
timeout=DEFAULT_TIMEOUT_SECONDS,
1470+
stream=False
1471+
)
1472+
1473+
def test_log_since_with_datetime(self):
1474+
ts = 809222400
1475+
time = datetime.datetime.utcfromtimestamp(ts)
1476+
with mock.patch('docker.Client.inspect_container',
1477+
fake_inspect_container):
1478+
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
1479+
since=time)
1480+
1481+
fake_request.assert_called_with(
1482+
'GET',
1483+
url_prefix + 'containers/3cc2351ab11b/logs',
1484+
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
1485+
'tail': 'all', 'since': ts},
1486+
timeout=DEFAULT_TIMEOUT_SECONDS,
1487+
stream=False
1488+
)
1489+
14561490
def test_log_tty(self):
14571491
m = mock.Mock()
14581492
with mock.patch('docker.Client.inspect_container',

0 commit comments

Comments
 (0)