Skip to content

Commit 6e73f04

Browse files
committed
Merge pull request #796 from v-boyko/feature/logs_since
Support the 'since' option in the 'containers/<id>/logs' endpoint (API upgrade)
2 parents c89d366 + 3330569 commit 6e73f04

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-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
@@ -184,7 +185,7 @@ def kill(self, container, signal=None):
184185

185186
@utils.check_resource
186187
def logs(self, container, stdout=True, stderr=True, stream=False,
187-
timestamps=False, tail='all'):
188+
timestamps=False, tail='all', since=None):
188189
if utils.compare_version('1.11', self._version) >= 0:
189190
params = {'stderr': stderr and 1 or 0,
190191
'stdout': stdout and 1 or 0,
@@ -195,6 +196,17 @@ def logs(self, container, stdout=True, stderr=True, stream=False,
195196
if tail != 'all' and (not isinstance(tail, int) or tail < 0):
196197
tail = 'all'
197198
params['tail'] = tail
199+
200+
if since is not None:
201+
if utils.compare_version('1.19', self._version) < 0:
202+
raise errors.InvalidVersion(
203+
'since is not supported in API < 1.19'
204+
)
205+
else:
206+
if isinstance(since, datetime):
207+
params['since'] = utils.datetime_to_timestamp(since)
208+
elif (isinstance(since, int) and since > 0):
209+
params['since'] = since
198210
url = self._url("/containers/{0}/logs", container)
199211
res = self._get(url, params=params, stream=stream)
200212
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, decode_json_header, split_command,
77
) # flake8: noqa

docs/api.md

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

tests/unit/container_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import json
23
import signal
34

@@ -1080,6 +1081,7 @@ def test_log_streaming(self):
10801081
)
10811082

10821083
def test_log_tail(self):
1084+
10831085
with mock.patch('docker.Client.inspect_container',
10841086
fake_inspect_container):
10851087
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
@@ -1094,6 +1096,39 @@ def test_log_tail(self):
10941096
stream=False
10951097
)
10961098

1099+
def test_log_since(self):
1100+
ts = 809222400
1101+
with mock.patch('docker.Client.inspect_container',
1102+
fake_inspect_container):
1103+
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
1104+
since=ts)
1105+
1106+
fake_request.assert_called_with(
1107+
'GET',
1108+
url_prefix + 'containers/3cc2351ab11b/logs',
1109+
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
1110+
'tail': 'all', 'since': ts},
1111+
timeout=DEFAULT_TIMEOUT_SECONDS,
1112+
stream=False
1113+
)
1114+
1115+
def test_log_since_with_datetime(self):
1116+
ts = 809222400
1117+
time = datetime.datetime.utcfromtimestamp(ts)
1118+
with mock.patch('docker.Client.inspect_container',
1119+
fake_inspect_container):
1120+
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
1121+
since=time)
1122+
1123+
fake_request.assert_called_with(
1124+
'GET',
1125+
url_prefix + 'containers/3cc2351ab11b/logs',
1126+
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
1127+
'tail': 'all', 'since': ts},
1128+
timeout=DEFAULT_TIMEOUT_SECONDS,
1129+
stream=False
1130+
)
1131+
10971132
def test_log_tty(self):
10981133
m = mock.Mock()
10991134
with mock.patch('docker.Client.inspect_container',

0 commit comments

Comments
 (0)