Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.github.dockerjava.api.command;

import com.github.dockerjava.api.NotFoundException;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.model.BuildResponseItem;
import com.github.dockerjava.api.model.WaitResponse;

/**
* Wait a container
*
* Block until container stops, then returns its exit code
*/
public interface WaitContainerCmd extends SyncDockerCmd<Integer> {
public interface WaitContainerCmd extends AsyncDockerCmd<WaitContainerCmd, WaitResponse> {

public String getContainerId();

Expand All @@ -18,9 +21,9 @@ public interface WaitContainerCmd extends SyncDockerCmd<Integer> {
* container not found
*/
@Override
public Integer exec() throws NotFoundException;
public <T extends ResultCallback<WaitResponse>> T exec(T resultCallback);

public static interface Exec extends DockerCmdSyncExec<WaitContainerCmd, Integer> {
public static interface Exec extends DockerCmdAsyncExec<WaitContainerCmd, WaitResponse> {
}

}
19 changes: 19 additions & 0 deletions src/main/java/com/github/dockerjava/api/model/WaitResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.dockerjava.api.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;


/**
* Represents a wait container command response
*/
@JsonIgnoreProperties(ignoreUnknown = false)
public class WaitResponse {

@JsonProperty("StatusCode")
private Integer statusCode;

public Integer getStatusCode() {
return statusCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import javax.annotation.CheckForNull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.dockerjava.api.async.ResultCallback;
import com.google.common.base.Throwables;

/**
* Abstract template implementation of {@link ResultCallback}
Expand All @@ -30,6 +33,8 @@ public abstract class ResultCallbackTemplate<RC_T extends ResultCallback<A_RES_T

private boolean closed = false;

private Throwable firstError = null;

@Override
public void onStart(Closeable stream) {
this.stream = stream;
Expand All @@ -38,12 +43,15 @@ public void onStart(Closeable stream) {

@Override
public void onError(Throwable throwable) {

if (closed)
return;

if (this.firstError == null)
this.firstError = throwable;

try {
LOGGER.error("Error during callback", throwable);
throw new RuntimeException(throwable);
} finally {
try {
close();
Expand Down Expand Up @@ -76,6 +84,8 @@ public void close() throws IOException {
@SuppressWarnings("unchecked")
public RC_T awaitCompletion() throws InterruptedException {
completed.await();
// eventually (re)throws RuntimeException
getFirstError();
return (RC_T) this;
}

Expand All @@ -87,4 +97,14 @@ public RC_T awaitCompletion(long timeout, TimeUnit timeUnit) throws InterruptedE
completed.await(timeout, timeUnit);
return (RC_T) this;
}

@CheckForNull
protected RuntimeException getFirstError() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually mark @CheckForNull and @Nonnull to know what logic about nullness i implemented in method.

if (firstError != null) {
// this call throws a RuntimeException
return Throwables.propagate(firstError);
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import static com.google.common.base.Preconditions.checkNotNull;

import com.github.dockerjava.api.command.WaitContainerCmd;
import com.github.dockerjava.api.model.WaitResponse;

/**
* Wait a container
*
*
* Block until container stops, then returns its exit code
*/
public class WaitContainerCmdImpl extends AbstrDockerCmd<WaitContainerCmd, Integer> implements WaitContainerCmd {
public class WaitContainerCmdImpl extends AbstrAsyncDockerCmd<WaitContainerCmd, WaitResponse> implements WaitContainerCmd {

private String containerId;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Created on 21.07.2015
*/
package com.github.dockerjava.core.command;

import java.util.concurrent.TimeUnit;

import javax.annotation.CheckForNull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.dockerjava.api.DockerClientException;
import com.github.dockerjava.api.model.WaitResponse;
import com.github.dockerjava.core.async.ResultCallbackTemplate;
import com.google.common.base.Throwables;

/**
*
* @author marcus
*
*/
public class WaitContainerResultCallback extends ResultCallbackTemplate<WaitContainerResultCallback, WaitResponse> {

private final static Logger LOGGER = LoggerFactory.getLogger(WaitContainerResultCallback.class);

@CheckForNull
private WaitResponse waitResponse = null;

@Override
public void onNext(WaitResponse waitResponse) {
this.waitResponse = waitResponse;
LOGGER.debug(waitResponse.toString());
}

/**
* Awaits the status code from the container.
*
* @throws DockerClientException
* if the wait operation fails.
*/
public Integer awaitStatusCode() {
try {
awaitCompletion();
} catch (InterruptedException e) {
throw new DockerClientException("", e);
}

return getStatusCode();
}

/**
* Awaits the status code from the container.
*
* @throws DockerClientException
* if the wait operation fails.
*/
public Integer awaitStatusCode(long timeout, TimeUnit timeUnit) {
try {
awaitCompletion(timeout, timeUnit);
} catch (InterruptedException e) {
throw new DockerClientException("Awaiting status code interrupted: ", e);
}

return getStatusCode();
}

private Integer getStatusCode() {
if (waitResponse == null) {
throw new DockerClientException("Error while wait container");
} else {
return waitResponse.getStatusCode();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package com.github.dockerjava.jaxrs;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.dockerjava.api.command.WaitContainerCmd;
import com.github.dockerjava.core.DockerClientConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static javax.ws.rs.client.Entity.entity;

import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;

public class WaitContainerCmdExec extends AbstrSyncDockerCmdExec<WaitContainerCmd, Integer> implements
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.WaitContainerCmd;
import com.github.dockerjava.api.model.WaitResponse;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.async.JsonStreamProcessor;
import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier;

public class WaitContainerCmdExec extends AbstrAsyncDockerCmdExec<WaitContainerCmd, WaitResponse> implements
WaitContainerCmd.Exec {

private static final Logger LOGGER = LoggerFactory.getLogger(WaitContainerCmdExec.class);
Expand All @@ -19,14 +26,16 @@ public WaitContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerCli
}

@Override
protected Integer execute(WaitContainerCmd command) {
protected AbstractCallbackNotifier<WaitResponse> callbackNotifier(WaitContainerCmd command,
ResultCallback<WaitResponse> resultCallback) {

WebTarget webResource = getBaseResource().path("/containers/{id}/wait").resolveTemplate("id",
command.getContainerId());

LOGGER.trace("POST: {}", webResource);
ObjectNode ObjectNode = webResource.request().accept(MediaType.APPLICATION_JSON).post(null, ObjectNode.class);

return ObjectNode.get("StatusCode").asInt();
return new POSTCallbackNotifier<WaitResponse>(new JsonStreamProcessor<WaitResponse>(
WaitResponse.class), resultCallback, webResource.request().accept(MediaType.APPLICATION_JSON), entity(null, MediaType.APPLICATION_JSON));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import com.github.dockerjava.api.DockerException;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.core.command.WaitContainerResultCallback;

/**
* Unit test for DockerClient.
Expand Down Expand Up @@ -61,7 +62,7 @@ public void testRunShlex() throws DockerException {
CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd(commands).exec();
dockerClient.startContainerCmd(container.getId());

int exitcode = dockerClient.waitContainerCmd(container.getId()).exec();
int exitcode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();
assertThat(exitcode, equalTo(0));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ private String execBuild(BuildImageCmd buildImageCmd) throws Exception {
assertThat(container.getId(), not(isEmptyString()));

dockerClient.startContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();

return containerLog(container.getId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void testContainerDiff() throws DockerException {
assertThat(container.getId(), not(isEmptyString()));
dockerClient.startContainerCmd(container.getId()).exec();

int exitCode = dockerClient.waitContainerCmd(container.getId()).exec();
int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();
assertThat(exitCode, equalTo(0));

List<ChangeLog> filesystemDiff = dockerClient.containerDiffCmd(container.getId()).exec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public void deleteDockerContainerImage() throws Exception {
public void canCloseFrameReaderAndReadExpectedLines() throws Exception {

// wait for the container to be successfully executed
int exitCode = dockerClient.waitContainerCmd(dockerfileFixture.getContainerId()).exec();
int exitCode = dockerClient.waitContainerCmd(dockerfileFixture.getContainerId())
.exec(new WaitContainerResultCallback()).awaitStatusCode();
assertEquals(0, exitCode);

Iterator<Frame> response = getLoggingFrames().iterator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import com.github.dockerjava.api.NotFoundException;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.client.AbstractDockerClientTest;

@Test(groups = "integration")
Expand Down Expand Up @@ -56,7 +55,8 @@ public void asyncLogContainer() throws Exception {

dockerClient.startContainerCmd(container.getId()).exec();

int exitCode = dockerClient.waitContainerCmd(container.getId()).exec();
int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback())
.awaitStatusCode();

assertThat(exitCode, equalTo(0));

Expand All @@ -80,7 +80,7 @@ public void onError(Throwable throwable) {
assertEquals(throwable.getClass().getName(), NotFoundException.class.getName());

try {
// close the callback to prevent the call to onFinish
// close the callback to prevent the call to onComplete
close();
} catch (IOException e) {
throw new RuntimeException();
Expand Down Expand Up @@ -111,7 +111,8 @@ public void asyncMultipleLogContainer() throws Exception {

dockerClient.startContainerCmd(container.getId()).exec();

int exitCode = dockerClient.waitContainerCmd(container.getId()).exec();
int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback())
.awaitStatusCode();

assertThat(exitCode, equalTo(0));

Expand Down Expand Up @@ -150,7 +151,8 @@ public void asyncLogContainerWithSince() throws Exception {

dockerClient.startContainerCmd(container.getId()).exec();

int exitCode = dockerClient.waitContainerCmd(container.getId()).exec();
int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback())
.awaitStatusCode();

assertThat(exitCode, equalTo(0));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void removeContainer() throws DockerException {
CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true").exec();

dockerClient.startContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();

LOG.info("Removing container: {}", container.getId());
dockerClient.removeContainerCmd(container.getId()).exec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void startContainerWithVolumes() throws DockerException {

dockerClient.startContainerCmd(container.getId()).exec();

dockerClient.waitContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();

inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec();

Expand Down
Loading