diff --git a/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java b/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java index 184b7ef33..d500d3078 100644 --- a/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java @@ -1,11 +1,13 @@ package com.github.dockerjava.api.command; +import com.github.dockerjava.api.model.LoadImageResponseItem; + import java.io.InputStream; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; -public interface LoadImageCmd extends SyncDockerCmd { +public interface LoadImageCmd extends AsyncDockerCmd { @CheckForNull InputStream getImageStream(); @@ -16,6 +18,11 @@ public interface LoadImageCmd extends SyncDockerCmd { */ LoadImageCmd withImageStream(@Nonnull InputStream imageStream); - interface Exec extends DockerCmdSyncExec { + @CheckForNull + Boolean getQuiet(); + + LoadImageCmd withQuiet(Boolean quiet); + + interface Exec extends DockerCmdAsyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java index a53a1df9a..ea29b8c34 100644 --- a/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java +++ b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import javax.annotation.CheckForNull; + /** * Represents a build response stream item */ @@ -25,6 +27,7 @@ public boolean isBuildSuccessIndicated() { return getStream().contains(BUILD_SUCCESS); } + @CheckForNull @JsonIgnore public String getImageId() { if (!isBuildSuccessIndicated()) { diff --git a/src/main/java/com/github/dockerjava/api/model/LoadImageResponseItem.java b/src/main/java/com/github/dockerjava/api/model/LoadImageResponseItem.java new file mode 100644 index 000000000..dfe8a4716 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/LoadImageResponseItem.java @@ -0,0 +1,23 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * @author Kanstantsin Shautsou + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class LoadImageResponseItem extends ResponseItem { + private static final long serialVersionUID = 1L; + + private static final String LOAD_SUCCESS = "Loaded image:"; + + @JsonIgnore + public boolean isLoadedOK() { + if (isErrorIndicated() || getStream() == null) { + return false; + } + + return getStream().contains(LOAD_SUCCESS); + } +} diff --git a/src/main/java/com/github/dockerjava/core/command/LoadImageCallback.java b/src/main/java/com/github/dockerjava/core/command/LoadImageCallback.java new file mode 100644 index 000000000..5702b4276 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/LoadImageCallback.java @@ -0,0 +1,39 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.exception.DockerClientException; +import com.github.dockerjava.api.model.LoadImageResponseItem; +import com.github.dockerjava.core.async.ResultCallbackTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.CheckForNull; + +/** + * @author Kanstantsin Shautsou + */ +public class LoadImageCallback extends ResultCallbackTemplate { + private static final Logger LOG = LoggerFactory.getLogger(LoadImageCallback.class); + + @CheckForNull + protected LoadImageResponseItem latestItem = null; + + @Override + public void onNext(LoadImageResponseItem responseItem) { + this.latestItem = responseItem; + LOG.debug(responseItem.toString()); + } + + public void awaitSuccess() { + try { + awaitCompletion(); + } catch (InterruptedException e) { + throw new DockerClientException("Interrupted", e); + } + + if (latestItem == null) { + throw new DockerClientException("Could not load image"); + } else if (latestItem.isErrorIndicated()) { + throw new DockerClientException("Could not load image: " + latestItem.getErrorDetail()); + } + } +} diff --git a/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java index 496ea3176..92da3030e 100644 --- a/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java @@ -5,16 +5,19 @@ import java.io.InputStream; import com.github.dockerjava.api.command.LoadImageCmd; +import com.github.dockerjava.api.model.LoadImageResponseItem; import javax.annotation.Nonnull; -public class LoadImageCmdImpl extends AbstrDockerCmd implements LoadImageCmd { +public class LoadImageCmdImpl extends AbstrAsyncDockerCmd implements LoadImageCmd { private InputStream imageStream; + // set false because in quiet mode it returns not JSON! + private Boolean quiet = false; + /** - * @param imageStream - * the InputStream of the tar file + * @param imageStream the InputStream of the tar file */ public LoadImageCmdImpl(LoadImageCmd.Exec exec, InputStream imageStream) { super(exec); @@ -26,9 +29,19 @@ public InputStream getImageStream() { return imageStream; } + @Override + public Boolean getQuiet() { + return quiet; + } + + @Override + public LoadImageCmd withQuiet(Boolean quiet) { + this.quiet = quiet; + return this; + } + /** - * @param imageStream - * the InputStream of the tar file + * @param imageStream the InputStream of the tar file */ @Override public LoadImageCmdImpl withImageStream(@Nonnull InputStream imageStream) { diff --git a/src/main/java/com/github/dockerjava/core/command/PushImageResultCallback.java b/src/main/java/com/github/dockerjava/core/command/PushImageResultCallback.java index 55dfb5650..5a715ae6f 100644 --- a/src/main/java/com/github/dockerjava/core/command/PushImageResultCallback.java +++ b/src/main/java/com/github/dockerjava/core/command/PushImageResultCallback.java @@ -46,7 +46,7 @@ public void awaitSuccess() { if (latestItem == null) { throw new DockerClientException("Could not push image"); } else if (latestItem.isErrorIndicated()) { - throw new DockerClientException("Could not push image: " + latestItem.getError()); + throw new DockerClientException("Could not push image: " + latestItem.getErrorDetail()); } } } diff --git a/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java index 23d6c493a..9e53f4910 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java @@ -5,13 +5,20 @@ import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; +import com.github.dockerjava.api.async.ResultCallback; +import com.github.dockerjava.api.model.LoadImageResponseItem; +import com.github.dockerjava.core.async.JsonStreamProcessor; +import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier; +import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.RequestEntityProcessing; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.core.DockerClientConfig; -public class LoadImageCmdExec extends AbstrSyncDockerCmdExec implements LoadImageCmd.Exec { +public class LoadImageCmdExec extends AbstrAsyncDockerCmdExec implements LoadImageCmd.Exec { private static final Logger LOGGER = LoggerFactory.getLogger(LoadImageCmdExec.class); @@ -20,12 +27,24 @@ public LoadImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientC } @Override - protected Void execute(LoadImageCmd command) { + protected AbstractCallbackNotifier callbackNotifier(LoadImageCmd command, ResultCallback resultCallback) { WebTarget webTarget = getBaseResource().path("/images/load"); - LOGGER.trace("POST: {}", webTarget); - webTarget.request().post(entity(command.getImageStream(), MediaType.APPLICATION_OCTET_STREAM)); + if (command.getQuiet() != null) { + webTarget = webTarget.queryParam("quiet", command.getQuiet()); + } + + webTarget.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED); + webTarget.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024 * 1024); - return null; + LOGGER.trace("POST: {}", webTarget); +// webTarget.request() +// .post(entity(command.getImageStream(), MediaType.APPLICATION_OCTET_STREAM)); + + return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(LoadImageResponseItem.class), + resultCallback, + webTarget.request().accept(MediaType.TEXT_PLAIN), + entity(command.getImageStream(), "application/tar") + ); } } diff --git a/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java index 23581119f..a5bc92d57 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java @@ -1,5 +1,9 @@ package com.github.dockerjava.netty.exec; +import com.github.dockerjava.api.async.ResultCallback; +import com.github.dockerjava.api.model.LoadImageResponseItem; +import com.github.dockerjava.netty.InvocationBuilder; +import com.github.dockerjava.netty.MediaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,7 +12,7 @@ import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.netty.WebTarget; -public class LoadImageCmdExec extends AbstrSyncDockerCmdExec implements +public class LoadImageCmdExec extends AbstrAsyncDockerCmdExec implements LoadImageCmd.Exec { private static final Logger LOGGER = LoggerFactory.getLogger(LoadImageCmdExec.class); @@ -18,12 +22,22 @@ public LoadImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientC } @Override - protected Void execute(LoadImageCmd command) { + protected Void execute0(LoadImageCmd command, ResultCallback resultCallback) { WebTarget webResource = getBaseResource().path("/images/load"); + if (command.getQuiet() != null) { + webResource = webResource.queryParam("quiet", command.getQuiet()); + } + LOGGER.trace("POST: {}", webResource); - return webResource.request() - .post(new TypeReference() { - }, command.getImageStream()); + final InvocationBuilder builder = webResource.request() + .accept(MediaType.APPLICATION_JSON) + .header("Content-Type", "application/tar") + .header("encoding", "gzip"); + + builder.post(new TypeReference() { + }, resultCallback, command.getImageStream()); + + return null; } } diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index 46d6d4dcc..3e34f23eb 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -58,6 +58,8 @@ import com.github.dockerjava.api.command.VersionCmd; import com.github.dockerjava.api.command.WaitContainerCmd; import com.github.dockerjava.api.model.BuildResponseItem; +import com.github.dockerjava.api.model.LoadImageResponseItem; +import com.github.dockerjava.core.command.LoadImageCallback; import java.io.IOException; import java.security.SecureRandom; @@ -136,8 +138,8 @@ public CreateImageResponse exec(CreateImageCmd command) { public LoadImageCmd.Exec createLoadImageCmdExec() { return new LoadImageCmd.Exec() { @Override - public Void exec(LoadImageCmd command) { - delegate.createLoadImageCmdExec().exec(command); + public Void exec(LoadImageCmd command, ResultCallback resultCallback) { + delegate.createLoadImageCmdExec().exec(command, new LoadImageCallback()); return null; } }; diff --git a/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java index 7cecf7334..1d2e9f98c 100644 --- a/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java @@ -55,7 +55,7 @@ public void afterMethod(ITestResult result) { @Test public void loadImageFromTar() throws Exception { try (InputStream uploadStream = Files.newInputStream(TestResources.getApiImagesLoadTestTarball())) { - dockerClient.loadImageCmd(uploadStream).exec(); + dockerClient.loadImageCmd(uploadStream).exec(new LoadImageCallback()).awaitSuccess(); } final Image image = findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec()); diff --git a/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java index d978f5662..b4d294337 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java @@ -2,6 +2,7 @@ import com.github.dockerjava.api.model.Image; +import com.github.dockerjava.core.command.LoadImageCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; import com.github.dockerjava.utils.TestResources; import org.testng.ITestResult; @@ -55,7 +56,7 @@ public void afterMethod(ITestResult result) { @Test public void loadImageFromTar() throws Exception { try (InputStream uploadStream = Files.newInputStream(TestResources.getApiImagesLoadTestTarball())) { - dockerClient.loadImageCmd(uploadStream).exec(); + dockerClient.loadImageCmd(uploadStream).exec(new LoadImageCallback()).awaitSuccess(); } final Image image = findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec());