Repository: docker-java/docker-java
Pull request #320 (2015-09-11 00:50:15)

This add the support for "since" field for logs command.


Patch:
diff --git a/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
index a97393aa..b1c22283 100644
--- a/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
@@ -18,6 +18,8 @@ import com.github.dockerjava.api.model.Frame;
  *            - true or false, if true, print timestamps for every log line. Defaults to false.
  * @param tail
  *            - `all` or `<number>`, Output specified number of lines at the end of logs
+ * @param since
+ *            - UNIX timestamp (integer) to filter logs. Specifying a timestamp will only output log-entries since that timestamp. Default: 0 (unfiltered)
  */
 public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame> {
 
@@ -33,6 +35,8 @@ public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame>
 
     public boolean hasStderrEnabled();
 
+    public int getSince();
+
     public LogContainerCmd withContainerId(String containerId);
 
     /**
@@ -63,6 +67,8 @@ public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame>
 
     public LogContainerCmd withTail(int tail);
 
+    public LogContainerCmd withSince(int since);
+
     public static interface Exec extends DockerCmdAsyncExec<LogContainerCmd, Frame> {
     }
 
diff --git a/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
index a9d92363..afc6a075 100644
--- a/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
@@ -18,6 +18,8 @@ import com.github.dockerjava.api.model.Frame;
  *            - true or false, if true, print timestamps for every log line. Defaults to false.
  * @param tail
  *            - `all` or `<number>`, Output specified number of lines at the end of logs
+ * @param since
+ *            - UNIX timestamp (integer) to filter logs. Specifying a timestamp will only output log-entries since that timestamp. Default: 0 (unfiltered)
  */
 public class LogContainerCmdImpl extends AbstrAsyncDockerCmd<LogContainerCmd, Frame> implements LogContainerCmd {
 
@@ -27,6 +29,8 @@ public class LogContainerCmdImpl extends AbstrAsyncDockerCmd<LogContainerCmd, Fr
 
     private boolean followStream, timestamps, stdout, stderr;
 
+    private int since = 0;
+
     public LogContainerCmdImpl(LogContainerCmd.Exec exec, String containerId) {
         super(exec);
         withContainerId(containerId);
@@ -62,6 +66,9 @@ public class LogContainerCmdImpl extends AbstrAsyncDockerCmd<LogContainerCmd, Fr
         return stderr;
     }
 
+    @Override
+    public int getSince() {return since; }
+
     @Override
     public LogContainerCmd withContainerId(String containerId) {
         checkNotNull(containerId, "containerId was not specified");
@@ -125,10 +132,18 @@ public class LogContainerCmdImpl extends AbstrAsyncDockerCmd<LogContainerCmd, Fr
         return this;
     }
 
+    @Override
+    public LogContainerCmd withSince(int since) {
+        this.since = since;
+        return this;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder("logs ").append(followStream ? "--follow=true" : "")
-                .append(timestamps ? "--timestamps=true" : "").append(containerId).toString();
+                .append(timestamps ? "--timestamps=true" : "")
+                .append(since > 0 ? "--since=" + since : "")
+                .append(containerId).toString();
     }
 
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
index 0ab3da7a..b2c1691b 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
@@ -31,6 +31,7 @@ public class LogContainerCmdExec extends AbstrAsyncDockerCmdExec<LogContainerCmd
                 .queryParam("stdout", command.hasStdoutEnabled() ? "1" : "0")
                 .queryParam("stderr", command.hasStderrEnabled() ? "1" : "0")
                 .queryParam("follow", command.hasFollowStreamEnabled() ? "1" : "0")
+                .queryParam("since", command.getSince())
                 .queryParam("tail", command.getTail() < 0 ? "all" : "" + command.getTail());
 
         LOGGER.trace("GET: {}", webTarget);


Test patch:
diff --git a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
index 2e2dedb4..16b0266a 100644
--- a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
@@ -62,6 +62,7 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
 
         LogContainerTestCallback loggingCallback = new LogContainerTestCallback();
 
+        //this essentially test the since=0 case
         dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().exec(loggingCallback);
 
         loggingCallback.awaitCompletion();
@@ -69,6 +70,8 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
         assertTrue(loggingCallback.toString().contains(snippet));
     }
 
+
+
     @Test
     public void asyncLogNonExistingContainer() throws Exception {
 
@@ -135,4 +138,30 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
         assertTrue(loggingCallback.toString().contains(snippet));
     }
 
+    @Test
+    public void asyncLogContainerWithSince() throws Exception {
+        String snippet = "hello world";
+
+        CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet)
+                .exec();
+
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+
+        dockerClient.startContainerCmd(container.getId()).exec();
+
+        int exitCode = dockerClient.waitContainerCmd(container.getId()).exec();
+
+        assertThat(exitCode, equalTo(0));
+
+        LogContainerTestCallback loggingCallback = new LogContainerTestCallback();
+
+        int oneMinuteIntoFuture = (int)(System.currentTimeMillis()/1000) + 60;
+        dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().withSince(oneMinuteIntoFuture).exec(loggingCallback);
+
+        loggingCallback.awaitCompletion();
+
+        assertFalse(loggingCallback.toString().contains(snippet));
+    }
+
 }