From cae292401b3fc227c66e23a51de4d048e6e6dee6 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Sat, 17 Oct 2015 18:47:32 +0200 Subject: [PATCH 01/10] Implementations of Copy file to container command Modification of Copy file from container command to follow 1.20 API --- .../github/dockerjava/api/DockerClient.java | 3 + .../api/command/DockerCmdExecFactory.java | 4 +- .../dockerjava/core/CompressArchiveUtil.java | 59 +++++++++++ .../dockerjava/core/DockerClientImpl.java | 23 +++-- .../github/dockerjava/core/FilePathUtil.java | 26 ++++- .../github/dockerjava/core/TarDirWalker.java | 46 +++++++++ .../command/CopyFileFromContainerCmdImpl.java | 10 +- .../core/command/CopyFileToContainerCmd.java | 62 ++++++++++++ .../command/CopyFileToContainerCmdImpl.java | 97 +++++++++++++++++++ .../jaxrs/CopyFileFromContainerCmdExec.java | 22 ++--- .../jaxrs/CopyFileToContainerCmdExec.java | 57 +++++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 6 ++ .../client/AbstractDockerClientTest.java | 2 +- .../core/TestDockerCmdExecFactory.java | 7 +- .../CopyFileToContainerCmdImplTest.java | 70 +++++++++++++ 15 files changed, 458 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/core/TarDirWalker.java create mode 100644 src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java create mode 100644 src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImpl.java create mode 100644 src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java create mode 100644 src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 8b578f08e..79bd8dac0 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -43,6 +43,7 @@ import com.github.dockerjava.api.command.WaitContainerCmd; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.Identifier; +import com.github.dockerjava.core.command.CopyFileToContainerCmd; // https://godoc.org/github.com/fsouza/go-dockerclient public interface DockerClient extends Closeable { @@ -120,6 +121,8 @@ public interface DockerClient extends Closeable { public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource); + public CopyFileToContainerCmd copyFileToContainerCmd(String containerId, String hostResource); + public ContainerDiffCmd containerDiffCmd(String containerId); public StopContainerCmd stopContainerCmd(String containerId); diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java index fc750a743..33581c0e7 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -4,6 +4,7 @@ import java.io.IOException; import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.command.CopyFileToContainerCmd; public interface DockerCmdExecFactory extends Closeable { @@ -57,6 +58,8 @@ public interface DockerCmdExecFactory extends Closeable { public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec(); + public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec(); + public StopContainerCmd.Exec createStopContainerCmdExec(); public ContainerDiffCmd.Exec createContainerDiffCmdExec(); @@ -83,5 +86,4 @@ public interface DockerCmdExecFactory extends Closeable { @Override public void close() throws IOException; - } \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java b/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java index c64d07b7d..de86ecc5c 100644 --- a/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java @@ -2,18 +2,77 @@ import static com.github.dockerjava.core.FilePathUtil.relativize; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.zip.GZIPOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.io.FileUtils; +import com.google.common.io.ByteStreams; +import com.google.common.io.Closeables; + public class CompressArchiveUtil { + static void putTarEntry(TarArchiveOutputStream tarOutputStream, TarArchiveEntry tarEntry, Path file) throws IOException { + tarEntry.setSize(Files.size(file)); + tarOutputStream.putArchiveEntry(tarEntry); + InputStream input = new BufferedInputStream(Files.newInputStream(file)); + try { + ByteStreams.copy(input, tarOutputStream); + tarOutputStream.closeArchiveEntry(); + } finally { + input.close(); + } + } + + /** + * Recursively tar file + * + * @param inputPath file path can be directory + * @param outputPath where to put the archived file + * @param childrenOnly if inputPath is directory and if childrenOnly is true, the archive will contain all of its children, else the archive contains unique + * entry which is the inputPath itself + * @param gZipped compress with gzip algorithm + */ + public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean childrenOnly) throws IOException { + if (!Files.exists(inputPath)) { + throw new FileNotFoundException("File not found " + inputPath); + } + FileUtils.touch(outputPath.toFile()); + OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(outputPath)); + if (gZipped) { + outputStream = new GzipCompressorOutputStream(outputStream); + } + TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(outputStream); + tarArchiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); + try { + if (!Files.isDirectory(inputPath)) { + putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(inputPath.getFileName().toString()), inputPath); + } else { + Path sourcePath = inputPath; + if (!childrenOnly) { + // In order to have the dossier as the root entry + sourcePath = inputPath.getParent(); + } + Files.walkFileTree(inputPath, new TarDirWalker(sourcePath, tarArchiveOutputStream)); + } + tarArchiveOutputStream.flush(); + } finally { + Closeables.close(tarArchiveOutputStream, true); + } + } + public static File archiveTARFiles(File base, Iterable files, String archiveNameWithOutExtension) throws IOException { File tarFile = new File(FileUtils.getTempDirectoryPath(), archiveNameWithOutExtension + ".tar"); diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index b00a7a7f9..9725116f6 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -1,5 +1,12 @@ package com.github.dockerjava.core; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.AttachContainerCmd; import com.github.dockerjava.api.command.AuthCmd; @@ -46,6 +53,8 @@ import com.github.dockerjava.core.command.CommitCmdImpl; import com.github.dockerjava.core.command.ContainerDiffCmdImpl; import com.github.dockerjava.core.command.CopyFileFromContainerCmdImpl; +import com.github.dockerjava.core.command.CopyFileToContainerCmd; +import com.github.dockerjava.core.command.CopyFileToContainerCmdImpl; import com.github.dockerjava.core.command.CreateContainerCmdImpl; import com.github.dockerjava.core.command.CreateImageCmdImpl; import com.github.dockerjava.core.command.EventsCmdImpl; @@ -77,16 +86,8 @@ import com.github.dockerjava.core.command.VersionCmdImpl; import com.github.dockerjava.core.command.WaitContainerCmdImpl; -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import static com.google.common.base.Preconditions.checkNotNull; - /** * @author Konstantin Pelykh (kpelykh@gmail.com) - * * @see "https://github.com/docker/docker/blob/master/api/client/commands.go" */ public class DockerClientImpl implements Closeable, DockerClient { @@ -304,6 +305,12 @@ public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, Str containerId, resource); } + @Override + public CopyFileToContainerCmd copyFileToContainerCmd(String containerId, String hostResource) { + return new CopyFileToContainerCmdImpl(getDockerCmdExecFactory().createCopyFileToContainerCmdExec(), + containerId, hostResource); + } + @Override public ContainerDiffCmd containerDiffCmd(String containerId) { return new ContainerDiffCmdImpl(getDockerCmdExecFactory().createContainerDiffCmdExec(), containerId); diff --git a/src/main/java/com/github/dockerjava/core/FilePathUtil.java b/src/main/java/com/github/dockerjava/core/FilePathUtil.java index b02821bde..94e7fd9be 100644 --- a/src/main/java/com/github/dockerjava/core/FilePathUtil.java +++ b/src/main/java/com/github/dockerjava/core/FilePathUtil.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import com.github.dockerjava.api.DockerClientException; @@ -9,11 +10,9 @@ public class FilePathUtil { /** * Return the relative path. Path elements are separated with / char. - * - * @param baseDir - * a parent directory of {@code file} - * @param file - * the file to get the relative path + * + * @param baseDir a parent directory of {@code file} + * @param file the file to get the relative path * @return the relative path */ public static String relativize(File baseDir, File file) { @@ -26,4 +25,21 @@ public static String relativize(File baseDir, File file) { throw new DockerClientException(e.getMessage(), e); } } + + /** + * Return the relative path. Path elements are separated with / char. + * + * @param baseDir a parent directory of {@code file} + * @param file the file to get the relative path + * @return the relative path + */ + public static String relativize(Path baseDir, Path file) { + String path = baseDir.toUri().relativize(file.toUri()).getPath(); + if (!"/".equals(baseDir.getFileSystem().getSeparator())) { + // For windows + return path.replace(baseDir.getFileSystem().getSeparator(), "/"); + } else { + return path; + } + } } diff --git a/src/main/java/com/github/dockerjava/core/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/TarDirWalker.java new file mode 100644 index 000000000..091d9d3a6 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/TarDirWalker.java @@ -0,0 +1,46 @@ +package com.github.dockerjava.core; + +import static com.github.dockerjava.core.FilePathUtil.relativize; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; + +import com.google.common.io.Closeables; + +public class TarDirWalker extends SimpleFileVisitor { + + private Path basePath; + + private TarArchiveOutputStream tarArchiveOutputStream; + + public TarDirWalker(Path basePath, TarArchiveOutputStream tarArchiveOutputStream) { + this.basePath = basePath; + this.tarArchiveOutputStream = tarArchiveOutputStream; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + if (!dir.equals(basePath)) { + tarArchiveOutputStream.putArchiveEntry(new TarArchiveEntry(relativize(basePath, dir))); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(relativize(basePath, file)), file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + Closeables.close(tarArchiveOutputStream, true); + throw exc; + } +} diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java index ef5f86a7a..e8e2503e1 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java @@ -6,24 +6,19 @@ import org.apache.commons.lang.builder.ToStringBuilder; -import com.fasterxml.jackson.annotation.JsonProperty; import com.github.dockerjava.api.NotFoundException; import com.github.dockerjava.api.command.CopyFileFromContainerCmd; /** - * * Copy files or folders from a container. - * */ public class CopyFileFromContainerCmdImpl extends AbstrDockerCmd implements CopyFileFromContainerCmd { private String containerId; - @JsonProperty("HostPath") private String hostPath = "."; - @JsonProperty("Resource") private String resource; public CopyFileFromContainerCmdImpl(CopyFileFromContainerCmd.Exec exec, String containerId, String resource) { @@ -70,12 +65,11 @@ public CopyFileFromContainerCmdImpl withHostPath(String hostPath) { @Override public String toString() { - return new ToStringBuilder(this).append("cp ").append(containerId).append(":").append(resource).toString(); + return new ToStringBuilder(this).append("cp ").append(hostPath).append(" ").append(containerId).append(":").append(resource).toString(); } /** - * @throws NotFoundException - * No such container + * @throws NotFoundException No such container */ @Override public InputStream exec() throws NotFoundException { diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java b/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java new file mode 100644 index 000000000..1c66be241 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java @@ -0,0 +1,62 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.NotFoundException; +import com.github.dockerjava.api.command.DockerCmdSyncExec; +import com.github.dockerjava.api.command.SyncDockerCmd; + +public interface CopyFileToContainerCmd extends SyncDockerCmd { + + public String getContainerId(); + + public String getHostResource(); + + public boolean isNoOverwriteDirNonDir(); + + public boolean isDirChildrenOnly(); + + /** + * Set container's id + * + * @param containerId id of the container to copy file to + * @return this + */ + public CopyFileToContainerCmd withContainerId(String containerId); + + /** + * Set path to the resource on the host machine + * + * @param resource path to the resource on the host machine + * @return this + */ + public CopyFileToContainerCmd withHostResource(String resource); + + /** + * If set to true then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa + * + * @param noOverwriteDirNonDir flag to know if non directory can be overwritten + * @return this + */ + public CopyFileToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); + + /** + * If this flag is set to true, all children of the local directory will be copied to the remote without the root directory. + * For ex: if I have root/titi and root/tata and the remote path is /var/data. + * dirChildrenOnly = true will create /var/data/titi and /var/data/tata + * dirChildrenOnly = false will create /var/data/root/titi and /var/data/root/tata + * + * @param dirChildrenOnly if root directory is ignored + * @return this + */ + public CopyFileToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); + + public String getRemotePath(); + + public CopyFileToContainerCmd withRemotePath(String remotePath); + + @Override + public Void exec() throws NotFoundException; + + public static interface Exec extends DockerCmdSyncExec { + } + +} diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImpl.java new file mode 100644 index 000000000..81d464b9b --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImpl.java @@ -0,0 +1,97 @@ +package com.github.dockerjava.core.command; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.apache.commons.lang.builder.ToStringBuilder; + +import com.github.dockerjava.api.NotFoundException; + +public class CopyFileToContainerCmdImpl extends AbstrDockerCmd implements CopyFileToContainerCmd { + + private String containerId; + + private String remotePath = "."; + + private String hostResource; + + private boolean noOverwriteDirNonDir = false; + + private boolean dirChildrenOnly = false; + + public CopyFileToContainerCmdImpl(CopyFileToContainerCmd.Exec exec, String containerId, String hostResource) { + super(exec); + withContainerId(containerId); + withHostResource(hostResource); + } + + @Override + public CopyFileToContainerCmd withContainerId(String containerId) { + checkNotNull(containerId, "containerId was not specified"); + this.containerId = containerId; + return this; + } + + @Override + public CopyFileToContainerCmd withHostResource(String hostResource) { + checkNotNull(hostResource, "hostResource was not specified"); + this.hostResource = hostResource; + return this; + } + + @Override + public String getContainerId() { + return this.containerId; + } + + @Override + public String getHostResource() { + return this.hostResource; + } + + @Override + public boolean isNoOverwriteDirNonDir() { + return this.noOverwriteDirNonDir; + } + + @Override + public CopyFileToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir) { + this.noOverwriteDirNonDir = noOverwriteDirNonDir; + return this; + } + + @Override + public CopyFileToContainerCmd withRemotePath(String remotePath) { + checkNotNull(remotePath, "remotePath was not specified"); + this.remotePath = remotePath; + return this; + } + + @Override + public String getRemotePath() { + return this.remotePath; + } + + @Override + public boolean isDirChildrenOnly() { + return this.dirChildrenOnly; + } + + @Override + public CopyFileToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly) { + this.dirChildrenOnly = dirChildrenOnly; + return this; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("cp ").append(hostResource).append(" ").append(containerId).append(":").append(remotePath).toString(); + } + + /** + * @throws NotFoundException No such container + */ + @Override + public Void exec() throws NotFoundException { + return super.exec(); + } +} diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java index 15185a8d8..4dec7556e 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java @@ -1,17 +1,16 @@ package com.github.dockerjava.jaxrs; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; -import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.io.InputStream; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.InputStream; -import static javax.ws.rs.client.Entity.entity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream; public class CopyFileFromContainerCmdExec extends AbstrSyncDockerCmdExec implements CopyFileFromContainerCmd.Exec { @@ -24,13 +23,12 @@ public CopyFileFromContainerCmdExec(WebTarget baseResource, DockerClientConfig d @Override protected InputStream execute(CopyFileFromContainerCmd command) { - WebTarget webResource = getBaseResource().path("/containers/{id}/copy").resolveTemplate("id", + WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", command.getContainerId()); - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("Get: " + webResource.toString()); - Response response = webResource.request().accept(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .post(entity(command, MediaType.APPLICATION_JSON)); + Response response = webResource.queryParam("path", command.getResource()).request().accept("application/x-tar").get(); return new WrappedResponseInputStream(response); } diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java new file mode 100644 index 000000000..db44a7551 --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java @@ -0,0 +1,57 @@ +package com.github.dockerjava.jaxrs; + +import static javax.ws.rs.client.Entity.entity; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.ws.rs.client.WebTarget; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.dockerjava.api.DockerClientException; +import com.github.dockerjava.core.CompressArchiveUtil; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.command.CopyFileToContainerCmd; +import com.google.common.io.Closeables; + +public class CopyFileToContainerCmdExec extends AbstrSyncDockerCmdExec implements CopyFileToContainerCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(CopyFileFromContainerCmdExec.class); + + public CopyFileToContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected Void execute(CopyFileToContainerCmd command) { + WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", + command.getContainerId()); + + LOGGER.trace("PUT: " + webResource.toString()); + InputStream streamToUpload = null; + try { + Path toUpload = Files.createTempFile("docker-java", "tar.gz"); + CompressArchiveUtil.tar(Paths.get(command.getHostResource()), toUpload, true, command.isDirChildrenOnly()); + streamToUpload = Files.newInputStream(toUpload); + webResource + .queryParam("path", command.getRemotePath()) + .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()) + .request() + .put(entity(streamToUpload, "application/x-tar")) + .close(); + return null; + } catch (IOException e) { + throw new DockerClientException("Error occurred while preparing uploading host resource <" + command.getHostResource() + ">", e); + } finally { + if (streamToUpload != null) { + Closeables.closeQuietly(streamToUpload); + } + } + } + +} diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index c331f461c..24a70be4a 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -41,6 +41,7 @@ import com.github.dockerjava.api.command.WaitContainerCmd; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.RemoteApiVersion; +import com.github.dockerjava.core.command.CopyFileToContainerCmd; import com.github.dockerjava.jaxrs.connector.ApacheConnectorProvider; import com.github.dockerjava.jaxrs.filter.JsonClientFilter; import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; @@ -315,6 +316,11 @@ public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { return new CopyFileFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec() { + return new CopyFileToContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public StopContainerCmd.Exec createStopContainerCmdExec() { return new StopContainerCmdExec(getBaseResource(), getDockerClientConfig()); diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index e8c98d902..bba339991 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -38,7 +38,7 @@ public abstract class AbstractDockerClientTest extends Assert { public static final Logger LOG = LoggerFactory.getLogger(AbstractDockerClientTest.class); - private String apiVersion = "1.19"; + private String apiVersion = "1.20"; protected DockerClient dockerClient; diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index fdc582083..5e9f18f06 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -46,13 +46,13 @@ 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.core.command.CopyFileToContainerCmd; /** * Special {@link DockerCmdExecFactory} implementation that collects container and image creations while test execution * for the purpose of automatically cleanup. * * @author marcus - * */ public class TestDockerCmdExecFactory implements DockerCmdExecFactory { @@ -242,6 +242,11 @@ public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { return delegate.createCopyFileFromContainerCmdExec(); } + @Override + public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec() { + return delegate.createCopyFileToContainerCmdExec(); + } + @Override public StopContainerCmd.Exec createStopContainerCmdExec() { return delegate.createStopContainerCmdExec(); diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java new file mode 100644 index 000000000..445fc5696 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java @@ -0,0 +1,70 @@ +package com.github.dockerjava.core.command; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.not; + +import java.io.InputStream; +import java.lang.reflect.Method; + +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.github.dockerjava.api.NotFoundException; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.client.AbstractDockerClientTest; +import com.google.common.io.Closeables; + +public class CopyFileToContainerCmdImplTest extends AbstractDockerClientTest { + @BeforeTest + public void beforeTest() throws Exception { + super.beforeTest(); + } + + @AfterTest + public void afterTest() { + super.afterTest(); + } + + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + super.afterMethod(result); + } + + @Test + public void copyToContainer() throws Exception { + // TODO extract this into a shared method + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withName("docker-java-itest-copyFromContainer").withCmd("touch", "/copyFromContainer").exec(); + + LOG.info("Created container: {}", container); + assertThat(container.getId(), not(isEmptyOrNullString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + dockerClient.copyFileToContainerCmd(container.getId(), "src/test/resources/testReadFile").exec(); + InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "testReadFile").exec(); + boolean bytesAvailable = response.available() > 0; + assertTrue(bytesAvailable, "The file was not copied to the container."); + Closeables.closeQuietly(response); + } + + @Test + public void copyToNonExistingContainer() throws Exception { + try { + dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); + fail("expected NotFoundException"); + } catch (NotFoundException ignored) { + } + } + +} From 89bb406bfa52d45c6ebcb73f687d25016e7ff22c Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Mon, 19 Oct 2015 22:11:15 +0200 Subject: [PATCH 02/10] Use new try syntax for Java to free resources --- .../dockerjava/core/CompressArchiveUtil.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java b/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java index de86ecc5c..97b05213e 100644 --- a/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/CompressArchiveUtil.java @@ -20,22 +20,28 @@ import org.apache.commons.io.FileUtils; import com.google.common.io.ByteStreams; -import com.google.common.io.Closeables; public class CompressArchiveUtil { static void putTarEntry(TarArchiveOutputStream tarOutputStream, TarArchiveEntry tarEntry, Path file) throws IOException { tarEntry.setSize(Files.size(file)); tarOutputStream.putArchiveEntry(tarEntry); - InputStream input = new BufferedInputStream(Files.newInputStream(file)); - try { + try (InputStream input = new BufferedInputStream(Files.newInputStream(file))) { ByteStreams.copy(input, tarOutputStream); tarOutputStream.closeArchiveEntry(); - } finally { - input.close(); } } + private static TarArchiveOutputStream buildTarStream(Path outputPath, boolean gZipped) throws IOException { + OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(outputPath)); + if (gZipped) { + outputStream = new GzipCompressorOutputStream(outputStream); + } + TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(outputStream); + tarArchiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); + return tarArchiveOutputStream; + } + /** * Recursively tar file * @@ -50,13 +56,8 @@ public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean throw new FileNotFoundException("File not found " + inputPath); } FileUtils.touch(outputPath.toFile()); - OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(outputPath)); - if (gZipped) { - outputStream = new GzipCompressorOutputStream(outputStream); - } - TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(outputStream); - tarArchiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); - try { + + try (TarArchiveOutputStream tarArchiveOutputStream = buildTarStream(outputPath, gZipped)) { if (!Files.isDirectory(inputPath)) { putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(inputPath.getFileName().toString()), inputPath); } else { @@ -68,8 +69,6 @@ public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean Files.walkFileTree(inputPath, new TarDirWalker(sourcePath, tarArchiveOutputStream)); } tarArchiveOutputStream.flush(); - } finally { - Closeables.close(tarArchiveOutputStream, true); } } From 90f4aba1d107ee9d721f643a0ce1cc7ef6c0570d Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Fri, 30 Oct 2015 18:12:32 +0100 Subject: [PATCH 03/10] Use java 7 to close stream --- .../jaxrs/CopyFileToContainerCmdExec.java | 18 +++++++----------- .../CopyFileToContainerCmdImplTest.java | 9 ++++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java index db44a7551..ca7c3d9b8 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java @@ -17,7 +17,6 @@ import com.github.dockerjava.core.CompressArchiveUtil; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.command.CopyFileToContainerCmd; -import com.google.common.io.Closeables; public class CopyFileToContainerCmdExec extends AbstrSyncDockerCmdExec implements CopyFileToContainerCmd.Exec { @@ -27,17 +26,19 @@ public CopyFileToContainerCmdExec(WebTarget baseResource, DockerClientConfig doc super(baseResource, dockerClientConfig); } + private InputStream buildUploadStream(CopyFileToContainerCmd command) throws IOException { + Path toUpload = Files.createTempFile("docker-java", ".tar.gz"); + CompressArchiveUtil.tar(Paths.get(command.getHostResource()), toUpload, true, command.isDirChildrenOnly()); + return Files.newInputStream(toUpload); + } + @Override protected Void execute(CopyFileToContainerCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", command.getContainerId()); LOGGER.trace("PUT: " + webResource.toString()); - InputStream streamToUpload = null; - try { - Path toUpload = Files.createTempFile("docker-java", "tar.gz"); - CompressArchiveUtil.tar(Paths.get(command.getHostResource()), toUpload, true, command.isDirChildrenOnly()); - streamToUpload = Files.newInputStream(toUpload); + try (InputStream streamToUpload = buildUploadStream(command)) { webResource .queryParam("path", command.getRemotePath()) .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()) @@ -47,11 +48,6 @@ protected Void execute(CopyFileToContainerCmd command) { return null; } catch (IOException e) { throw new DockerClientException("Error occurred while preparing uploading host resource <" + command.getHostResource() + ">", e); - } finally { - if (streamToUpload != null) { - Closeables.closeQuietly(streamToUpload); - } } } - } diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java index 445fc5696..7bee960b4 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java @@ -17,7 +17,6 @@ import com.github.dockerjava.api.NotFoundException; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; -import com.google.common.io.Closeables; public class CopyFileToContainerCmdImplTest extends AbstractDockerClientTest { @BeforeTest @@ -52,10 +51,10 @@ public void copyToContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); dockerClient.copyFileToContainerCmd(container.getId(), "src/test/resources/testReadFile").exec(); - InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "testReadFile").exec(); - boolean bytesAvailable = response.available() > 0; - assertTrue(bytesAvailable, "The file was not copied to the container."); - Closeables.closeQuietly(response); + try (InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "testReadFile").exec()) { + boolean bytesAvailable = response.available() > 0; + assertTrue(bytesAvailable, "The file was not copied to the container."); + } } @Test From f44ee8f76237a84bc3a4e57c41e097452c808447 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Mon, 23 Nov 2015 23:31:25 +0100 Subject: [PATCH 04/10] Rename CopyFileFromContainerCmd and CopyFileToContainerCmd to CopyArchiveFromContainerCmd and CopyArchiveToContainerCmd --- .../github/dockerjava/api/DockerClient.java | 8 ++++---- ...d.java => CopyArchiveFromContainerCmd.java} | 10 +++++----- .../command/CopyArchiveToContainerCmd.java} | 18 ++++++++---------- .../api/command/DockerCmdExecFactory.java | 5 ++--- .../dockerjava/core/DockerClientImpl.java | 16 ++++++++-------- ...va => CopyArchiveFromContainerCmdImpl.java} | 14 +++++++------- ...java => CopyArchiveToContainerCmdImpl.java} | 15 ++++++++------- ...va => CopyArchiveFromContainerCmdExec.java} | 12 ++++++------ ...java => CopyArchiveToContainerCmdExec.java} | 16 ++++++++-------- .../jaxrs/DockerCmdExecFactoryImpl.java | 13 ++++++------- .../core/TestDockerCmdExecFactory.java | 12 ++++++------ ...> CopyArchiveFromContainerCmdImplTest.java} | 6 +++--- ... => CopyArchiveToContainerCmdImplTest.java} | 8 ++++---- .../core/command/ExecStartCmdImplTest.java | 4 ++-- 14 files changed, 77 insertions(+), 80 deletions(-) rename src/main/java/com/github/dockerjava/api/command/{CopyFileFromContainerCmd.java => CopyArchiveFromContainerCmd.java} (61%) rename src/main/java/com/github/dockerjava/{core/command/CopyFileToContainerCmd.java => api/command/CopyArchiveToContainerCmd.java} (66%) rename src/main/java/com/github/dockerjava/core/command/{CopyFileFromContainerCmdImpl.java => CopyArchiveFromContainerCmdImpl.java} (69%) rename src/main/java/com/github/dockerjava/core/command/{CopyFileToContainerCmdImpl.java => CopyArchiveToContainerCmdImpl.java} (73%) rename src/main/java/com/github/dockerjava/jaxrs/{CopyFileFromContainerCmdExec.java => CopyArchiveFromContainerCmdExec.java} (64%) rename src/main/java/com/github/dockerjava/jaxrs/{CopyFileToContainerCmdExec.java => CopyArchiveToContainerCmdExec.java} (70%) rename src/test/java/com/github/dockerjava/core/command/{CopyFileFromContainerCmdImplTest.java => CopyArchiveFromContainerCmdImplTest.java} (88%) rename src/test/java/com/github/dockerjava/core/command/{CopyFileToContainerCmdImplTest.java => CopyArchiveToContainerCmdImplTest.java} (82%) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index feebfae45..88c830ea7 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -10,7 +10,7 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.EventsCmd; @@ -44,7 +44,7 @@ import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.Identifier; -import com.github.dockerjava.core.command.CopyFileToContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; // https://godoc.org/github.com/fsouza/go-dockerclient public interface DockerClient extends Closeable { @@ -120,9 +120,9 @@ public interface DockerClient extends Closeable { public LogContainerCmd logContainerCmd(String containerId); - public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource); + public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerId, String resource); - public CopyFileToContainerCmd copyFileToContainerCmd(String containerId, String hostResource); + public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource); public ContainerDiffCmd containerDiffCmd(String containerId); diff --git a/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java similarity index 61% rename from src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java rename to src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java index 5ae9f6276..1bb8cf617 100644 --- a/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java @@ -7,7 +7,7 @@ import com.github.dockerjava.api.exception.NotFoundException; -public interface CopyFileFromContainerCmd extends SyncDockerCmd { +public interface CopyArchiveFromContainerCmd extends SyncDockerCmd { @CheckForNull public String getContainerId(); @@ -18,11 +18,11 @@ public interface CopyFileFromContainerCmd extends SyncDockerCmd { @CheckForNull public String getResource(); - public CopyFileFromContainerCmd withContainerId(@Nonnull String containerId); + public CopyArchiveFromContainerCmd withContainerId(@Nonnull String containerId); - public CopyFileFromContainerCmd withHostPath(String hostPath); + public CopyArchiveFromContainerCmd withHostPath(String hostPath); - public CopyFileFromContainerCmd withResource(@Nonnull String resource); + public CopyArchiveFromContainerCmd withResource(@Nonnull String resource); /** * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks. @@ -33,6 +33,6 @@ public interface CopyFileFromContainerCmd extends SyncDockerCmd { @Override public InputStream exec() throws NotFoundException; - public static interface Exec extends DockerCmdSyncExec { + public static interface Exec extends DockerCmdSyncExec { } } \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java similarity index 66% rename from src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java rename to src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java index ab168c9c3..6fbad5eff 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyFileToContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java @@ -1,10 +1,8 @@ -package com.github.dockerjava.core.command; +package com.github.dockerjava.api.command; -import com.github.dockerjava.api.command.DockerCmdSyncExec; -import com.github.dockerjava.api.command.SyncDockerCmd; import com.github.dockerjava.api.exception.NotFoundException; -public interface CopyFileToContainerCmd extends SyncDockerCmd { +public interface CopyArchiveToContainerCmd extends SyncDockerCmd { public String getContainerId(); @@ -20,7 +18,7 @@ public interface CopyFileToContainerCmd extends SyncDockerCmd { * @param containerId id of the container to copy file to * @return this */ - public CopyFileToContainerCmd withContainerId(String containerId); + public CopyArchiveToContainerCmd withContainerId(String containerId); /** * Set path to the resource on the host machine @@ -28,7 +26,7 @@ public interface CopyFileToContainerCmd extends SyncDockerCmd { * @param resource path to the resource on the host machine * @return this */ - public CopyFileToContainerCmd withHostResource(String resource); + public CopyArchiveToContainerCmd withHostResource(String resource); /** * If set to true then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa @@ -36,7 +34,7 @@ public interface CopyFileToContainerCmd extends SyncDockerCmd { * @param noOverwriteDirNonDir flag to know if non directory can be overwritten * @return this */ - public CopyFileToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); + public CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); /** * If this flag is set to true, all children of the local directory will be copied to the remote without the root directory. @@ -47,16 +45,16 @@ public interface CopyFileToContainerCmd extends SyncDockerCmd { * @param dirChildrenOnly if root directory is ignored * @return this */ - public CopyFileToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); + public CopyArchiveToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); public String getRemotePath(); - public CopyFileToContainerCmd withRemotePath(String remotePath); + public CopyArchiveToContainerCmd withRemotePath(String remotePath); @Override public Void exec() throws NotFoundException; - public static interface Exec extends DockerCmdSyncExec { + public static interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java index 33581c0e7..a8f63ab52 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -4,7 +4,6 @@ import java.io.IOException; import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.core.command.CopyFileToContainerCmd; public interface DockerCmdExecFactory extends Closeable { @@ -56,9 +55,9 @@ public interface DockerCmdExecFactory extends Closeable { public LogContainerCmd.Exec createLogContainerCmdExec(); - public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec(); + public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec(); - public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec(); + public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec(); public StopContainerCmd.Exec createStopContainerCmdExec(); diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 9725116f6..572b8e906 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -13,7 +13,7 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.DockerCmdExecFactory; @@ -52,9 +52,9 @@ import com.github.dockerjava.core.command.BuildImageCmdImpl; import com.github.dockerjava.core.command.CommitCmdImpl; import com.github.dockerjava.core.command.ContainerDiffCmdImpl; -import com.github.dockerjava.core.command.CopyFileFromContainerCmdImpl; -import com.github.dockerjava.core.command.CopyFileToContainerCmd; -import com.github.dockerjava.core.command.CopyFileToContainerCmdImpl; +import com.github.dockerjava.core.command.CopyArchiveFromContainerCmdImpl; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.core.command.CopyArchiveToContainerCmdImpl; import com.github.dockerjava.core.command.CreateContainerCmdImpl; import com.github.dockerjava.core.command.CreateImageCmdImpl; import com.github.dockerjava.core.command.EventsCmdImpl; @@ -300,14 +300,14 @@ public LogContainerCmd logContainerCmd(String containerId) { } @Override - public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource) { - return new CopyFileFromContainerCmdImpl(getDockerCmdExecFactory().createCopyFileFromContainerCmdExec(), + public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerId, String resource) { + return new CopyArchiveFromContainerCmdImpl(getDockerCmdExecFactory().createCopyArchiveFromContainerCmdExec(), containerId, resource); } @Override - public CopyFileToContainerCmd copyFileToContainerCmd(String containerId, String hostResource) { - return new CopyFileToContainerCmdImpl(getDockerCmdExecFactory().createCopyFileToContainerCmdExec(), + public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource) { + return new CopyArchiveToContainerCmdImpl(getDockerCmdExecFactory().createCopyArchiveToContainerCmdExec(), containerId, hostResource); } diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImpl.java similarity index 69% rename from src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java rename to src/main/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImpl.java index 5ff671d14..dd03fc435 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImpl.java @@ -4,14 +4,14 @@ import java.io.InputStream; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.exception.NotFoundException; /** * Copy files or folders from a container. */ -public class CopyFileFromContainerCmdImpl extends AbstrDockerCmd implements - CopyFileFromContainerCmd { +public class CopyArchiveFromContainerCmdImpl extends AbstrDockerCmd implements + CopyArchiveFromContainerCmd { private String containerId; @@ -19,7 +19,7 @@ public class CopyFileFromContainerCmdImpl extends AbstrDockerCmd implements CopyFileToContainerCmd { +public class CopyArchiveToContainerCmdImpl extends AbstrDockerCmd implements CopyArchiveToContainerCmd { private String containerId; @@ -18,21 +19,21 @@ public class CopyFileToContainerCmdImpl extends AbstrDockerCmd - implements CopyFileFromContainerCmd.Exec { +public class CopyArchiveFromContainerCmdExec extends AbstrSyncDockerCmdExec + implements CopyArchiveFromContainerCmd.Exec { - private static final Logger LOGGER = LoggerFactory.getLogger(CopyFileFromContainerCmdExec.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyArchiveFromContainerCmdExec.class); - public CopyFileFromContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + public CopyArchiveFromContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { super(baseResource, dockerClientConfig); } @Override - protected InputStream execute(CopyFileFromContainerCmd command) { + protected InputStream execute(CopyArchiveFromContainerCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", command.getContainerId()); diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyArchiveToContainerCmdExec.java similarity index 70% rename from src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java rename to src/main/java/com/github/dockerjava/jaxrs/CopyArchiveToContainerCmdExec.java index ca7c3d9b8..1866d196c 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/CopyFileToContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/CopyArchiveToContainerCmdExec.java @@ -13,27 +13,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.github.dockerjava.api.DockerClientException; -import com.github.dockerjava.core.CompressArchiveUtil; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.core.command.CopyFileToContainerCmd; +import com.github.dockerjava.core.util.CompressArchiveUtil; -public class CopyFileToContainerCmdExec extends AbstrSyncDockerCmdExec implements CopyFileToContainerCmd.Exec { +public class CopyArchiveToContainerCmdExec extends AbstrSyncDockerCmdExec implements CopyArchiveToContainerCmd.Exec { - private static final Logger LOGGER = LoggerFactory.getLogger(CopyFileFromContainerCmdExec.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyArchiveFromContainerCmdExec.class); - public CopyFileToContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + public CopyArchiveToContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { super(baseResource, dockerClientConfig); } - private InputStream buildUploadStream(CopyFileToContainerCmd command) throws IOException { + private InputStream buildUploadStream(CopyArchiveToContainerCmd command) throws IOException { Path toUpload = Files.createTempFile("docker-java", ".tar.gz"); CompressArchiveUtil.tar(Paths.get(command.getHostResource()), toUpload, true, command.isDirChildrenOnly()); return Files.newInputStream(toUpload); } @Override - protected Void execute(CopyFileToContainerCmd command) { + protected Void execute(CopyArchiveToContainerCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", command.getContainerId()); diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index b373d737a..bcb669f47 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -7,7 +7,7 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.DockerCmdExecFactory; @@ -40,8 +40,7 @@ import com.github.dockerjava.api.command.VersionCmd; import com.github.dockerjava.api.command.WaitContainerCmd; import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.core.RemoteApiVersion; -import com.github.dockerjava.core.command.CopyFileToContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.jaxrs.connector.ApacheConnectorProvider; import com.github.dockerjava.jaxrs.filter.JsonClientFilter; import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; @@ -312,13 +311,13 @@ public LogContainerCmd.Exec createLogContainerCmdExec() { } @Override - public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { - return new CopyFileFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); + public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() { + return new CopyArchiveFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); } @Override - public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec() { - return new CopyFileToContainerCmdExec(getBaseResource(), getDockerClientConfig()); + public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() { + return new CopyArchiveToContainerCmdExec(getBaseResource(), getDockerClientConfig()); } @Override diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index 5e9f18f06..528d99cec 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -11,7 +11,7 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; -import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.CreateImageCmd; @@ -46,7 +46,7 @@ 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.core.command.CopyFileToContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; /** * Special {@link DockerCmdExecFactory} implementation that collects container and image creations while test execution @@ -238,13 +238,13 @@ public LogContainerCmd.Exec createLogContainerCmdExec() { } @Override - public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { - return delegate.createCopyFileFromContainerCmdExec(); + public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() { + return delegate.createCopyArchiveFromContainerCmdExec(); } @Override - public CopyFileToContainerCmd.Exec createCopyFileToContainerCmdExec() { - return delegate.createCopyFileToContainerCmdExec(); + public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() { + return delegate.createCopyArchiveToContainerCmdExec(); } @Override diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java similarity index 88% rename from src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java rename to src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java index 3e4e88612..0f9da6058 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java @@ -19,7 +19,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest; @Test(groups = "integration") -public class CopyFileFromContainerCmdImplTest extends AbstractDockerClientTest { +public class CopyArchiveFromContainerCmdImplTest extends AbstractDockerClientTest { @BeforeTest public void beforeTest() throws Exception { @@ -52,7 +52,7 @@ public void copyFromContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "/copyFromContainer").exec(); + InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "/copyFromContainer").exec(); Boolean bytesAvailable = response.available() > 0; assertTrue(bytesAvailable, "The file was not copied from the container."); @@ -65,7 +65,7 @@ public void copyFromContainer() throws Exception { @Test public void copyFromNonExistingContainer() throws Exception { try { - dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); + dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); fail("expected NotFoundException"); } catch (NotFoundException ignored) { } diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java similarity index 82% rename from src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java rename to src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java index 7bee960b4..77d35970b 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -18,7 +18,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; -public class CopyFileToContainerCmdImplTest extends AbstractDockerClientTest { +public class CopyArchiveToContainerCmdImplTest extends AbstractDockerClientTest { @BeforeTest public void beforeTest() throws Exception { super.beforeTest(); @@ -50,8 +50,8 @@ public void copyToContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - dockerClient.copyFileToContainerCmd(container.getId(), "src/test/resources/testReadFile").exec(); - try (InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "testReadFile").exec()) { + dockerClient.copyArchiveToContainerCmd(container.getId(), "src/test/resources/testReadFile").exec(); + try (InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "testReadFile").exec()) { boolean bytesAvailable = response.available() > 0; assertTrue(bytesAvailable, "The file was not copied to the container."); } @@ -60,7 +60,7 @@ public void copyToContainer() throws Exception { @Test public void copyToNonExistingContainer() throws Exception { try { - dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); + dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); fail("expected NotFoundException"); } catch (NotFoundException ignored) { } diff --git a/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java index 43aa49f0e..5144f2d4f 100644 --- a/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java @@ -56,7 +56,7 @@ public void execStart() throws Exception { .withAttachStdout(true).withCmd("touch", "/execStartTest.log").exec(); dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(); - InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "/execStartTest.log").exec(); + InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "/execStartTest.log").exec(); Boolean bytesAvailable = response.available() > 0; assertTrue(bytesAvailable, "The file was not copied from the container."); @@ -81,7 +81,7 @@ public void execStartAttached() throws Exception { .withAttachStdout(true).withCmd("touch", "/execStartTest.log").exec(); dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false).withTty(true).exec(); - InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "/execStartTest.log").exec(); + InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "/execStartTest.log").exec(); Boolean bytesAvailable = response.available() > 0; assertTrue(bytesAvailable, "The file was not copied from the container."); From 6124775f91b2b8c2631ce7a71eead72dc63d6d8c Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Tue, 24 Nov 2015 00:30:25 +0100 Subject: [PATCH 05/10] Reset CopyFileFromContainerCmd for compatibility purpose --- .../github/dockerjava/api/DockerClient.java | 5 +- .../api/command/CopyFileFromContainerCmd.java | 38 +++++++++ .../api/command/DockerCmdExecFactory.java | 2 + .../dockerjava/core/DockerClientImpl.java | 8 ++ .../command/CopyFileFromContainerCmdImpl.java | 77 +++++++++++++++++++ .../core/util/CompressArchiveUtil.java | 1 - .../core/{ => util}/TarDirWalker.java | 8 +- .../jaxrs/CopyFileFromContainerCmdExec.java | 38 +++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 58 ++++++++------ .../core/TestDockerCmdExecFactory.java | 8 +- .../CopyArchiveToContainerCmdImplTest.java | 2 +- .../CopyFileFromContainerCmdImplTest.java | 73 ++++++++++++++++++ 12 files changed, 284 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java create mode 100644 src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java rename src/main/java/com/github/dockerjava/core/{ => util}/TarDirWalker.java (87%) create mode 100644 src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java create mode 100644 src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 88c830ea7..81bd1957e 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -11,6 +11,8 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.EventsCmd; @@ -44,7 +46,6 @@ import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.Identifier; -import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; // https://godoc.org/github.com/fsouza/go-dockerclient public interface DockerClient extends Closeable { @@ -122,6 +123,8 @@ public interface DockerClient extends Closeable { public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerId, String resource); + public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource); + public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource); public ContainerDiffCmd containerDiffCmd(String containerId); diff --git a/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java new file mode 100644 index 000000000..5ae9f6276 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java @@ -0,0 +1,38 @@ +package com.github.dockerjava.api.command; + +import java.io.InputStream; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +import com.github.dockerjava.api.exception.NotFoundException; + +public interface CopyFileFromContainerCmd extends SyncDockerCmd { + + @CheckForNull + public String getContainerId(); + + @CheckForNull + public String getHostPath(); + + @CheckForNull + public String getResource(); + + public CopyFileFromContainerCmd withContainerId(@Nonnull String containerId); + + public CopyFileFromContainerCmd withHostPath(String hostPath); + + public CopyFileFromContainerCmd withResource(@Nonnull String resource); + + /** + * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks. + * + * @throws NotFoundException + * No such container + */ + @Override + public InputStream exec() throws NotFoundException; + + public static interface Exec extends DockerCmdSyncExec { + } +} \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java index a8f63ab52..f0b35f58f 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -55,6 +55,8 @@ public interface DockerCmdExecFactory extends Closeable { public LogContainerCmd.Exec createLogContainerCmdExec(); + public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec(); + public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec(); public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec(); diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 572b8e906..913cf0a4c 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -14,6 +14,7 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.DockerCmdExecFactory; @@ -55,6 +56,7 @@ import com.github.dockerjava.core.command.CopyArchiveFromContainerCmdImpl; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.core.command.CopyArchiveToContainerCmdImpl; +import com.github.dockerjava.core.command.CopyFileFromContainerCmdImpl; import com.github.dockerjava.core.command.CreateContainerCmdImpl; import com.github.dockerjava.core.command.CreateImageCmdImpl; import com.github.dockerjava.core.command.EventsCmdImpl; @@ -299,6 +301,12 @@ public LogContainerCmd logContainerCmd(String containerId) { return new LogContainerCmdImpl(getDockerCmdExecFactory().createLogContainerCmdExec(), containerId); } + @Override + public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource) { + return new CopyFileFromContainerCmdImpl(getDockerCmdExecFactory().createCopyFileFromContainerCmdExec(), + containerId, resource); + } + @Override public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerId, String resource) { return new CopyArchiveFromContainerCmdImpl(getDockerCmdExecFactory().createCopyArchiveFromContainerCmdExec(), diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java new file mode 100644 index 000000000..77a219170 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java @@ -0,0 +1,77 @@ +package com.github.dockerjava.core.command; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.InputStream; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; + +/** + * + * Copy files or folders from a container. + * + */ +public class CopyFileFromContainerCmdImpl extends AbstrDockerCmd implements + CopyFileFromContainerCmd { + + private String containerId; + + @JsonProperty("HostPath") + private String hostPath = "."; + + @JsonProperty("Resource") + private String resource; + + public CopyFileFromContainerCmdImpl(CopyFileFromContainerCmd.Exec exec, String containerId, String resource) { + super(exec); + withContainerId(containerId); + withResource(resource); + } + + @Override + public String getContainerId() { + return containerId; + } + + @Override + public String getResource() { + return resource; + } + + @Override + public CopyFileFromContainerCmdImpl withContainerId(String containerId) { + checkNotNull(containerId, "containerId was not specified"); + this.containerId = containerId; + return this; + } + + @Override + public CopyFileFromContainerCmdImpl withResource(String resource) { + checkNotNull(resource, "resource was not specified"); + this.resource = resource; + return this; + } + + @Override + public String getHostPath() { + return hostPath; + } + + @Override + public CopyFileFromContainerCmdImpl withHostPath(String hostPath) { + checkNotNull(hostPath, "hostPath was not specified"); + this.hostPath = hostPath; + return this; + } + + /** + * @throws NotFoundException + * No such container + */ + @Override + public InputStream exec() throws NotFoundException { + return super.exec(); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java index c5bf9f0be..8506a66e3 100644 --- a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java @@ -19,7 +19,6 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.io.FileUtils; -import com.github.dockerjava.core.TarDirWalker; import com.google.common.io.ByteStreams; public class CompressArchiveUtil { diff --git a/src/main/java/com/github/dockerjava/core/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java similarity index 87% rename from src/main/java/com/github/dockerjava/core/TarDirWalker.java rename to src/main/java/com/github/dockerjava/core/util/TarDirWalker.java index 091d9d3a6..927736af5 100644 --- a/src/main/java/com/github/dockerjava/core/TarDirWalker.java +++ b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java @@ -1,6 +1,4 @@ -package com.github.dockerjava.core; - -import static com.github.dockerjava.core.FilePathUtil.relativize; +package com.github.dockerjava.core.util; import java.io.IOException; import java.nio.file.FileVisitResult; @@ -27,14 +25,14 @@ public TarDirWalker(Path basePath, TarArchiveOutputStream tarArchiveOutputStream @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (!dir.equals(basePath)) { - tarArchiveOutputStream.putArchiveEntry(new TarArchiveEntry(relativize(basePath, dir))); + tarArchiveOutputStream.putArchiveEntry(new TarArchiveEntry(FilePathUtil.relativize(basePath, dir))); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(relativize(basePath, file)), file); + CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(FilePathUtil.relativize(basePath, file)), file); return FileVisitResult.CONTINUE; } diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java new file mode 100644 index 000000000..10a719cbc --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java @@ -0,0 +1,38 @@ +package com.github.dockerjava.jaxrs; + +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.InputStream; + +import static javax.ws.rs.client.Entity.entity; + +public class CopyFileFromContainerCmdExec extends AbstrSyncDockerCmdExec + implements CopyFileFromContainerCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(CopyFileFromContainerCmdExec.class); + + public CopyFileFromContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected InputStream execute(CopyFileFromContainerCmd command) { + WebTarget webResource = getBaseResource().path("/containers/{id}/copy").resolveTemplate("id", + command.getContainerId()); + + LOGGER.trace("POST: " + webResource.toString()); + + Response response = webResource.request().accept(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .post(entity(command, MediaType.APPLICATION_JSON)); + + return new WrappedResponseInputStream(response); + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index bcb669f47..ba076848d 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -1,13 +1,38 @@ package com.github.dockerjava.jaxrs; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.IOException; +import java.net.URI; + +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.client.WebTarget; + +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.apache.connector.ApacheClientProperties; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; -import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.command.AttachContainerCmd; import com.github.dockerjava.api.command.AuthCmd; import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateImageCmd; import com.github.dockerjava.api.command.DockerCmdExecFactory; @@ -39,34 +64,12 @@ import com.github.dockerjava.api.command.UnpauseContainerCmd; import com.github.dockerjava.api.command.VersionCmd; import com.github.dockerjava.api.command.WaitContainerCmd; +import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.jaxrs.connector.ApacheConnectorProvider; import com.github.dockerjava.jaxrs.filter.JsonClientFilter; import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; import com.github.dockerjava.jaxrs.filter.SelectiveLoggingFilter; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.glassfish.jersey.CommonProperties; -import org.glassfish.jersey.apache.connector.ApacheClientProperties; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.ClientResponseFilter; -import javax.ws.rs.client.WebTarget; -import java.io.IOException; -import java.net.URI; - -import static com.google.common.base.Preconditions.checkNotNull; //import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; // see https://github.com/docker-java/docker-java/issues/196 @@ -174,7 +177,7 @@ public void init(DockerClientConfig dockerClientConfig) { } private org.apache.http.config.Registry getSchemeRegistry(final URI originalUri, - SSLContext sslContext) { + SSLContext sslContext) { RegistryBuilder registryBuilder = RegistryBuilder.create(); registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory()); if (sslContext != null) { @@ -315,6 +318,11 @@ public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() return new CopyArchiveFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { + return new CopyFileFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() { return new CopyArchiveToContainerCmdExec(getBaseResource(), getDockerClientConfig()); diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index 528d99cec..d1ff920b0 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -12,6 +12,8 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; +import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.CreateImageCmd; @@ -46,7 +48,6 @@ 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.command.CopyArchiveToContainerCmd; /** * Special {@link DockerCmdExecFactory} implementation that collects container and image creations while test execution @@ -237,6 +238,11 @@ public LogContainerCmd.Exec createLogContainerCmdExec() { return delegate.createLogContainerCmdExec(); } + @Override + public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { + return delegate.createCopyFileFromContainerCmdExec(); + } + @Override public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() { return delegate.createCopyArchiveFromContainerCmdExec(); diff --git a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java index 77d35970b..dfc991526 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -14,8 +14,8 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.github.dockerjava.api.NotFoundException; import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.client.AbstractDockerClientTest; public class CopyArchiveToContainerCmdImplTest extends AbstractDockerClientTest { diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java new file mode 100644 index 000000000..d073daf45 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java @@ -0,0 +1,73 @@ +package com.github.dockerjava.core.command; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.not; + +import java.io.InputStream; +import java.lang.reflect.Method; + +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.client.AbstractDockerClientTest; + +@Test(groups = "integration") +public class CopyFileFromContainerCmdImplTest extends AbstractDockerClientTest { + + @BeforeTest + public void beforeTest() throws Exception { + super.beforeTest(); + } + + @AfterTest + public void afterTest() { + super.afterTest(); + } + + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + super.afterMethod(result); + } + + @Test + public void copyFromContainer() throws Exception { + // TODO extract this into a shared method + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withName("docker-java-itest-copyFromContainer").withCmd("touch", "/copyFromContainer").exec(); + + LOG.info("Created container: {}", container); + assertThat(container.getId(), not(isEmptyOrNullString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "/copyFromContainer").exec(); + Boolean bytesAvailable = response.available() > 0; + assertTrue(bytesAvailable, "The file was not copied from the container."); + + // read the stream fully. Otherwise, the underlying stream will not be closed. + String responseAsString = asString(response); + assertNotNull(responseAsString); + assertTrue(responseAsString.length() > 0); + } + + @Test + public void copyFromNonExistingContainer() throws Exception { + try { + dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); + fail("expected NotFoundException"); + } catch (NotFoundException ignored) { + } + } +} \ No newline at end of file From 0f654699e04985c2c129be1442798f6edbb600cc Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Fri, 27 Nov 2015 22:52:12 +0100 Subject: [PATCH 06/10] Fix formatting rules --- .../github/dockerjava/api/DockerClient.java | 25 +++++++++++++++++++ .../command/CopyArchiveFromContainerCmd.java | 2 +- .../command/CopyArchiveToContainerCmd.java | 4 --- .../command/CopyFileFromContainerCmdImpl.java | 2 +- .../dockerjava/core/util/FilePathUtil.java | 12 ++++++--- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 81bd1957e..9ee8e0aea 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -121,10 +121,35 @@ public interface DockerClient extends Closeable { public LogContainerCmd logContainerCmd(String containerId); + /** + * Copy resource from container to local machine. + * Since docker API version 1.20 and above. + * + * @param containerId id of the container + * @param resource path to container's resource + * @return created command + */ public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerId, String resource); + /** + * Copy resource from container to local machine. + * Deprecated, since docker API version 1.20 and above use copyArchiveFromContainerCmd instead. + * + * @param containerId id of the container + * @param resource path to container's resource + * @return created command + */ + @Deprecated public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource); + /** + * Copy archive from local machine to remote container + * Since docker API version 1.20 and above. + * + * @param containerId id of the container + * @param hostResource path to container's resource + * @return created command + */ public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource); public ContainerDiffCmd containerDiffCmd(String containerId); diff --git a/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java index 1bb8cf617..56b24d24d 100644 --- a/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CopyArchiveFromContainerCmd.java @@ -35,4 +35,4 @@ public interface CopyArchiveFromContainerCmd extends SyncDockerCmd public static interface Exec extends DockerCmdSyncExec { } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java index 6fbad5eff..c21f76fa6 100644 --- a/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java @@ -16,7 +16,6 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd { * Set container's id * * @param containerId id of the container to copy file to - * @return this */ public CopyArchiveToContainerCmd withContainerId(String containerId); @@ -24,7 +23,6 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd { * Set path to the resource on the host machine * * @param resource path to the resource on the host machine - * @return this */ public CopyArchiveToContainerCmd withHostResource(String resource); @@ -32,7 +30,6 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd { * If set to true then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa * * @param noOverwriteDirNonDir flag to know if non directory can be overwritten - * @return this */ public CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); @@ -43,7 +40,6 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd { * dirChildrenOnly = false will create /var/data/root/titi and /var/data/root/tata * * @param dirChildrenOnly if root directory is ignored - * @return this */ public CopyArchiveToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); diff --git a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java index 77a219170..93c7e807c 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImpl.java @@ -74,4 +74,4 @@ public CopyFileFromContainerCmdImpl withHostPath(String hostPath) { public InputStream exec() throws NotFoundException { return super.exec(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/dockerjava/core/util/FilePathUtil.java b/src/main/java/com/github/dockerjava/core/util/FilePathUtil.java index 402991559..d5e14ed0d 100644 --- a/src/main/java/com/github/dockerjava/core/util/FilePathUtil.java +++ b/src/main/java/com/github/dockerjava/core/util/FilePathUtil.java @@ -14,8 +14,10 @@ private FilePathUtil() { /** * Return the relative path. Path elements are separated with / char. * - * @param baseDir a parent directory of {@code file} - * @param file the file to get the relative path + * @param baseDir + * a parent directory of {@code file} + * @param file + * the file to get the relative path * @return the relative path */ public static String relativize(File baseDir, File file) { @@ -32,8 +34,10 @@ public static String relativize(File baseDir, File file) { /** * Return the relative path. Path elements are separated with / char. * - * @param baseDir a parent directory of {@code file} - * @param file the file to get the relative path + * @param baseDir + * a parent directory of {@code file} + * @param file + * the file to get the relative path * @return the relative path */ public static String relativize(Path baseDir, Path file) { From fca2ea584f0ad588e0090280a53d904406e854fa Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Thu, 3 Dec 2015 21:50:14 +0100 Subject: [PATCH 07/10] Re-design API to accept both a path and a tar input stream --- .../github/dockerjava/api/DockerClient.java | 10 +-- .../command/CopyArchiveToContainerCmd.java | 35 +++++--- .../dockerjava/core/DockerClientImpl.java | 4 +- .../CopyArchiveToContainerCmdImpl.java | 84 ++++++++++++++----- .../jaxrs/CopyArchiveToContainerCmdExec.java | 32 ++----- .../CopyArchiveToContainerCmdImplTest.java | 35 ++++++-- 6 files changed, 131 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 9ee8e0aea..5e77e579b 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -133,24 +133,24 @@ public interface DockerClient extends Closeable { /** * Copy resource from container to local machine. - * Deprecated, since docker API version 1.20 and above use copyArchiveFromContainerCmd instead. * * @param containerId id of the container * @param resource path to container's resource * @return created command + * @see #copyArchiveFromContainerCmd(String, String) + * @deprecated since docker API version 1.20 and replaced by {@link #copyArchiveFromContainerCmd(String, String)} instead */ @Deprecated public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource); /** * Copy archive from local machine to remote container - * Since docker API version 1.20 and above. * - * @param containerId id of the container - * @param hostResource path to container's resource + * @param containerId id of the container * @return created command + * @since docker API version 1.20 and above. */ - public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource); + public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId); public ContainerDiffCmd containerDiffCmd(String containerId); diff --git a/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java index c21f76fa6..129526cfe 100644 --- a/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CopyArchiveToContainerCmd.java @@ -1,37 +1,48 @@ package com.github.dockerjava.api.command; +import java.io.InputStream; + import com.github.dockerjava.api.exception.NotFoundException; public interface CopyArchiveToContainerCmd extends SyncDockerCmd { - public String getContainerId(); + String getContainerId(); + + String getHostResource(); - public String getHostResource(); + InputStream getTarInputStream(); - public boolean isNoOverwriteDirNonDir(); + boolean isNoOverwriteDirNonDir(); - public boolean isDirChildrenOnly(); + boolean isDirChildrenOnly(); /** * Set container's id * * @param containerId id of the container to copy file to */ - public CopyArchiveToContainerCmd withContainerId(String containerId); + CopyArchiveToContainerCmd withContainerId(String containerId); /** * Set path to the resource on the host machine * * @param resource path to the resource on the host machine */ - public CopyArchiveToContainerCmd withHostResource(String resource); + CopyArchiveToContainerCmd withHostResource(String resource); + + /** + * Set the tar input stream that will be uploaded to the container. withHostResource or withTarInputStream can be defined but not both. + * + * @param tarInputStream the stream to upload to the container + */ + CopyArchiveToContainerCmd withTarInputStream(InputStream tarInputStream); /** * If set to true then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa * * @param noOverwriteDirNonDir flag to know if non directory can be overwritten */ - public CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); + CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); /** * If this flag is set to true, all children of the local directory will be copied to the remote without the root directory. @@ -41,16 +52,16 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd { * * @param dirChildrenOnly if root directory is ignored */ - public CopyArchiveToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); + CopyArchiveToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly); - public String getRemotePath(); + String getRemotePath(); - public CopyArchiveToContainerCmd withRemotePath(String remotePath); + CopyArchiveToContainerCmd withRemotePath(String remotePath); @Override - public Void exec() throws NotFoundException; + Void exec() throws NotFoundException; - public static interface Exec extends DockerCmdSyncExec { + interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 913cf0a4c..10014efcb 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -314,9 +314,9 @@ public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(String containerI } @Override - public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId, String hostResource) { + public CopyArchiveToContainerCmd copyArchiveToContainerCmd(String containerId) { return new CopyArchiveToContainerCmdImpl(getDockerCmdExecFactory().createCopyArchiveToContainerCmdExec(), - containerId, hostResource); + containerId); } @Override diff --git a/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java index 47c0d0446..a40fc72d9 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java @@ -2,10 +2,19 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; +import com.github.dockerjava.api.exception.BadRequestException; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.core.util.CompressArchiveUtil; public class CopyArchiveToContainerCmdImpl extends AbstrDockerCmd implements CopyArchiveToContainerCmd { @@ -13,16 +22,17 @@ public class CopyArchiveToContainerCmdImpl extends AbstrDockerCmd implements CopyArchiveToContainerCmd.Exec { @@ -26,28 +20,20 @@ public CopyArchiveToContainerCmdExec(WebTarget baseResource, DockerClientConfig super(baseResource, dockerClientConfig); } - private InputStream buildUploadStream(CopyArchiveToContainerCmd command) throws IOException { - Path toUpload = Files.createTempFile("docker-java", ".tar.gz"); - CompressArchiveUtil.tar(Paths.get(command.getHostResource()), toUpload, true, command.isDirChildrenOnly()); - return Files.newInputStream(toUpload); - } - @Override protected Void execute(CopyArchiveToContainerCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id", command.getContainerId()); LOGGER.trace("PUT: " + webResource.toString()); - try (InputStream streamToUpload = buildUploadStream(command)) { - webResource - .queryParam("path", command.getRemotePath()) - .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()) - .request() - .put(entity(streamToUpload, "application/x-tar")) - .close(); - return null; - } catch (IOException e) { - throw new DockerClientException("Error occurred while preparing uploading host resource <" + command.getHostResource() + ">", e); - } + InputStream streamToUpload = command.getTarInputStream(); + webResource + .queryParam("path", command.getRemotePath()) + .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()) + .request() + .put(entity(streamToUpload, "application/x-tar")) + .close(); + return null; + } } diff --git a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java index dfc991526..3e5cb6702 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -4,8 +4,12 @@ import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; @@ -17,6 +21,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.core.util.CompressArchiveUtil; public class CopyArchiveToContainerCmdImplTest extends AbstractDockerClientTest { @BeforeTest @@ -40,17 +45,33 @@ public void afterMethod(ITestResult result) { } @Test - public void copyToContainer() throws Exception { - // TODO extract this into a shared method - CreateContainerResponse container = dockerClient.createContainerCmd("busybox") - .withName("docker-java-itest-copyFromContainer").withCmd("touch", "/copyFromContainer").exec(); + public void copyFileToContainer() throws Exception { + CreateContainerResponse container = prepareContainerForCopy(); + Path temp = Files.createTempFile("", ".tar.gz"); + CompressArchiveUtil.tar(Paths.get("src/test/resources/testReadFile"), temp, true, false); + try (InputStream uploadStream = Files.newInputStream(temp)) { + dockerClient.copyArchiveToContainerCmd(container.getId()).withTarInputStream(uploadStream).exec(); + assertFileCopied(container); + } + } + @Test + public void copyStreamToContainer() throws Exception { + CreateContainerResponse container = prepareContainerForCopy(); + dockerClient.copyArchiveToContainerCmd(container.getId()).withHostResource("src/test/resources/testReadFile").exec(); + assertFileCopied(container); + } + + private CreateContainerResponse prepareContainerForCopy() { + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withName("docker-java-itest-copyToContainer").exec(); LOG.info("Created container: {}", container); assertThat(container.getId(), not(isEmptyOrNullString())); - dockerClient.startContainerCmd(container.getId()).exec(); + // Copy a folder to the container + return container; + } - dockerClient.copyArchiveToContainerCmd(container.getId(), "src/test/resources/testReadFile").exec(); + private void assertFileCopied(CreateContainerResponse container) throws IOException { try (InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "testReadFile").exec()) { boolean bytesAvailable = response.available() > 0; assertTrue(bytesAvailable, "The file was not copied to the container."); @@ -60,7 +81,7 @@ public void copyToContainer() throws Exception { @Test public void copyToNonExistingContainer() throws Exception { try { - dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); + dockerClient.copyArchiveToContainerCmd("non-existing").withHostResource("src/test/resources/testReadFile").exec(); fail("expected NotFoundException"); } catch (NotFoundException ignored) { } From 0871b9dbed2efacbea3f32e0fa3b1906d2384b2c Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Thu, 3 Dec 2015 23:35:11 +0100 Subject: [PATCH 08/10] Minor fix API doc --- src/main/java/com/github/dockerjava/api/DockerClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 9a0c02962..586c40ff0 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -125,11 +125,11 @@ public interface DockerClient extends Closeable { /** * Copy resource from container to local machine. - * Since docker API version 1.20 and above. * * @param containerId id of the container * @param resource path to container's resource * @return created command + * @since docker API version 1.20 and above. */ public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(@Nonnull String containerId, @Nonnull String resource); @@ -140,7 +140,7 @@ public interface DockerClient extends Closeable { * @param resource path to container's resource * @return created command * @see #copyArchiveFromContainerCmd(String, String) - * @deprecated since docker API version 1.20 and replaced by {@link #copyArchiveFromContainerCmd(String, String)} instead + * @deprecated since docker API version 1.20, replaced by {@link #copyArchiveFromContainerCmd(String, String)} */ @Deprecated public CopyFileFromContainerCmd copyFileFromContainerCmd(@Nonnull String containerId, @Nonnull String resource); From a72355f47478f674eded2b0afe143dac6576a6a3 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Sat, 5 Dec 2015 19:15:10 +0100 Subject: [PATCH 09/10] Rollback unrelated changes due to code formatter --- .../com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java | 2 +- .../core/command/CopyFileFromContainerCmdImplTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index ba076848d..6e2591f86 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -177,7 +177,7 @@ public void init(DockerClientConfig dockerClientConfig) { } private org.apache.http.config.Registry getSchemeRegistry(final URI originalUri, - SSLContext sslContext) { + SSLContext sslContext) { RegistryBuilder registryBuilder = RegistryBuilder.create(); registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory()); if (sslContext != null) { diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java index d073daf45..3e4e88612 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java @@ -70,4 +70,4 @@ public void copyFromNonExistingContainer() throws Exception { } catch (NotFoundException ignored) { } } -} \ No newline at end of file +} From 477f4a1eb32c459d1d3ec364039ed31e7f5d8820 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Sat, 5 Dec 2015 19:19:24 +0100 Subject: [PATCH 10/10] Use remote api version constant --- src/main/java/com/github/dockerjava/api/DockerClient.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 586c40ff0..49eafcfca 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -48,6 +48,7 @@ import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.Identifier; +import com.github.dockerjava.core.RemoteApiVersion; // https://godoc.org/github.com/fsouza/go-dockerclient public interface DockerClient extends Closeable { @@ -129,7 +130,7 @@ public interface DockerClient extends Closeable { * @param containerId id of the container * @param resource path to container's resource * @return created command - * @since docker API version 1.20 and above. + * @since {@link RemoteApiVersion#VERSION_1_20} */ public CopyArchiveFromContainerCmd copyArchiveFromContainerCmd(@Nonnull String containerId, @Nonnull String resource); @@ -150,7 +151,7 @@ public interface DockerClient extends Closeable { * * @param containerId id of the container * @return created command - * @since docker API version 1.20 and above. + * @since {@link RemoteApiVersion#VERSION_1_20} */ public CopyArchiveToContainerCmd copyArchiveToContainerCmd(@Nonnull String containerId);