Repository: docker/docker-py
Issue: docker.Client.logs(tail=0) returns all logs instead of no logs

This is a confusing behavior.  It also makes it harder to follow a container's logs (with `stream=True`) without getting at least some old log data.  A work-around is required, specifying `tail=1` and then discarding the first line of output.


Changed files:
docker/api/container.py, tests/integration/container_test.py

diff --git a/docker/api/container.py b/docker/api/container.py
index 142bd0f6..f3f85e8d 100644
--- a/docker/api/container.py
+++ b/docker/api/container.py
@@ -192,7 +192,7 @@ class ContainerApiMixin(object):
                       'follow': stream and 1 or 0,
                       }
             if utils.compare_version('1.13', self._version) >= 0:
-                if tail != 'all' and (not isinstance(tail, int) or tail <= 0):
+                if tail != 'all' and (not isinstance(tail, int) or tail < 0):
                     tail = 'all'
                 params['tail'] = tail
             url = self._url("/containers/{0}/logs", container)
diff --git a/tests/integration/container_test.py b/tests/integration/container_test.py
index 9606e14b..3340e4b2 100644
--- a/tests/integration/container_test.py
+++ b/tests/integration/container_test.py
@@ -613,8 +613,8 @@ class LogsTest(api_test.BaseTestCase):
             BUSYBOX, 'echo {0}'.format(snippet)
         )
         id = container['Id']
-        self.client.start(id)
         self.tmp_containers.append(id)
+        self.client.start(id)
         exitcode = self.client.wait(id)
         self.assertEqual(exitcode, 0)
         logs = self.client.logs(id)
@@ -627,29 +627,29 @@ Line2'''
             BUSYBOX, 'echo "{0}"'.format(snippet)
         )
         id = container['Id']
-        self.client.start(id)
         self.tmp_containers.append(id)
+        self.client.start(id)
         exitcode = self.client.wait(id)
         self.assertEqual(exitcode, 0)
         logs = self.client.logs(id, tail=1)
-        self.assertEqual(logs, ('Line2\\n').encode(encoding='ascii'))
+        self.assertEqual(logs, 'Line2\\n'.encode(encoding='ascii'))
 
-#     def test_logs_streaming(self):
-#         snippet = 'Flowering Nights (Sakuya Iyazoi)'
-#         container = self.client.create_container(
-#             BUSYBOX, 'echo {0}'.format(snippet)
-#         )
-#         id = container['Id']
-#         self.client.start(id)
-#         self.tmp_containers.append(id)
-#         logs = bytes() if six.PY3 else str()
-#         for chunk in self.client.logs(id, stream=True):
-#             logs += chunk
+    def test_logs_streaming(self):
+        snippet = 'Flowering Nights (Sakuya Iyazoi)'
+        container = self.client.create_container(
+            BUSYBOX, 'echo {0}'.format(snippet)
+        )
+        id = container['Id']
+        self.tmp_containers.append(id)
+        self.client.start(id)
+        logs = six.binary_type()
+        for chunk in self.client.logs(id, stream=True):
+            logs += chunk
 
-#         exitcode = self.client.wait(id)
-#         self.assertEqual(exitcode, 0)
+        exitcode = self.client.wait(id)
+        self.assertEqual(exitcode, 0)
 
-#         self.assertEqual(logs, (snippet + '\\n').encode(encoding='ascii'))
+        self.assertEqual(logs, (snippet + '\\n').encode(encoding='ascii'))
 
     def test_logs_with_dict_instead_of_id(self):
         snippet = 'Flowering Nights (Sakuya Iyazoi)'
@@ -657,13 +657,26 @@ Line2'''
             BUSYBOX, 'echo {0}'.format(snippet)
         )
         id = container['Id']
-        self.client.start(id)
         self.tmp_containers.append(id)
+        self.client.start(id)
         exitcode = self.client.wait(id)
         self.assertEqual(exitcode, 0)
         logs = self.client.logs(container)
         self.assertEqual(logs, (snippet + '\\n').encode(encoding='ascii'))
 
+    def test_logs_with_tail_0(self):
+        snippet = 'Flowering Nights (Sakuya Iyazoi)'
+        container = self.client.create_container(
+            BUSYBOX, 'echo "{0}"'.format(snippet)
+        )
+        id = container['Id']
+        self.tmp_containers.append(id)
+        self.client.start(id)
+        exitcode = self.client.wait(id)
+        self.assertEqual(exitcode, 0)
+        logs = self.client.logs(id, tail=0)
+        self.assertEqual(logs, ''.encode(encoding='ascii'))
+
 
 class DiffTest(api_test.BaseTestCase):
     def test_diff(self):