mirror of https://github.com/docker/docker-py.git
Support the 'since' option in the 'containers/<id>/logs' endpoint
Signed-off-by: Viacheslav Boiko <v.e.boyko@gmail.com>
This commit is contained in:
parent
7884ab9fe2
commit
4a2db828b4
|
@ -1,5 +1,6 @@
|
||||||
import six
|
import six
|
||||||
import warnings
|
import warnings
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from .. import errors
|
from .. import errors
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
@ -163,7 +164,7 @@ class ContainerApiMixin(object):
|
||||||
|
|
||||||
@utils.check_resource
|
@utils.check_resource
|
||||||
def logs(self, container, stdout=True, stderr=True, stream=False,
|
def logs(self, container, stdout=True, stderr=True, stream=False,
|
||||||
timestamps=False, tail='all'):
|
timestamps=False, tail='all', since=None):
|
||||||
if utils.compare_version('1.11', self._version) >= 0:
|
if utils.compare_version('1.11', self._version) >= 0:
|
||||||
params = {'stderr': stderr and 1 or 0,
|
params = {'stderr': stderr and 1 or 0,
|
||||||
'stdout': stdout and 1 or 0,
|
'stdout': stdout and 1 or 0,
|
||||||
|
@ -174,6 +175,17 @@ class ContainerApiMixin(object):
|
||||||
if tail != 'all' and (not isinstance(tail, int) or tail <= 0):
|
if tail != 'all' and (not isinstance(tail, int) or tail <= 0):
|
||||||
tail = 'all'
|
tail = 'all'
|
||||||
params['tail'] = tail
|
params['tail'] = tail
|
||||||
|
|
||||||
|
if since is not None:
|
||||||
|
if utils.compare_version('1.19', self._version) < 0:
|
||||||
|
raise errors.InvalidVersion(
|
||||||
|
'since is not supported in API < 1.19'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if isinstance(since, datetime):
|
||||||
|
params['since'] = utils.datetime_to_timestamp(since)
|
||||||
|
elif (isinstance(since, int) and since > 0):
|
||||||
|
params['since'] = since
|
||||||
url = self._url("/containers/{0}/logs", container)
|
url = self._url("/containers/{0}/logs", container)
|
||||||
res = self._get(url, params=params, stream=stream)
|
res = self._get(url, params=params, stream=stream)
|
||||||
return self._get_result(container, stream, res)
|
return self._get_result(container, stream, res)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from .utils import (
|
from .utils import (
|
||||||
compare_version, convert_port_bindings, convert_volume_binds,
|
compare_version, convert_port_bindings, convert_volume_binds,
|
||||||
mkbuildcontext, tar, exclude_paths, parse_repository_tag, parse_host,
|
mkbuildcontext, tar, exclude_paths, parse_repository_tag, parse_host,
|
||||||
kwargs_from_env, convert_filters, create_host_config,
|
kwargs_from_env, convert_filters, datetime_to_timestamp, create_host_config,
|
||||||
create_container_config, parse_bytes, ping_registry, parse_env_file,
|
create_container_config, parse_bytes, ping_registry, parse_env_file,
|
||||||
version_lt, version_gte
|
version_lt, version_gte
|
||||||
) # flake8: noqa
|
) # flake8: noqa
|
||||||
|
|
|
@ -325,6 +325,7 @@ Sets up an exec instance in a running container.
|
||||||
* cmd (str or list): Command to be executed
|
* cmd (str or list): Command to be executed
|
||||||
* stdout (bool): Attach to stdout of the exec command if true. Default: True
|
* stdout (bool): Attach to stdout of the exec command if true. Default: True
|
||||||
* stderr (bool): Attach to stderr of the exec command if true. Default: True
|
* stderr (bool): Attach to stderr of the exec command if true. Default: True
|
||||||
|
* since (UTC datetime or int): Output logs from this timestamp. Default: `None` (all logs are given)
|
||||||
* tty (bool): Allocate a pseudo-TTY. Default: False
|
* tty (bool): Allocate a pseudo-TTY. Default: False
|
||||||
* user (str): User to execute command as. Default: root
|
* user (str): User to execute command as. Default: root
|
||||||
|
|
||||||
|
|
|
@ -1439,6 +1439,7 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_log_tail(self):
|
def test_log_tail(self):
|
||||||
|
|
||||||
with mock.patch('docker.Client.inspect_container',
|
with mock.patch('docker.Client.inspect_container',
|
||||||
fake_inspect_container):
|
fake_inspect_container):
|
||||||
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
|
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
|
||||||
|
@ -1453,6 +1454,39 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
|
||||||
stream=False
|
stream=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_log_since(self):
|
||||||
|
ts = 809222400
|
||||||
|
with mock.patch('docker.Client.inspect_container',
|
||||||
|
fake_inspect_container):
|
||||||
|
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
|
||||||
|
since=ts)
|
||||||
|
|
||||||
|
fake_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
url_prefix + 'containers/3cc2351ab11b/logs',
|
||||||
|
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
|
||||||
|
'tail': 'all', 'since': ts},
|
||||||
|
timeout=DEFAULT_TIMEOUT_SECONDS,
|
||||||
|
stream=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_log_since_with_datetime(self):
|
||||||
|
ts = 809222400
|
||||||
|
time = datetime.datetime.utcfromtimestamp(ts)
|
||||||
|
with mock.patch('docker.Client.inspect_container',
|
||||||
|
fake_inspect_container):
|
||||||
|
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
|
||||||
|
since=time)
|
||||||
|
|
||||||
|
fake_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
url_prefix + 'containers/3cc2351ab11b/logs',
|
||||||
|
params={'timestamps': 0, 'follow': 0, 'stderr': 1, 'stdout': 1,
|
||||||
|
'tail': 'all', 'since': ts},
|
||||||
|
timeout=DEFAULT_TIMEOUT_SECONDS,
|
||||||
|
stream=False
|
||||||
|
)
|
||||||
|
|
||||||
def test_log_tty(self):
|
def test_log_tty(self):
|
||||||
m = mock.Mock()
|
m = mock.Mock()
|
||||||
with mock.patch('docker.Client.inspect_container',
|
with mock.patch('docker.Client.inspect_container',
|
||||||
|
|
Loading…
Reference in New Issue