diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java index 3117cf7e4..7b910cd69 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java @@ -2,9 +2,11 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.github.dockerjava.api.async.ResultCallback; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; /** @@ -20,8 +22,20 @@ public interface WaitContainerCmd extends AsyncDockerCmd> T exec(T resultCallback); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java new file mode 100644 index 000000000..8af0efa35 --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java @@ -0,0 +1,26 @@ +package com.github.dockerjava.api.model; + +import javax.annotation.Nonnull; + +/** + * Docker Engine API wait conditions (added in v1.30). + * + * @since {@link RemoteApiVersion#VERSION_1_30} + */ +public enum WaitContainerCondition { + NOT_RUNNING("not-running"), + NEXT_EXIT("next-exit"), + REMOVED("removed"); + + @Nonnull + private final String value; + + WaitContainerCondition(@Nonnull String value) { + this.value = value; + } + + @Nonnull + public String getValue() { + return value; + } +} diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java index 91b2255bc..b627e2ccd 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java @@ -2,7 +2,10 @@ import java.util.Objects; +import javax.annotation.Nullable; + import com.github.dockerjava.api.command.WaitContainerCmd; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; /** @@ -15,6 +18,8 @@ public class WaitContainerCmdImpl extends AbstrAsyncDockerCmd r WebTarget webTarget = getBaseResource().path("/containers/{id}/wait").resolveTemplate("id", command.getContainerId()); + WaitContainerCondition condition = command.getCondition(); + if (condition != null) { + webTarget = webTarget.queryParam("condition", condition.getValue()); + } + LOGGER.trace("POST: {}", webTarget); webTarget.request().accept(MediaType.APPLICATION_JSON).post((Object) null, new TypeReference() { diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java index e2ad2a643..3a39b3eea 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java @@ -8,18 +8,25 @@ import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; +import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; +import static com.github.dockerjava.api.model.HostConfig.newHostConfig; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_25; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_30; +import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.not; +import static org.junit.Assume.assumeThat; public class WaitContainerCmdIT extends CmdIT { public static final Logger LOG = LoggerFactory.getLogger(BuildImageCmd.class); @@ -102,4 +109,77 @@ public void testWaitContainerTimeout() { LOG.info(e.getMessage()); } } + + @Test + public void testWaitNotStartedContainer() { + assumeThat("API version should be > 1.25", dockerRule, isGreaterOrEqual(VERSION_1_25)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withHostConfig(newHostConfig().withAutoRemove(true)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback callback = dockerRule.getClient().waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()); + + Integer statusCode = callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(0, statusCode.intValue()); + } + + @Test + public void testWaitContainerWithAutoRemoval() { + assumeThat("API version should be > 1.30", dockerRule, isGreaterOrEqual(VERSION_1_30)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("false") + .withHostConfig(newHostConfig().withAutoRemove(true)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback removedCondition = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.REMOVED) + .exec(new WaitContainerResultCallback()); + + WaitContainerResultCallback nextExitCondition = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Assert.assertEquals(1, removedCondition.awaitStatusCode(100, TimeUnit.MILLISECONDS).intValue()); + Assert.assertEquals(1, nextExitCondition.awaitStatusCode(100, TimeUnit.MILLISECONDS).intValue()); + } + + @Test + public void testWaitRestartedContainer() { + assumeThat("API version should be > 1.30", dockerRule, isGreaterOrEqual(VERSION_1_30)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("sh", "-c", "[ -f \"$HOME/.first_run_marker\" ] && exit 2 || { touch \"$HOME/.first_run_marker\"; exit 1; }") + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback firstExitCallback = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Integer firstStatusCode = firstExitCallback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(1, firstStatusCode.intValue()); + + WaitContainerResultCallback callback = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Integer statusCode = callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(2, statusCode.intValue()); + } }