summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Labouisse <christophe@labouisse.org>2015-02-06 20:00:04 +0100
committerChristophe Labouisse <christophe@labouisse.org>2015-02-11 07:25:59 +0100
commita07bd28077ce8cd13bfe66c2b74b3b0f76f14d8e (patch)
tree85ea996688b6c5cc6be90c90b3a6cb457db8bc49
parentd0512028be0301325a59bc94831743e628e3108e (diff)
downloaddocker-py-a07bd28077ce8cd13bfe66c2b74b3b0f76f14d8e.tar.gz
Add missing options to the events command
- Add since, until and filters parameters to `Client.events` - Add missing `events`command in the documentation Signed-off-by: Christophe Labouisse <christophe@labouisse.org>
-rw-r--r--docker/client.py22
-rw-r--r--docker/utils/utils.py6
-rw-r--r--docs/api.md22
-rw-r--r--tests/fake_api.py11
-rw-r--r--tests/test.py50
5 files changed, 108 insertions, 3 deletions
diff --git a/docker/client.py b/docker/client.py
index 563fe00..80e53b6 100644
--- a/docker/client.py
+++ b/docker/client.py
@@ -23,6 +23,8 @@ import requests
import requests.exceptions
import six
+from datetime import datetime
+
from .auth import auth
from .unixconn import unixconn
from .ssladapter import ssladapter
@@ -565,8 +567,24 @@ class Client(requests.Session):
return self._result(self._get(self._url("/containers/{0}/changes".
format(container))), True)
- def events(self):
- return self._stream_helper(self.get(self._url('/events'), stream=True))
+ def events(self, since=None, until=None, filters=None):
+ if isinstance(since, datetime):
+ since = utils.datetime_to_timestamp(since)
+
+ if isinstance(until, datetime):
+ until = utils.datetime_to_timestamp(until)
+
+ if filters:
+ filters = utils.convert_filters(filters)
+
+ params = {
+ 'since': since,
+ 'until': until,
+ 'filters': filters
+ }
+
+ return self._stream_helper(self.get(self._url('/events'),
+ params=params, stream=True))
def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
stream=False, tty=False):
diff --git a/docker/utils/utils.py b/docker/utils/utils.py
index fdaf667..ccb8320 100644
--- a/docker/utils/utils.py
+++ b/docker/utils/utils.py
@@ -20,6 +20,7 @@ import tarfile
import tempfile
from distutils.version import StrictVersion
from fnmatch import fnmatch
+from datetime import datetime
import requests
import six
@@ -296,6 +297,11 @@ def convert_filters(filters):
return json.dumps(result)
+def datetime_to_timestamp(dt=datetime.now()):
+ """Convert a datetime in local timezone to a unix timestamp"""
+ return int((dt - datetime.fromtimestamp(0)).total_seconds())
+
+
def create_host_config(
binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False,
diff --git a/docs/api.md b/docs/api.md
index 1d162e9..421e5da 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -229,6 +229,28 @@ Inspect changes on a container's filesystem
**Returns** (str):
+## events
+
+Identical to the `docker events` command: get real time events from the server. The `events`
+function return a blocking generator you can iterate over to retrieve events as they happen.
+
+**Params**:
+
+* since (datetime or int): get events from this point
+
+* until (datetime or int): get events until this point
+
+* filters (dict): filter the events by event time, container or image
+
+**Returns** (generator):
+
+```python
+{"status":"die",
+"id":"container-id",
+"from":"image/with:tag",
+"time":unix-timestamp}
+```
+
## execute
```python
diff --git a/tests/fake_api.py b/tests/fake_api.py
index d311fc1..ab2e4fd 100644
--- a/tests/fake_api.py
+++ b/tests/fake_api.py
@@ -221,6 +221,13 @@ def get_fake_diff():
return status_code, response
+def get_fake_events():
+ status_code = 200
+ response = [{'status': 'stop', 'id': FAKE_CONTAINER_ID,
+ 'from': FAKE_IMAGE_ID, 'time': 1423247867}]
+ return status_code, response
+
+
def get_fake_export():
status_code = 200
response = 'Byte Stream....'
@@ -402,5 +409,7 @@ fake_responses = {
'{1}/{0}/containers/create'.format(CURRENT_VERSION, prefix):
post_fake_create_container,
'{1}/{0}/build'.format(CURRENT_VERSION, prefix):
- post_fake_build_container
+ post_fake_build_container,
+ '{1}/{0}/events'.format(CURRENT_VERSION, prefix):
+ get_fake_events
}
diff --git a/tests/test.py b/tests/test.py
index 5ad3ba9..bd219a8 100644
--- a/tests/test.py
+++ b/tests/test.py
@@ -177,6 +177,56 @@ class DockerClientTest(Cleanup, unittest.TestCase):
except Exception:
pass
+ def test_events(self):
+ try:
+ self.client.events()
+ except Exception as e:
+ self.fail('Command should not raise exception: {0}'.format(e))
+
+ fake_request.assert_called_with(
+ url_prefix + 'events',
+ params={'since': None, 'until': None, 'filters': None},
+ stream=True
+ )
+
+ def test_events_with_since_until(self):
+ now = datetime.datetime.now()
+ since = now - datetime.timedelta(seconds=10)
+ until = now + datetime.timedelta(seconds=10)
+ ts = int((now - datetime.datetime.fromtimestamp(0)).total_seconds())
+ try:
+ self.client.events(since=since, until=until)
+ except Exception as e:
+ self.fail('Command should not raise exception: {0}'.format(e))
+
+ fake_request.assert_called_with(
+ url_prefix + 'events',
+ params={
+ 'since': ts - 10,
+ 'until': ts + 10,
+ 'filters': None
+ },
+ stream=True
+ )
+
+ def test_events_with_filters(self):
+ filters = {'event': ['die', 'stop'], 'container': fake_api.FAKE_CONTAINER_ID}
+ try:
+ self.client.events(filters=filters)
+ except Exception as e:
+ self.fail('Command should not raise exception: {0}'.format(e))
+
+ expected_filters = docker.utils.convert_filters(filters)
+ fake_request.assert_called_with(
+ url_prefix + 'events',
+ params={
+ 'since': None,
+ 'until': None,
+ 'filters': expected_filters
+ },
+ stream=True
+ )
+
###################
# LISTING TESTS #
###################