From 9639cb7bdf602887899feccdd639406e4c9323ca Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 28 Mar 2016 00:33:12 +0300 Subject: [PATCH 001/780] Refactor CertUtils. Support ECDSA and PrivateKey. --- .../core/util/CertificateUtils.java | 206 +++++++++++------- 1 file changed, 128 insertions(+), 78 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java index 562a954a7..6e1925630 100644 --- a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java +++ b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java @@ -2,30 +2,38 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; import java.security.KeyFactory; -import java.security.KeyPair; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; -import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.List; -import org.apache.commons.io.IOUtils; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.CheckForNull; + +import static java.util.Objects.requireNonNull; public class CertificateUtils { + private static final Logger LOG = LoggerFactory.getLogger(CertificateUtils.class); + private CertificateUtils() { // utility class } @@ -41,115 +49,157 @@ public static boolean verifyCertificatesExist(String dockerCertPath) { return result; } + /** + * @param dockerCertPath with standard named files. + */ public static KeyStore createKeyStore(final String dockerCertPath) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, CertificateException, KeyStoreException { - KeyPair keyPair = loadPrivateKey(dockerCertPath); - List privateCertificates = loadCertificates(dockerCertPath); + return createKeyStore("key.pem", "cert.pem"); + } + + + @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") + public static KeyStore createKeyStore(final String keypem, final String certpem) throws NoSuchAlgorithmException, + InvalidKeySpecException, IOException, CertificateException, KeyStoreException { + PrivateKey privateKey = loadPrivateKey(keypem); + requireNonNull(privateKey); + List privateCertificates = loadCertificates(certpem); KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(null); - keyStore.setKeyEntry("docker", keyPair.getPrivate(), "docker".toCharArray(), - privateCertificates.toArray(new Certificate[privateCertificates.size()])); + keyStore.setKeyEntry("docker", + privateKey, + "docker".toCharArray(), + privateCertificates.toArray(new Certificate[privateCertificates.size()]) + ); + return keyStore; } - public static KeyStore createTrustStore(final String dockerCertPath) throws IOException, CertificateException, - KeyStoreException, NoSuchAlgorithmException { - File caPath = new File(dockerCertPath, "ca.pem"); - BufferedReader reader = new BufferedReader(new FileReader(caPath)); - PEMParser pemParser = null; - - try { - pemParser = new PEMParser(reader); - X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject(); - Certificate caCertificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate( - certificateHolder); - - KeyStore trustStore = KeyStore.getInstance("JKS"); - trustStore.load(null); - trustStore.setCertificateEntry("ca", caCertificate); - return trustStore; - - } finally { - if (pemParser != null) { - IOUtils.closeQuietly(pemParser); - } - - if (reader != null) { - IOUtils.closeQuietly(reader); - } + /** + * from "cert.pem" String + */ + private static List loadCertificates(final String certpem) throws IOException, + CertificateException { + final StringReader certReader = new StringReader(certpem); + try (BufferedReader reader = new BufferedReader(certReader)) { + return loadCertificates(reader); } - } - private static List loadCertificates(final String dockerCertPath) throws IOException, + /** + * "cert.pem" from reader + */ + private static List loadCertificates(final Reader reader) throws IOException, CertificateException { - File certificate = new File(dockerCertPath, "cert.pem"); - BufferedReader reader = new BufferedReader(new FileReader(certificate)); - PEMParser pemParser = null; - - try { + try (PEMParser pemParser = new PEMParser(reader)) { List certificates = new ArrayList<>(); - pemParser = new PEMParser(reader); + JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter().setProvider("BC"); Object certObj = pemParser.readObject(); - while (certObj != null) { + if (certObj instanceof X509CertificateHolder) { X509CertificateHolder certificateHolder = (X509CertificateHolder) certObj; certificates.add(certificateConverter.getCertificate(certificateHolder)); - - certObj = pemParser.readObject(); } return certificates; - } finally { - if (pemParser != null) { - IOUtils.closeQuietly(pemParser); - } - - if (reader != null) { - IOUtils.closeQuietly(reader); - } } - } - private static KeyPair loadPrivateKey(final String dockerCertPath) throws IOException, NoSuchAlgorithmException, - InvalidKeySpecException { - File certificate = new File(dockerCertPath, "key.pem"); - BufferedReader reader = new BufferedReader(new FileReader(certificate)); - PEMParser pemParser = null; + /** + * Return private key ("key.pem") from Reader + */ + @CheckForNull + private static PrivateKey loadPrivateKey(final Reader reader) throws IOException, NoSuchAlgorithmException, + InvalidKeySpecException { + try (PEMParser pemParser = new PEMParser(reader)) { + Object readObject = pemParser.readObject(); + while (readObject != null) { + if (readObject instanceof PEMKeyPair) { + PEMKeyPair pemKeyPair = (PEMKeyPair) readObject; + PrivateKey privateKey = guessKey(pemKeyPair.getPrivateKeyInfo().getEncoded()); + if (privateKey != null) { + return privateKey; + } + } else if (readObject instanceof PrivateKeyInfo) { + PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) readObject; + PrivateKey privateKey = guessKey(privateKeyInfo.getEncoded()); + if (privateKey != null) { + return privateKey; + } + } else if (readObject instanceof ASN1ObjectIdentifier) { + // no idea how it can be used + final ASN1ObjectIdentifier asn1ObjectIdentifier = (ASN1ObjectIdentifier) readObject; + LOG.trace("Ignoring asn1ObjectIdentifier {}", asn1ObjectIdentifier); + } else { + LOG.warn("Unknown object '{}' from PEMParser", readObject); + } + + readObject = pemParser.readObject(); + } + } - try { - pemParser = new PEMParser(reader); + return null; + } - PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject(); + @CheckForNull + private static PrivateKey guessKey(byte[] encodedKey) throws NoSuchAlgorithmException { + //no way to know, so iterate + for (String guessFactory : new String[]{"RSA", "ECDSA"}) { + try { + KeyFactory factory = KeyFactory.getInstance(guessFactory); - byte[] pemPrivateKeyEncoded = pemKeyPair.getPrivateKeyInfo().getEncoded(); - byte[] pemPublicKeyEncoded = pemKeyPair.getPublicKeyInfo().getEncoded(); + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey); + return factory.generatePrivate(privateKeySpec); + } catch (InvalidKeySpecException ignore) { + } + } - KeyFactory factory = KeyFactory.getInstance("RSA"); + return null; + } - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pemPublicKeyEncoded); - PublicKey publicKey = factory.generatePublic(publicKeySpec); + /** + * Return KeyPair from "key.pem" + */ + @CheckForNull + private static PrivateKey loadPrivateKey(final String keypem) throws IOException, NoSuchAlgorithmException, + InvalidKeySpecException { + try (StringReader certReader = new StringReader(keypem); + BufferedReader reader = new BufferedReader(certReader)) { + return loadPrivateKey(reader); + } + } - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(pemPrivateKeyEncoded); - PrivateKey privateKey = factory.generatePrivate(privateKeySpec); + /** + * "ca.pem" from String + */ + public static KeyStore createTrustStore(String capem) throws IOException, CertificateException, + KeyStoreException, NoSuchAlgorithmException { + try (Reader certReader = new StringReader(capem)) { + return createTrustStore(certReader); + } + } - return new KeyPair(publicKey, privateKey); + /** + * "ca.pem" from Reader + */ + public static KeyStore createTrustStore(final Reader certReader) throws IOException, CertificateException, + KeyStoreException, NoSuchAlgorithmException { + try (PEMParser pemParser = new PEMParser(certReader)) { + X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject(); + Certificate caCertificate = new JcaX509CertificateConverter() + .setProvider("BC") + .getCertificate(certificateHolder); - } finally { - if (pemParser != null) { - IOUtils.closeQuietly(pemParser); - } + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(null); + trustStore.setCertificateEntry("ca", caCertificate); - if (reader != null) { - IOUtils.closeQuietly(reader); - } + return trustStore; } - } } From 741492cd1181443e81af3b3475d97c5ff93141fa Mon Sep 17 00:00:00 2001 From: Mikhail Stepura Date: Thu, 14 Apr 2016 13:57:39 -0700 Subject: [PATCH 002/780] Use named daemon threads for callback processing --- .../dockerjava/jaxrs/async/AbstractCallbackNotifier.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java index aac5a94d6..86f528af6 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java +++ b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java @@ -10,6 +10,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Invocation.Builder; @@ -18,6 +19,7 @@ import com.github.dockerjava.api.async.ResultCallback; import com.github.dockerjava.core.async.ResponseStreamProcessor; import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream; +import com.google.common.util.concurrent.ThreadFactoryBuilder; public abstract class AbstractCallbackNotifier implements Callable { @@ -25,6 +27,9 @@ public abstract class AbstractCallbackNotifier implements Callable { private final ResultCallback resultCallback; + private static final ThreadFactory FACTORY = + new ThreadFactoryBuilder().setDaemon(true).setNameFormat("dockerjava-jaxrs-async-%d").build(); + protected final Builder requestBuilder; protected AbstractCallbackNotifier(ResponseStreamProcessor responseStreamProcessor, @@ -76,7 +81,7 @@ public Void call() throws Exception { public static Future startAsyncProcessing(AbstractCallbackNotifier callbackNotifier) { - ExecutorService executorService = Executors.newSingleThreadExecutor(); + ExecutorService executorService = Executors.newSingleThreadExecutor(FACTORY); Future response = executorService.submit(callbackNotifier); executorService.shutdown(); return response; From 2f88b39a4954a2ebc88a4ebdfe74a245c6183685 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Mon, 18 Apr 2016 00:20:48 +0200 Subject: [PATCH 003/780] Add setters in order to be able to construct network creation request --- .../com/github/dockerjava/api/model/Network.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/model/Network.java b/src/main/java/com/github/dockerjava/api/model/Network.java index 546904254..583441049 100644 --- a/src/main/java/com/github/dockerjava/api/model/Network.java +++ b/src/main/java/com/github/dockerjava/api/model/Network.java @@ -149,6 +149,18 @@ public String getIpRange() { public String getGateway() { return gateway; } + + public void setSubnet(String subnet) { + this.subnet = subnet; + } + + public void setIpRange(String ipRange) { + this.ipRange = ipRange; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } } } } From 14f64794c722522da59ec8b83d6dd17f95f8a54d Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Mon, 18 Apr 2016 00:41:55 +0200 Subject: [PATCH 004/780] Fix NPE for withIpamConfig --- .../github/dockerjava/core/command/CreateNetworkCmdImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java index c7d3b0abb..b07076dc5 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java @@ -58,6 +58,9 @@ public CreateNetworkCmd withDriver(String driver) { @Override public CreateNetworkCmd withIpamConfig(Ipam.Config config) { + if (this.ipam == null) { + this.ipam = new Ipam(); + } this.ipam.getConfig().add(config); return this; } From 3ed7e7cf32943fbcf604eba3511faeb9c85f17e9 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Mon, 18 Apr 2016 00:54:25 +0200 Subject: [PATCH 005/780] Add test for network creation with ipam config --- .../dockerjava/core/command/CreateNetworkCmdImplTest.java | 5 +++-- .../dockerjava/netty/exec/CreateNetworkCmdExecTest.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java index eefeb535f..25225160b 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java @@ -40,8 +40,9 @@ public void afterMethod(ITestResult result) { public void createNetwork() throws DockerException { String networkName = "testNetwork"; - - CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).exec(); + Network.Ipam.Config config = new Network.Ipam.Config(); + config.setSubnet("10.67.79.0/24"); + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).withIpamConfig(config).exec(); assertNotNull(createNetworkResponse.getId()); diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java index fa9962826..cd5b788ed 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java @@ -40,8 +40,9 @@ public void afterMethod(ITestResult result) { public void createNetwork() throws DockerException { String networkName = "testNetwork"; - - CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).exec(); + Network.Ipam.Config config = new Network.Ipam.Config(); + config.setSubnet("10.67.79.0/24"); + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).withIpamConfig(config).exec(); assertNotNull(createNetworkResponse.getId()); From 41355559bbbfd0b8ea258f81951a23bb03417d11 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 22 Apr 2016 20:25:37 +0200 Subject: [PATCH 006/780] rename netty worker threads --- .../github/dockerjava/netty/DockerCmdExecFactoryImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java index 08a0179a1..8f704c7af 100644 --- a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java @@ -119,6 +119,7 @@ import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -148,6 +149,8 @@ */ public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { + private static String threadPrefix = "dockerjava-netty"; + /* * useful links: * @@ -215,7 +218,7 @@ private interface NettyInitializer { private class UnixDomainSocketInitializer implements NettyInitializer { @Override public EventLoopGroup init(Bootstrap bootstrap, DockerClientConfig dockerClientConfig) { - EventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(); + EventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); bootstrap.group(epollEventLoopGroup).channel(EpollDomainSocketChannel.class) .handler(new ChannelInitializer() { @Override @@ -235,7 +238,7 @@ public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { private class InetSocketInitializer implements NettyInitializer { @Override public EventLoopGroup init(Bootstrap bootstrap, final DockerClientConfig dockerClientConfig) { - EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(); + EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); InetAddress addr = InetAddress.getLoopbackAddress(); From fa0a69a3dbee6a940a21e77e6868ac95f7fbd660 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 22 Apr 2016 20:40:48 +0200 Subject: [PATCH 007/780] [maven-release-plugin] prepare release docker-java-3.0.0-RC5 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9ee5cad51..17964e6b9 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.0-SNAPSHOT + 3.0.0-RC5 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + docker-java-3.0.0-RC5 From f384eb4b293d498c3d0ac6adc3a51383ad1aede8 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 22 Apr 2016 20:40:53 +0200 Subject: [PATCH 008/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 17964e6b9..9ee5cad51 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.0-RC5 + 3.0.0-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - docker-java-3.0.0-RC5 + HEAD From 12e266bba47ad0a3e7f6b56a11a675b77a7b53b7 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Fri, 22 Apr 2016 20:48:10 +0200 Subject: [PATCH 009/780] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 196408717..2154f36a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Notes All changes +Included in 3.0.0-RC5 + * [#542] (https://github.com/docker-java/docker-java/pull/542) Fix large volumes of output from "docker exec" trigger out of memory error * [#541] (https://github.com/docker-java/docker-java/pull/541) ImageInspectResponse.GraphDriver.Data is more complex structure * [#534] (https://github.com/docker-java/docker-java/pull/534) Fix create volume command doesn't assign passed in volume driverOpts to field From a760dd5954cc465b840c79640cc436608e64b49c Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Fri, 22 Apr 2016 20:48:40 +0200 Subject: [PATCH 010/780] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a155d0c4..f2135f61b 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Supports a subset of the Docker Remote API [v1.22](https://github.com/docker/doc com.github.docker-java docker-java - 3.0.0-RC4 + 3.0.0-RC5 ### Latest development version From 89330387bf90fbe2bde1dcc3bea87b11be47fa06 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Sat, 30 Apr 2016 14:24:44 +0200 Subject: [PATCH 011/780] Separate tests --- .../command/CreateNetworkCmdImplTest.java | 21 ++++++++++++++----- .../netty/exec/CreateNetworkCmdExecTest.java | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java index 25225160b..c278f191b 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java @@ -5,11 +5,7 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.client.AbstractDockerClientTest; 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 org.testng.annotations.*; import java.lang.reflect.Method; @@ -39,6 +35,20 @@ public void afterMethod(ITestResult result) { @Test public void createNetwork() throws DockerException { + String networkName = "testNetwork"; + + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).exec(); + + assertNotNull(createNetworkResponse.getId()); + + Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); + assertEquals(network.getName(), networkName); + assertEquals(network.getDriver(), "bridge"); + } + + @Test + public void createNetworkWithCustomConfig() throws DockerException { + String networkName = "testNetwork"; Network.Ipam.Config config = new Network.Ipam.Config(); config.setSubnet("10.67.79.0/24"); @@ -49,5 +59,6 @@ public void createNetwork() throws DockerException { Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); assertEquals(network.getName(), networkName); assertEquals(network.getDriver(), "bridge"); + assertEquals("10.67.79.0/24", network.getIpam().getConfig().iterator().next().getSubnet()); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java index cd5b788ed..974d684b8 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java @@ -5,11 +5,7 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; 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 org.testng.annotations.*; import java.lang.reflect.Method; @@ -39,6 +35,20 @@ public void afterMethod(ITestResult result) { @Test public void createNetwork() throws DockerException { + String networkName = "testNetwork"; + + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).exec(); + + assertNotNull(createNetworkResponse.getId()); + + Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); + assertEquals(network.getName(), networkName); + assertEquals(network.getDriver(), "bridge"); + } + + @Test + public void createNetworkWithCustomConfig() throws DockerException { + String networkName = "testNetwork"; Network.Ipam.Config config = new Network.Ipam.Config(); config.setSubnet("10.67.79.0/24"); @@ -49,5 +59,6 @@ public void createNetwork() throws DockerException { Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); assertEquals(network.getName(), networkName); assertEquals(network.getDriver(), "bridge"); + assertEquals("10.67.79.0/24", network.getIpam().getConfig().iterator().next().getSubnet()); } } From b8f87dcf3897390414dd55f6cbe1016cd0859929 Mon Sep 17 00:00:00 2001 From: Yannick Lorenzati Date: Sat, 30 Apr 2016 14:40:41 +0200 Subject: [PATCH 012/780] docker java generate empty filter instead of no filter #557 --- .../java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java | 2 +- .../com/github/dockerjava/netty/exec/ListContainersCmdExec.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java index fd882b673..50311ef54 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java @@ -37,7 +37,7 @@ protected List execute(ListContainersCmd command) { webTarget = webTarget.queryParam("limit", String.valueOf(command.getLimit())); } - if (command.getFilters() != null) { + if (command.getFilters() != null && !command.getFilters().isEmpty()) { webTarget = webTarget .queryParam("filters", urlPathSegmentEscaper().escape(FiltersEncoder.jsonEncode(command.getFilters()))); } diff --git a/src/main/java/com/github/dockerjava/netty/exec/ListContainersCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/ListContainersCmdExec.java index 219aebc4b..e5ab4b66b 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/ListContainersCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/ListContainersCmdExec.java @@ -36,7 +36,7 @@ protected List execute(ListContainersCmd command) { webTarget = webTarget.queryParam("limit", String.valueOf(command.getLimit())); } - if (command.getFilters() != null) { + if (command.getFilters() != null && !command.getFilters().isEmpty()) { webTarget = webTarget .queryParam("filters", urlPathSegmentEscaper().escape(FiltersEncoder.jsonEncode(command.getFilters()))); } From 4d605506b2a1512977103f9313259b503917d35d Mon Sep 17 00:00:00 2001 From: fb Date: Sat, 27 Feb 2016 11:11:47 +0100 Subject: [PATCH 013/780] implement links and aliases for user defined networks add missing network options add tests --- .../api/command/ConnectToNetworkCmd.java | 6 + .../api/command/CreateContainerCmd.java | 34 ++++- .../api/command/CreateNetworkCmd.java | 33 +++-- .../api/command/DisconnectFromNetworkCmd.java | 5 + .../api/model/ContainerNetwork.java | 73 +++++++++-- .../dockerjava/api/model/HostConfig.java | 12 ++ .../github/dockerjava/api/model/Network.java | 35 ++++- .../dockerjava/api/model/NetworkSettings.java | 90 +------------ .../core/command/ConnectToNetworkCmdImpl.java | 15 +++ .../core/command/CreateContainerCmdImpl.java | 122 ++++++++++++++++-- .../core/command/CreateNetworkCmdImpl.java | 51 +++++++- .../command/DisconnectFromNetworkCmdImpl.java | 14 ++ .../core/command/RemoveNetworkCmdImpl.java | 1 - .../command/ConnectToNetworkCmdImplTest.java | 52 +++++++- .../command/CreateContainerCmdImplTest.java | 106 +++++++++++++++ .../DisconnectFromNetworkCmdImplTest.java | 22 ++++ 16 files changed, 542 insertions(+), 129 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/ConnectToNetworkCmd.java b/src/main/java/com/github/dockerjava/api/command/ConnectToNetworkCmd.java index cd5c57774..0f384e043 100644 --- a/src/main/java/com/github/dockerjava/api/command/ConnectToNetworkCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/ConnectToNetworkCmd.java @@ -1,5 +1,6 @@ package com.github.dockerjava.api.command; +import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.core.RemoteApiVersion; import javax.annotation.CheckForNull; @@ -18,10 +19,15 @@ public interface ConnectToNetworkCmd extends SyncDockerCmd { @CheckForNull String getContainerId(); + @CheckForNull + ContainerNetwork getContainerConfig(); + ConnectToNetworkCmd withNetworkId(@Nonnull String networkId); ConnectToNetworkCmd withContainerId(@Nonnull String containerId); + ConnectToNetworkCmd withContainerNetwork(@Nonnull ContainerNetwork endpointConfig); + interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java index ffcb01c98..196763560 100644 --- a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java @@ -1,10 +1,5 @@ package com.github.dockerjava.api.command; -import java.util.List; -import java.util.Map; - -import javax.annotation.CheckForNull; - import com.github.dockerjava.api.exception.ConflictException; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.Bind; @@ -21,8 +16,15 @@ import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; +import javax.annotation.CheckForNull; +import java.util.List; +import java.util.Map; + public interface CreateContainerCmd extends SyncDockerCmd { + @CheckForNull + List getAliases(); + @CheckForNull Bind[] getBinds(); @@ -92,6 +94,12 @@ public interface CreateContainerCmd extends SyncDockerCmd getLabels(); @@ -185,6 +193,18 @@ public interface CreateContainerCmd extends SyncDockerCmd aliases); + CreateContainerCmd withAttachStderr(Boolean attachStderr); CreateContainerCmd withAttachStdin(Boolean attachStdin); @@ -304,6 +324,10 @@ public interface CreateContainerCmd extends SyncDockerCmd labels); /** diff --git a/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java index 6ad26b605..39989bd13 100644 --- a/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java @@ -1,14 +1,13 @@ package com.github.dockerjava.api.command; -import java.util.Map; - -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; - import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.Network.Ipam; import com.github.dockerjava.core.RemoteApiVersion; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import java.util.Map; + /** * Create a network. * @@ -25,18 +24,36 @@ public interface CreateNetworkCmd extends SyncDockerCmd { @CheckForNull Network.Ipam getIpam(); + @CheckForNull + Map getOptions(); + + @CheckForNull + Boolean getCheckDuplicate(); + + @CheckForNull + Boolean getInternal(); + + @CheckForNull + Boolean getEnableIPv6(); + /** The new network's name. Required. */ CreateNetworkCmd withName(@Nonnull String name); - /** Optional custom IP scheme for the network. */ - CreateNetworkCmd withIpamConfig(Ipam.Config config); - /** Name of the network driver to use. Defaults to bridge. */ CreateNetworkCmd withDriver(String driver); + /** Ipam config, such es subnet, gateway and ip range of the network */ + CreateNetworkCmd withIpam(Ipam ipam); + /** Driver specific options */ CreateNetworkCmd withOptions(Map options); + CreateNetworkCmd withCheckDuplicate(boolean checkForDuplicate); + + CreateNetworkCmd withInternal(boolean internal); + + CreateNetworkCmd withEnableIpv6(boolean enableIpv6); + interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/command/DisconnectFromNetworkCmd.java b/src/main/java/com/github/dockerjava/api/command/DisconnectFromNetworkCmd.java index ca870ef37..ce75172b4 100644 --- a/src/main/java/com/github/dockerjava/api/command/DisconnectFromNetworkCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/DisconnectFromNetworkCmd.java @@ -18,10 +18,15 @@ public interface DisconnectFromNetworkCmd extends SyncDockerCmd { @CheckForNull String getContainerId(); + @CheckForNull + Boolean getForce(); + DisconnectFromNetworkCmd withNetworkId(@Nonnull String networkId); DisconnectFromNetworkCmd withContainerId(@Nonnull String containerId); + DisconnectFromNetworkCmd withForce(@Nonnull Boolean force); + interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java b/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java index 4bfde8bfd..9b2160e98 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java @@ -1,5 +1,6 @@ package com.github.dockerjava.api.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.github.dockerjava.core.RemoteApiVersion; @@ -8,9 +9,14 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.util.Arrays; import java.util.List; /** + * Types taken form + * {@see https://github.com/docker/engine-api/blob/release/1.10/types/network/network.go} + * Docker named it EndpointSettings + * * @see ContainerNetworkSettings * @author Kanstantsin Shautsou */ @@ -20,16 +26,16 @@ public class ContainerNetwork { * FIXME verify */ @JsonProperty("IPAMConfig") - private Network.Ipam.Config ipamConfig; + private Ipam ipamConfig; /** * FIXME verify */ @JsonProperty("Links") - private List links; + private Links links; /** - * FIXME no docs, unknown field. + * Add network-scoped alias for the container * Type picked from `docker/vendor/src/github.com/docker/engine-api/types/network/network.go` * * @since {@link RemoteApiVersion#VERSION_1_22} @@ -80,6 +86,14 @@ public ContainerNetwork withAliases(List aliases) { return this; } + /** + * @see #aliases + */ + public ContainerNetwork withAliases(String... aliases) { + this.aliases = Arrays.asList(aliases); + return this; + } + /** * @see #endpointId */ @@ -155,7 +169,7 @@ public String getIpAddress() { /** * @see #ipAddress */ - public ContainerNetwork withIpAddress(String ipAddress) { + public ContainerNetwork withIpv4Address(String ipAddress) { this.ipAddress = ipAddress; return this; } @@ -164,14 +178,14 @@ public ContainerNetwork withIpAddress(String ipAddress) { * @see #ipamConfig */ @CheckForNull - public Network.Ipam.Config getIpamConfig() { + public Ipam getIpamConfig() { return ipamConfig; } /** * @see #ipamConfig */ - public ContainerNetwork withIpamConfig(Network.Ipam.Config ipamConfig) { + public ContainerNetwork withIpamConfig(Ipam ipamConfig) { this.ipamConfig = ipamConfig; return this; } @@ -212,15 +226,24 @@ public ContainerNetwork withIpV6Gateway(String ipV6Gateway) { * @see #links */ @CheckForNull - public List getLinks() { - return links; + @JsonIgnore + public Link[] getLinks() { + return links == null ? new Link[0] : links.getLinks(); + } + + /** + * @see #links + */ + public ContainerNetwork withLinks(List links) { + this.links = new Links(links); + return this; } /** * @see #links */ - public ContainerNetwork withLinks(List links) { - this.links = links; + public ContainerNetwork withLinks(Link... links) { + this.links = new Links(links); return this; } @@ -270,4 +293,34 @@ public boolean equals(Object o) { public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } + + /** + * Docker named it EndpointIPAMConfig + */ + public static class Ipam { + + @JsonProperty("IPv4Address") + private String ipv4Address; + + @JsonProperty("IPv6Address") + private String ipv6Address; + + public String getIpv4Address() { + return ipv4Address; + } + + public String getIpv6Address() { + return ipv6Address; + } + + public Ipam withIpv4Address(String ipv4Address) { + this.ipv4Address = ipv4Address; + return this; + } + + public Ipam withIpv6Address(String ipv6Address) { + this.ipv6Address = ipv6Address; + return this; + } + } } diff --git a/src/main/java/com/github/dockerjava/api/model/HostConfig.java b/src/main/java/com/github/dockerjava/api/model/HostConfig.java index 400ae29dd..19a6a9128 100644 --- a/src/main/java/com/github/dockerjava/api/model/HostConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/HostConfig.java @@ -11,6 +11,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.util.Arrays; import java.util.List; /** @@ -21,6 +22,8 @@ @JsonInclude(Include.NON_NULL) public class HostConfig { + private static final List PREDEFINED_NETWORKS = Arrays.asList("bridge", "host", "none"); + @JsonProperty("Binds") private Binds binds; @@ -410,6 +413,15 @@ public String getVolumeDriver() { return volumeDriver; } + /** + * Parse the network mode as specified at + * {@see https://github.com/docker/engine-api/blob/master/types/container/hostconfig_unix.go} + */ + @JsonIgnore + public boolean isUserDefinedNetwork() { + return networkMode != null && !PREDEFINED_NETWORKS.contains(networkMode) && !networkMode.startsWith("container:"); + } + @JsonIgnore public void setBinds(Bind... binds) { this.binds = new Binds(binds); diff --git a/src/main/java/com/github/dockerjava/api/model/Network.java b/src/main/java/com/github/dockerjava/api/model/Network.java index 546904254..6f4114914 100644 --- a/src/main/java/com/github/dockerjava/api/model/Network.java +++ b/src/main/java/com/github/dockerjava/api/model/Network.java @@ -6,6 +6,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -111,16 +112,33 @@ public static class Ipam { private String driver; @JsonProperty("Config") - List config = new ArrayList<>(); + private List config = new ArrayList<>(); + + @JsonProperty("Options") + private Map options = null; public String getDriver() { return driver; } + public Map getOptions() { + return options; + } + public List getConfig() { return config; } + public Ipam withConfig(List ipamConfigs) { + config = ipamConfigs; + return this; + } + + public Ipam withConfig(Config... ipamConfigs) { + config = Arrays.asList(ipamConfigs); + return this; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); @@ -149,6 +167,21 @@ public String getIpRange() { public String getGateway() { return gateway; } + + public Config withSubnet(String subnet) { + this.subnet = subnet; + return this; + } + + public Config withIpRange(String ipRange) { + this.ipRange = ipRange; + return this; + } + + public Config withGateway(String gateway) { + this.gateway = gateway; + return this; + } } } } diff --git a/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java b/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java index 680048c18..1d523bf4b 100644 --- a/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java +++ b/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java @@ -3,15 +3,12 @@ */ package com.github.dockerjava.api.model; -import java.util.Map; - -import org.apache.commons.lang.builder.ToStringBuilder; - import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.github.dockerjava.core.RemoteApiVersion; +import org.apache.commons.lang.builder.ToStringBuilder; -import javax.annotation.CheckForNull; +import java.util.Map; /** * @@ -76,7 +73,7 @@ public class NetworkSettings { private String macAddress; @JsonProperty("Networks") - private Map networks; + private Map networks; /** * @deprecated since {@link RemoteApiVersion#VERSION_1_21} @@ -135,7 +132,7 @@ public String getIpV6Gateway() { /** * @since {@link RemoteApiVersion#VERSION_1_21} */ - public Map getNetworks() { + public Map getNetworks() { return networks; } @@ -206,83 +203,4 @@ public Integer getGlobalIPv6PrefixLen() { public String toString() { return ToStringBuilder.reflectionToString(this); } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Network { - - @JsonProperty("IPAMConfig") - private String ipamConfig; - - /** - * @since {@link RemoteApiVersion#VERSION_1_22} - */ - @JsonProperty("NetworkID") - private String networkID; - - @JsonProperty("EndpointID") - private String endpointId; - - @JsonProperty("Gateway") - private String gateway; - - @JsonProperty("IPAddress") - private String ipAddress; - - @JsonProperty("IPPrefixLen") - private Integer ipPrefixLen; - - @JsonProperty("IPv6Gateway") - private String ipV6Gateway; - - @JsonProperty("GlobalIPv6Address") - private String globalIPv6Address; - - @JsonProperty("GlobalIPv6PrefixLen") - private Integer globalIPv6PrefixLen; - - @JsonProperty("MacAddress") - private String macAddress; - - @CheckForNull - public String getNetworkID() { - return networkID; - } - - public String getEndpointId() { - return endpointId; - } - - public String getGateway() { - return gateway; - } - - public String getIpAddress() { - return ipAddress; - } - - public Integer getIpPrefixLen() { - return ipPrefixLen; - } - - public String getIpV6Gateway() { - return ipV6Gateway; - } - - public String getGlobalIPv6Address() { - return globalIPv6Address; - } - - public Integer getGlobalIPv6PrefixLen() { - return globalIPv6PrefixLen; - } - - public String getMacAddress() { - return macAddress; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - } } diff --git a/src/main/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImpl.java index 7014704b1..93fd8abb8 100644 --- a/src/main/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImpl.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.github.dockerjava.api.command.ConnectToNetworkCmd; import com.github.dockerjava.api.command.DockerCmdSyncExec; +import com.github.dockerjava.api.model.ContainerNetwork; public class ConnectToNetworkCmdImpl extends AbstrDockerCmd implements ConnectToNetworkCmd { @@ -13,6 +14,9 @@ public class ConnectToNetworkCmdImpl extends AbstrDockerCmd execution) { super(execution); } @@ -27,6 +31,11 @@ public String getContainerId() { return containerId; } + @Override + public ContainerNetwork getContainerConfig() { + return endpointConfig; + } + @Override public ConnectToNetworkCmd withNetworkId(String networkId) { this.networkId = networkId; @@ -38,4 +47,10 @@ public ConnectToNetworkCmd withContainerId(String containerId) { this.containerId = containerId; return this; } + + @Override + public ConnectToNetworkCmd withContainerNetwork(ContainerNetwork endpointConfig) { + this.endpointConfig = endpointConfig; + return this; + } } diff --git a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java index 48b93a004..0b6944b04 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java @@ -1,14 +1,5 @@ package com.github.dockerjava.core.command; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -19,6 +10,7 @@ import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.Bind; import com.github.dockerjava.api.model.Capability; +import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.Device; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.ExposedPorts; @@ -33,6 +25,16 @@ import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.Volumes; import com.github.dockerjava.api.model.VolumesFrom; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Collections.singletonMap; /** * Creates a new container. @@ -113,6 +115,18 @@ public class CreateContainerCmdImpl extends AbstrDockerCmd labels; + @JsonProperty("NetworkingConfig") + private NetworkingConfig networkingConfig; + + @JsonIgnore + private String ipv4Address = null; + + @JsonIgnore + private String ipv6Address = null; + + @JsonIgnore + private List aliases = null; + public CreateContainerCmdImpl(CreateContainerCmd.Exec exec, String image) { super(exec); checkNotNull(image, "image was not specified"); @@ -127,9 +141,48 @@ public CreateContainerCmdImpl(CreateContainerCmd.Exec exec, String image) { */ @Override public CreateContainerResponse exec() throws NotFoundException, ConflictException { + //code flow taken from https://github.com/docker/docker/blob/master/runconfig/opts/parse.go + ContainerNetwork containerNetwork = null; + + if (ipv4Address != null || ipv6Address != null) { + containerNetwork = new ContainerNetwork() + .withIpamConfig(new ContainerNetwork.Ipam() + .withIpv4Address(ipv4Address) + .withIpv6Address(ipv6Address) + ); + + } + + if (hostConfig.isUserDefinedNetwork() && hostConfig.getLinks().length > 0) { + if (containerNetwork == null) { + containerNetwork = new ContainerNetwork(); + } + + containerNetwork.withLinks(hostConfig.getLinks()); + } + + if (aliases != null) { + if (containerNetwork == null) { + containerNetwork = new ContainerNetwork(); + } + + containerNetwork.withAliases(aliases); + } + + if (containerNetwork != null) { + networkingConfig = new NetworkingConfig() + .withEndpointsConfig(singletonMap(hostConfig.getNetworkMode(), containerNetwork)); + } + return super.exec(); } + @Override + @JsonIgnore + public List getAliases() { + return aliases; + } + @Override @JsonIgnore public Bind[] getBinds() { @@ -247,6 +300,16 @@ public String getImage() { return image; } + @Override + public String getIpv4Address() { + return ipv4Address; + } + + @Override + public String getIpv6Address() { + return ipv6Address; + } + @Override @JsonIgnore public Map getLabels() { @@ -414,6 +477,19 @@ public String getCgroupParent() { return hostConfig.getCgroupParent(); } + @Override + public CreateContainerCmd withAliases(String... aliases) { + this.aliases = Arrays.asList(aliases); + return this; + } + + @Override + public CreateContainerCmd withAliases(List aliases) { + checkNotNull(aliases, "aliases was not specified"); + this.aliases = aliases; + return this; + } + @Override public CreateContainerCmd withAttachStderr(Boolean attachStderr) { checkNotNull(attachStderr, "attachStderr was not specified"); @@ -648,6 +724,20 @@ public CreateContainerCmd withImage(String image) { return this; } + @Override + public CreateContainerCmd withIpv4Address(String ipv4Address) { + checkNotNull(ipv4Address, "no ipv4Address was specified"); + this.ipv4Address = ipv4Address; + return this; + } + + @Override + public CreateContainerCmd withIpv6Address(String ipv6Address) { + checkNotNull(ipv6Address, "no ipv6Address was specified"); + this.ipv6Address = ipv6Address; + return this; + } + @Override public CreateContainerCmd withLabels(Map labels) { checkNotNull(labels, "labels was not specified"); @@ -900,4 +990,18 @@ public boolean equals(Object o) { public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } + + public static class NetworkingConfig { + @JsonProperty("EndpointsConfig") + public Map endpointsConfig; + + public Map getEndpointsConfig() { + return endpointsConfig; + } + + public NetworkingConfig withEndpointsConfig(Map endpointsConfig) { + this.endpointsConfig = endpointsConfig; + return this; + } + } } diff --git a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java index c7d3b0abb..834aa6905 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java @@ -25,6 +25,15 @@ public class CreateNetworkCmdImpl extends AbstrDockerCmd options = new HashMap<>(); + @JsonProperty("CheckDuplicate") + private Boolean checkDuplicate; + + @JsonProperty("Internal") + private Boolean internal; + + @JsonProperty("EnableIPv6") + private Boolean enableIpv6; + public CreateNetworkCmdImpl(DockerCmdSyncExec execution) { super(execution); } @@ -44,6 +53,26 @@ public Network.Ipam getIpam() { return ipam; } + @Override + public Map getOptions() { + return options; + } + + @Override + public Boolean getCheckDuplicate() { + return checkDuplicate; + } + + @Override + public Boolean getInternal() { + return internal; + } + + @Override + public Boolean getEnableIPv6() { + return enableIpv6; + } + @Override public CreateNetworkCmd withName(String name) { this.name = name; @@ -57,8 +86,8 @@ public CreateNetworkCmd withDriver(String driver) { } @Override - public CreateNetworkCmd withIpamConfig(Ipam.Config config) { - this.ipam.getConfig().add(config); + public CreateNetworkCmd withIpam(Ipam ipam) { + this.ipam = ipam; return this; } @@ -67,4 +96,22 @@ public CreateNetworkCmd withOptions(Map options) { this.options = options; return this; } + + @Override + public CreateNetworkCmd withCheckDuplicate(boolean checkDuplicate) { + this.checkDuplicate = checkDuplicate; + return this; + } + + @Override + public CreateNetworkCmd withInternal(boolean internal) { + this.internal = internal; + return this; + } + + @Override + public CreateNetworkCmd withEnableIpv6(boolean enableIpv6) { + this.enableIpv6 = enableIpv6; + return this; + } } diff --git a/src/main/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImpl.java index ae24946b6..b871b36c6 100644 --- a/src/main/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImpl.java @@ -14,6 +14,9 @@ public class DisconnectFromNetworkCmdImpl extends AbstrDockerCmd execution) { super(execution); } @@ -28,6 +31,11 @@ public String getContainerId() { return containerId; } + @Override + public Boolean getForce() { + return force; + } + @Override public DisconnectFromNetworkCmd withNetworkId(String networkId) { this.networkId = networkId; @@ -39,4 +47,10 @@ public DisconnectFromNetworkCmd withContainerId(String containerId) { this.containerId = containerId; return this; } + + @Override + public DisconnectFromNetworkCmd withForce(Boolean force) { + this.force = force; + return this; + } } diff --git a/src/main/java/com/github/dockerjava/core/command/RemoveNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/RemoveNetworkCmdImpl.java index ced7279f9..cc9465244 100644 --- a/src/main/java/com/github/dockerjava/core/command/RemoveNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/RemoveNetworkCmdImpl.java @@ -14,7 +14,6 @@ public RemoveNetworkCmdImpl(DockerCmdSyncExec execution, @Override public String getNetworkId() { - return networkId; } diff --git a/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java index ad051e0bd..f67994de6 100644 --- a/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java @@ -1,7 +1,11 @@ package com.github.dockerjava.core.command; -import java.lang.reflect.Method; - +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.CreateNetworkResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.ContainerNetwork; +import com.github.dockerjava.api.model.Network; +import com.github.dockerjava.client.AbstractDockerClientTest; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -9,11 +13,8 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.command.CreateNetworkResponse; -import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerjava.api.model.Network; -import com.github.dockerjava.client.AbstractDockerClientTest; +import java.lang.reflect.Method; +import java.util.Collections; @Test(groups = "integration") public class ConnectToNetworkCmdImplTest extends AbstractDockerClientTest { @@ -56,4 +57,41 @@ public void connectToNetwork() throws InterruptedException { assertNotNull(inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork")); } + + @Test + public void connectToNetworkWithContainerNetwork() throws InterruptedException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + dockerClient.startContainerCmd(container.getId()).exec(); + + CreateNetworkResponse network = dockerClient.createNetworkCmd() + .withName("testNetwork") + .withIpam(new Network.Ipam() + .withConfig(new Network.Ipam.Config() + .withSubnet("10.100.100.0/24"))) + .exec(); + + dockerClient.connectToNetworkCmd() + .withNetworkId(network.getId()) + .withContainerId(container.getId()) + .withContainerNetwork(new ContainerNetwork() + .withAliases("testing") + .withIpamConfig(new ContainerNetwork.Ipam() + .withIpv4Address("10.100.100.100"))) + .exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + + Network.ContainerNetworkConfig containerNetworkConfig = updatedNetwork.getContainers().get(container.getId()); + assertNotNull(containerNetworkConfig); + assertEquals("10.100.100.100", containerNetworkConfig.getIpv4Address()); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork"); + assertNotNull(testNetwork); + assertEquals(Collections.singletonList("testing"), testNetwork.getAliases()); + assertEquals("10.100.100.0", testNetwork.getGateway()); + assertEquals("10.100.100.100", testNetwork.getIpAddress()); + } } diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index f2fd32b6a..682edc4ce 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -1,15 +1,18 @@ package com.github.dockerjava.core.command; import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.CreateNetworkResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.exception.ConflictException; import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.Bind; +import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.Device; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.Frame; import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.LogConfig; +import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.Ports; import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.api.model.Ulimit; @@ -22,10 +25,12 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import org.testng.internal.junit.ArrayAsserts; import java.lang.reflect.Method; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -268,6 +273,107 @@ public void createContainerWithLink() throws DockerException { "container1Link")})); } + @Test + public void createContainerWithLinkInCustomNetwork() throws DockerException { + + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd() + .withName("linkNet") + .exec(); + + assertNotNull(createNetworkResponse.getId()); + + CreateContainerResponse container1 = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withNetworkMode("linkNet") + .withCmd("sleep", "9999") + .withName("container1") + .exec(); + + assertThat(container1.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container1.getId()).exec(); + + InspectContainerResponse inspectContainerResponse1 = dockerClient.inspectContainerCmd(container1.getId()) + .exec(); + LOG.info("Container1 Inspect: {}", inspectContainerResponse1.toString()); + assertThat(inspectContainerResponse1.getState().getRunning(), is(true)); + + CreateContainerResponse container2 = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withNetworkMode("linkNet") + .withName("container2") + .withCmd("env") + .withLinks(new Link("container1", "container1Link")) + .exec(); + + LOG.info("Created container {}", container2.toString()); + assertThat(container2.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse2 = dockerClient.inspectContainerCmd(container2.getId()) + .exec(); + + ContainerNetwork linkNet = inspectContainerResponse2.getNetworkSettings().getNetworks().get("linkNet"); + assertNotNull(linkNet); + ArrayAsserts.assertArrayEquals(new Link[]{ new Link("container1", "container1Link")}, linkNet.getLinks()); + } + + @Test + public void createContainerWithCustomIp() throws DockerException { + + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd() + .withIpam(new Network.Ipam() + .withConfig(new Network.Ipam.Config() + .withSubnet("10.100.101.0/24"))) + .withName("customIpNet") + .exec(); + + assertNotNull(createNetworkResponse.getId()); + + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withNetworkMode("customIpNet") + .withCmd("sleep", "9999") + .withName("container") + .withIpv4Address("10.100.101.100") + .exec(); + + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()) + .exec(); + + ContainerNetwork customIpNet = inspectContainerResponse.getNetworkSettings().getNetworks().get("customIpNet"); + assertNotNull(customIpNet); + assertEquals("10.100.101.0", customIpNet.getGateway()); + assertEquals("10.100.101.100", customIpNet.getIpAddress()); + } + + @Test + public void createContainerWithAlias() throws DockerException { + + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd() + .withName("aliasNet") + .exec(); + + assertNotNull(createNetworkResponse.getId()); + + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withNetworkMode("aliasNet") + .withCmd("sleep", "9999") + .withName("container") + .withAliases("server") + .exec(); + + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()) + .exec(); + + ContainerNetwork aliasNet = inspectContainerResponse.getNetworkSettings().getNetworks().get("aliasNet"); + assertEquals(Collections.singletonList("server"), aliasNet.getAliases()); + } + @Test public void createContainerWithCapAddAndCapDrop() throws DockerException { diff --git a/src/test/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImplTest.java index 7f94c5a0f..c4219b54e 100644 --- a/src/test/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/DisconnectFromNetworkCmdImplTest.java @@ -56,4 +56,26 @@ public void disconnectFromNetwork() throws InterruptedException { assertFalse(updatedNetwork.getContainers().containsKey(container.getId())); } + + @Test + public void forceDisconnectFromNetwork() throws InterruptedException { + + CreateNetworkResponse network = dockerClient.createNetworkCmd().withName("testNetwork").exec(); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withNetworkMode("testNetwork") + .withCmd("sleep", "9999") + .exec(); + + dockerClient.startContainerCmd(container.getId()).exec(); + + dockerClient.disconnectFromNetworkCmd() + .withNetworkId(network.getId()) + .withContainerId(container.getId()) + .withForce(true) + .exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + assertFalse(updatedNetwork.getContainers().containsKey(container.getId())); + } } From 54d34f0c00e0ba6b81b05e82d782f050b165cff6 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Mon, 2 May 2016 21:34:59 +0200 Subject: [PATCH 014/780] Fix issue #560 --- .../netty/handler/FramedResponseStreamHandler.java | 2 +- .../github/dockerjava/netty/handler/HttpResponseHandler.java | 5 ++++- .../netty/handler/JsonResponseCallbackHandler.java | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/handler/FramedResponseStreamHandler.java b/src/main/java/com/github/dockerjava/netty/handler/FramedResponseStreamHandler.java index f360ca756..534894a99 100644 --- a/src/main/java/com/github/dockerjava/netty/handler/FramedResponseStreamHandler.java +++ b/src/main/java/com/github/dockerjava/netty/handler/FramedResponseStreamHandler.java @@ -45,7 +45,7 @@ public FramedResponseStreamHandler(ResultCallback resultCallback) { @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { - rawBuffer.writeBytes(msg.copy(), 0, msg.readableBytes()); + rawBuffer.writeBytes(msg, 0, msg.readableBytes()); Frame frame = null; diff --git a/src/main/java/com/github/dockerjava/netty/handler/HttpResponseHandler.java b/src/main/java/com/github/dockerjava/netty/handler/HttpResponseHandler.java index 571fa9be5..9986e10e9 100644 --- a/src/main/java/com/github/dockerjava/netty/handler/HttpResponseHandler.java +++ b/src/main/java/com/github/dockerjava/netty/handler/HttpResponseHandler.java @@ -120,6 +120,9 @@ public void close() { } private String getBodyAsMessage(ByteBuf body) { - return body.readBytes(body.readableBytes()).toString(Charset.forName("UTF-8")); + String result = body.readBytes(body.readableBytes()).toString(Charset.forName("UTF-8")); + body.discardReadBytes(); + body.release(); + return result; } } diff --git a/src/main/java/com/github/dockerjava/netty/handler/JsonResponseCallbackHandler.java b/src/main/java/com/github/dockerjava/netty/handler/JsonResponseCallbackHandler.java index b5f76ab73..db20d6216 100644 --- a/src/main/java/com/github/dockerjava/netty/handler/JsonResponseCallbackHandler.java +++ b/src/main/java/com/github/dockerjava/netty/handler/JsonResponseCallbackHandler.java @@ -30,6 +30,7 @@ public JsonResponseCallbackHandler(TypeReference typeReference, ResultCallbac protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { byte[] buffer = new byte[msg.readableBytes()]; msg.readBytes(buffer); + msg.discardReadBytes(); T object = null; From 1ab6e63c4c6eb30baa66771d97f244735565dc0b Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Mon, 2 May 2016 21:49:39 +0200 Subject: [PATCH 015/780] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2154f36a7..f88303a1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Notes All changes +* [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory + Included in 3.0.0-RC5 * [#542] (https://github.com/docker-java/docker-java/pull/542) Fix large volumes of output from "docker exec" trigger out of memory error From 90ff0bd99b490a3eb4553f36c222a7c5d3881af6 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Thu, 5 May 2016 20:43:46 +0200 Subject: [PATCH 016/780] Fix imports --- .../dockerjava/core/command/CreateNetworkCmdImplTest.java | 6 +++++- .../dockerjava/netty/exec/CreateNetworkCmdExecTest.java | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java index c278f191b..f56a89f64 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java @@ -5,7 +5,11 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.client.AbstractDockerClientTest; import org.testng.ITestResult; -import org.testng.annotations.*; +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 java.lang.reflect.Method; diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java index 974d684b8..35602ddd9 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java @@ -5,7 +5,11 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; import org.testng.ITestResult; -import org.testng.annotations.*; +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 java.lang.reflect.Method; From 4431df9c0dee7d6d75554c27a59c5157caf6b395 Mon Sep 17 00:00:00 2001 From: VU Minh Khang Date: Fri, 6 May 2016 10:20:46 +0200 Subject: [PATCH 017/780] Fix test names --- .../dockerjava/core/command/CreateNetworkCmdImplTest.java | 2 +- .../github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java index f56a89f64..4875ba7c5 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java @@ -51,7 +51,7 @@ public void createNetwork() throws DockerException { } @Test - public void createNetworkWithCustomConfig() throws DockerException { + public void createNetworkWithIpamConfig() throws DockerException { String networkName = "testNetwork"; Network.Ipam.Config config = new Network.Ipam.Config(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java index 35602ddd9..63f2eb620 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateNetworkCmdExecTest.java @@ -51,7 +51,7 @@ public void createNetwork() throws DockerException { } @Test - public void createNetworkWithCustomConfig() throws DockerException { + public void createNetworkWithIpamConfig() throws DockerException { String networkName = "testNetwork"; Network.Ipam.Config config = new Network.Ipam.Config(); From 0f0353a95a22748a52e99856596bcc32c670b419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Warcha=C5=82?= Date: Fri, 6 May 2016 11:57:27 +0200 Subject: [PATCH 018/780] Throws exception when WaitContainerResultCallback timeouts Fixes #570 --- .../command/WaitContainerResultCallback.java | 4 +- .../command/WaitContainerCmdImplTest.java | 55 ++++++++++++++----- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/command/WaitContainerResultCallback.java b/src/main/java/com/github/dockerjava/core/command/WaitContainerResultCallback.java index feb7916e7..df415d555 100644 --- a/src/main/java/com/github/dockerjava/core/command/WaitContainerResultCallback.java +++ b/src/main/java/com/github/dockerjava/core/command/WaitContainerResultCallback.java @@ -56,7 +56,9 @@ public Integer awaitStatusCode() { */ public Integer awaitStatusCode(long timeout, TimeUnit timeUnit) { try { - awaitCompletion(timeout, timeUnit); + if (!awaitCompletion(timeout, timeUnit)) { + throw new DockerClientException("Awaiting status code timeout."); + } } catch (InterruptedException e) { throw new DockerClientException("Awaiting status code interrupted: ", e); } diff --git a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java index 8de80573c..0e69d00f0 100644 --- a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java @@ -1,13 +1,12 @@ package com.github.dockerjava.core.command; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; - -import java.lang.reflect.Method; - +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.exception.DockerClientException; +import com.github.dockerjava.api.exception.DockerException; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.WaitResponse; +import com.github.dockerjava.client.AbstractDockerClientTest; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -15,12 +14,11 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.github.dockerjava.api.exception.DockerException; -import com.github.dockerjava.api.exception.NotFoundException; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerjava.api.model.WaitResponse; -import com.github.dockerjava.client.AbstractDockerClientTest; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; @Test(groups = "integration") public class WaitContainerCmdImplTest extends AbstractDockerClientTest { @@ -74,7 +72,7 @@ public void testWaitNonExistingContainer() throws DockerException { WaitContainerResultCallback callback = new WaitContainerResultCallback() { public void onNext(WaitResponse waitResponse) { fail("expected NotFoundException"); - }; + } }; dockerClient.waitContainerCmd("non-existing").exec(callback).awaitStatusCode(); @@ -104,4 +102,31 @@ public void testWaitContainerAbort() throws Exception { assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); } + + @Test + public void testWaitContainerTimeout() throws Exception { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + WaitContainerResultCallback callback = dockerClient.waitContainerCmd(container.getId()).exec( + new WaitContainerResultCallback()); + try { + callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + fail("Should throw exception on timeout."); + } catch(DockerClientException e){ + LOG.info(e.getMessage()); + } + + dockerClient.killContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + LOG.info("Container Inspect: {}", inspectContainerResponse.toString()); + + assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); + } } From a8466ff9fa46d653cafbbc4d4b3ed00fbd683f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Warcha=C5=82?= Date: Fri, 6 May 2016 12:56:21 +0200 Subject: [PATCH 019/780] Add test for WaitContainerResultCallback timeout in Netty implementation --- .../netty/exec/WaitContainerCmdExecTest.java | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java index 527d5f995..20919a934 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java @@ -1,27 +1,25 @@ package com.github.dockerjava.netty.exec; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; - -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.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.WaitResponse; import com.github.dockerjava.core.command.WaitContainerResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +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 java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; @Test(groups = "integration") public class WaitContainerCmdExecTest extends AbstractNettyDockerClientTest { @@ -75,7 +73,7 @@ public void testWaitNonExistingContainer() throws DockerException { WaitContainerResultCallback callback = new WaitContainerResultCallback() { public void onNext(WaitResponse waitResponse) { fail("expected NotFoundException"); - }; + } }; dockerClient.waitContainerCmd("non-existing").exec(callback).awaitStatusCode(); @@ -107,4 +105,31 @@ public void testWaitContainerAbort() throws Exception { assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); } + + @Test + public void testWaitContainerTimeout() throws Exception { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + WaitContainerResultCallback callback = dockerClient.waitContainerCmd(container.getId()).exec( + new WaitContainerResultCallback()); + try { + callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + fail("Should throw exception on timeout."); + } catch(DockerClientException e){ + LOG.info(e.getMessage()); + } + + dockerClient.killContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + LOG.info("Container Inspect: {}", inspectContainerResponse.toString()); + + assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); + } } From f24fc2613d4b9be8ef3619d9cf3827f6e5f780e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Warcha=C5=82?= Date: Fri, 6 May 2016 13:12:57 +0200 Subject: [PATCH 020/780] Polish tests for WaitContainerCmd Reduce containers sleep duration to 10 seconds. Remove unnecessary calls to KillContainerCmd. --- .../core/command/WaitContainerCmdImplTest.java | 9 +-------- .../dockerjava/netty/exec/WaitContainerCmdExecTest.java | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java index 0e69d00f0..b92dcc657 100644 --- a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java @@ -106,7 +106,7 @@ public void testWaitContainerAbort() throws Exception { @Test public void testWaitContainerTimeout() throws Exception { - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "10").exec(); LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); @@ -121,12 +121,5 @@ public void testWaitContainerTimeout() throws Exception { } catch(DockerClientException e){ LOG.info(e.getMessage()); } - - dockerClient.killContainerCmd(container.getId()).exec(); - - InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - LOG.info("Container Inspect: {}", inspectContainerResponse.toString()); - - assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java index 20919a934..42898974c 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/WaitContainerCmdExecTest.java @@ -109,7 +109,7 @@ public void testWaitContainerAbort() throws Exception { @Test public void testWaitContainerTimeout() throws Exception { - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "10").exec(); LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); @@ -124,12 +124,5 @@ public void testWaitContainerTimeout() throws Exception { } catch(DockerClientException e){ LOG.info(e.getMessage()); } - - dockerClient.killContainerCmd(container.getId()).exec(); - - InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - LOG.info("Container Inspect: {}", inspectContainerResponse.toString()); - - assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); } } From 4fc98a0d406e000915db5e55ca3d1a6f82e8e1ff Mon Sep 17 00:00:00 2001 From: AE Date: Fri, 6 May 2016 16:39:53 +0200 Subject: [PATCH 021/780] Docker inspect command now shows sizes if request. --- .../dockerjava/api/command/InspectContainerCmd.java | 4 ++++ .../api/command/InspectContainerResponse.java | 7 +++++++ .../core/command/InspectContainerCmdImpl.java | 12 ++++++++++++ .../dockerjava/jaxrs/InspectContainerCmdExec.java | 5 +++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java index cb782c64d..c0f666fa3 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java @@ -12,6 +12,10 @@ public interface InspectContainerCmd extends SyncDockerCmd Date: Sun, 1 May 2016 23:44:39 +0200 Subject: [PATCH 022/780] Work on port ranges - change all to strings --- .../dockerjava/api/model/ExposedPort.java | 6 +- .../github/dockerjava/api/model/Ports.java | 76 +++++++++---------- .../command/InspectContainerResponseTest.java | 4 +- .../dockerjava/api/model/BindingTest.java | 7 +- .../dockerjava/api/model/PortBindingTest.java | 12 +-- .../api/model/Ports_SerializingTest.java | 17 ++--- .../api/model/Ports_addBindingsTest.java | 13 ++-- .../core/TestDockerCmdExecFactory.java | 66 ++++++++++++++-- .../core/command/BuildImageCmdImplTest.java | 2 +- .../command/CreateContainerCmdImplTest.java | 12 +-- .../command/RenameContainerCmdImplTest.java | 9 ++- .../command/StartContainerCmdImplTest.java | 71 +++++++++-------- .../core/util/FiltersBuilderTest.java | 5 +- .../netty/exec/BuildImageCmdExecTest.java | 2 +- .../exec/CreateContainerCmdExecTest.java | 67 ++++++++-------- .../exec/RenameContainerCmdExecTest.java | 9 ++- .../netty/exec/StartContainerCmdExecTest.java | 71 +++++++++-------- 17 files changed, 253 insertions(+), 196 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java index 25829b8aa..4e30c8df0 100644 --- a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java +++ b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java @@ -65,7 +65,7 @@ public ExposedPort(int port) { * @param scheme * the {@link #getScheme() scheme}, tcp or udp * @param port - * the {@link #getPort() port number} + * the {@link #getPort() port number or port range} * @deprecated use {@link #ExposedPort(int, InternetProtocol)} */ @Deprecated @@ -124,9 +124,9 @@ public static ExposedPort parse(String serialized) throws IllegalArgumentExcepti String[] parts = serialized.split("/"); switch (parts.length) { case 1: - return new ExposedPort(Integer.valueOf(parts[0])); + return new ExposedPort(Integer.parseInt(parts[0])); case 2: - return new ExposedPort(Integer.valueOf(parts[0]), InternetProtocol.parse(parts[1])); + return new ExposedPort(Integer.parseInt(parts[0]), InternetProtocol.parse(parts[1])); default: throw new IllegalArgumentException(); } diff --git a/src/main/java/com/github/dockerjava/api/model/Ports.java b/src/main/java/com/github/dockerjava/api/model/Ports.java index e0250bba1..17b2ad432 100644 --- a/src/main/java/com/github/dockerjava/api/model/Ports.java +++ b/src/main/java/com/github/dockerjava/api/model/Ports.java @@ -1,16 +1,5 @@ package com.github.dockerjava.api.model; -import static org.apache.commons.lang.StringUtils.isEmpty; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.builder.EqualsBuilder; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -23,6 +12,16 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.NullNode; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.builder.EqualsBuilder; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import static org.apache.commons.lang.StringUtils.isEmpty; /** * A container for port bindings, made available as a {@link Map} via its {@link #getBindings()} method. @@ -111,15 +110,15 @@ public Map getBindings() { /** * Creates a {@link Binding} for the given IP address and port number. */ - public static Binding binding(String hostIp, Integer hostPort) { + public static Binding binding(String hostIp, String hostPort) { return new Binding(hostIp, hostPort); } /** * Creates a {@link Binding} for the given port number, leaving the IP address undefined. */ - public static Binding binding(Integer hostPort) { - return new Binding(hostPort); + public static Binding binding(String hostPort) { + return new Binding(null, hostPort); } /** @@ -132,38 +131,38 @@ public static Binding binding(Integer hostPort) { */ public static class Binding { - private final String hostIp; - - private final Integer hostPort; - /** - * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}. + * Creates a {@link Binding} for the given {@link #getHostPort() port number or range}, leaving the {@link #getHostIp() IP address} + * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ - public Binding(String hostIp, Integer hostPort) { - this.hostIp = isEmpty(hostIp) ? null : hostIp; - this.hostPort = hostPort; + public static Binding forPort(String port) { + return new Binding(null, port); } /** - * Creates a {@link Binding} for the given {@link #getHostPort() port number}, leaving the {@link #getHostIp() IP address} + * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number} * undefined. - * - * @see Ports#bind(ExposedPort, Binding) - * @see ExposedPort */ - public Binding(Integer hostPort) { - this(null, hostPort); + public static Binding forIp(String hostIp) { + return new Binding(hostIp, null); } + private final String hostIp; + + private final String hostPort; + /** - * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number} - * undefined. + * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}. + * + * @see Ports#bind(ExposedPort, Binding) + * @see ExposedPort */ - public Binding(String hostIp) { - this(hostIp, null); + public Binding(String hostIp, String hostPort) { + this.hostIp = isEmpty(hostIp) ? null : hostIp; + this.hostPort = hostPort; } /** @@ -184,7 +183,7 @@ public String getHostIp() { /** * @return the port number on the Docker host. May be null, in which case Docker will dynamically assign a port. */ - public Integer getHostPort() { + public String getHostPort() { return hostPort; } @@ -208,10 +207,10 @@ public static Binding parse(String serialized) throws IllegalArgumentException { String[] parts = serialized.split(":"); switch (parts.length) { case 2: { - return new Binding(parts[0], Integer.valueOf(parts[1])); + return new Binding(parts[0], parts[1]); } case 1: { - return parts[0].contains(".") ? new Binding(parts[0]) : new Binding(Integer.valueOf(parts[0])); + return parts[0].contains(".") ? Binding.forIp(parts[0]) : Binding.forPort(parts[0]); } default: { throw new IllegalArgumentException(); @@ -231,7 +230,7 @@ public static Binding parse(String serialized) throws IllegalArgumentException { @Override public String toString() { if (isEmpty(hostIp)) { - return Integer.toString(hostPort); + return hostPort; } else if (hostPort == null) { return hostIp; } else { @@ -270,7 +269,7 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali JsonNode bindingNode = bindingsArray.get(i); if (!bindingNode.equals(NullNode.getInstance())) { String hostIp = bindingNode.get("HostIp").textValue(); - int hostPort = bindingNode.get("HostPort").asInt(); + String hostPort = bindingNode.get("HostPort").textValue(); out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort)); } } @@ -294,8 +293,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvi for (Binding binding : entry.getValue()) { jsonGen.writeStartObject(); jsonGen.writeStringField("HostIp", binding.getHostIp() == null ? "" : binding.getHostIp()); - jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort() - .toString()); + jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort()); jsonGen.writeEndObject(); } jsonGen.writeEndArray(); diff --git a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java index c9d40b65f..f64cf4ead 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java @@ -25,7 +25,9 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.IsNot.not; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; /** * Tests for {@link InspectContainerResponse}. diff --git a/src/test/java/com/github/dockerjava/api/model/BindingTest.java b/src/test/java/com/github/dockerjava/api/model/BindingTest.java index 23e793cf8..290e66b82 100644 --- a/src/test/java/com/github/dockerjava/api/model/BindingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/BindingTest.java @@ -10,12 +10,12 @@ public class BindingTest { @Test public void parseIpAndPort() { - assertEquals(Binding.parse("127.0.0.1:80"), Ports.binding("127.0.0.1", 80)); + assertEquals(Binding.parse("127.0.0.1:80"), Ports.binding("127.0.0.1", "80")); } @Test public void parsePortOnly() { - assertEquals(Binding.parse("80"), Ports.binding(null, 80)); + assertEquals(Binding.parse("80"), Ports.binding(null, "80")); } @Test @@ -28,7 +28,8 @@ public void parseEmptyString() { assertEquals(Binding.parse(""), Ports.binding(null, null)); } - @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing Binding 'nonsense'") + // Strings can be used since it can be a range. Let the docker daemon do the validation. + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing Binding 'nonsense'", enabled = false) public void parseInvalidInput() { Binding.parse("nonsense"); } diff --git a/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java b/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java index e5f5f4c1b..296148177 100644 --- a/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java @@ -13,22 +13,22 @@ public class PortBindingTest { @Test public void fullDefinition() { assertEquals(PortBinding.parse("127.0.0.1:80:8080/tcp"), - new PortBinding(new Binding("127.0.0.1", 80), TCP_8080)); + new PortBinding(new Binding("127.0.0.1", "80"), TCP_8080)); } @Test public void noProtocol() { - assertEquals(PortBinding.parse("127.0.0.1:80:8080"), new PortBinding(new Binding("127.0.0.1", 80), TCP_8080)); + assertEquals(PortBinding.parse("127.0.0.1:80:8080"), new PortBinding(new Binding("127.0.0.1", "80"), TCP_8080)); } @Test public void noHostIp() { - assertEquals(PortBinding.parse("80:8080/tcp"), new PortBinding(new Binding(80), TCP_8080)); + assertEquals(PortBinding.parse("80:8080/tcp"), new PortBinding(Binding.forPort("80"), TCP_8080)); } @Test public void portsOnly() { - assertEquals(PortBinding.parse("80:8080"), new PortBinding(new Binding(80), TCP_8080)); + assertEquals(PortBinding.parse("80:8080"), new PortBinding(Binding.forPort("80"), TCP_8080)); } @Test @@ -38,10 +38,10 @@ public void exposedPortOnly() { @Test public void dynamicHostPort() { - assertEquals(PortBinding.parse("127.0.0.1::8080"), new PortBinding(new Binding("127.0.0.1"), TCP_8080)); + assertEquals(PortBinding.parse("127.0.0.1::8080"), new PortBinding(Binding.forIp("127.0.0.1"), TCP_8080)); } - @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing PortBinding 'nonsense'") + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing PortBinding 'nonsense'", enabled = false) public void parseInvalidInput() { PortBinding.parse("nonsense"); } diff --git a/src/test/java/com/github/dockerjava/api/model/Ports_SerializingTest.java b/src/test/java/com/github/dockerjava/api/model/Ports_SerializingTest.java index 8c8d2014f..fb89561e5 100644 --- a/src/test/java/com/github/dockerjava/api/model/Ports_SerializingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/Ports_SerializingTest.java @@ -1,13 +1,12 @@ package com.github.dockerjava.api.model; -import static org.testng.Assert.assertEquals; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Ports.Binding; +import org.testng.annotations.Test; import java.util.Map; -import org.testng.annotations.Test; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.dockerjava.api.model.Ports.Binding; +import static org.testng.Assert.assertEquals; public class Ports_SerializingTest { private final ObjectMapper objectMapper = new ObjectMapper(); @@ -24,15 +23,15 @@ public void deserializingPortWithMultipleBindings() throws Exception { Binding[] bindings = map.get(ExposedPort.tcp(80)); assertEquals(bindings.length, 2); - assertEquals(bindings[0], new Binding("10.0.0.1", 80)); - assertEquals(bindings[1], new Binding("10.0.0.2", 80)); + assertEquals(bindings[0], new Binding("10.0.0.1", "80")); + assertEquals(bindings[1], new Binding("10.0.0.2", "80")); } @Test public void serializingPortWithMultipleBindings() throws Exception { Ports ports = new Ports(); - ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.1", 80)); - ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.2", 80)); + ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.1", "80")); + ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.2", "80")); assertEquals(objectMapper.writeValueAsString(ports), jsonWithDoubleBindingForOnePort); } diff --git a/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java b/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java index a5a8697f5..401ee4b44 100644 --- a/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java +++ b/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java @@ -1,13 +1,12 @@ package com.github.dockerjava.api.model; -import static org.testng.Assert.assertEquals; - -import java.util.Map; - +import com.github.dockerjava.api.model.Ports.Binding; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import com.github.dockerjava.api.model.Ports.Binding; +import java.util.Map; + +import static org.testng.Assert.assertEquals; /** * As there may be several {@link Binding}s per {@link ExposedPort}, it makes a difference if you add {@link PortBinding}s for the same or @@ -18,9 +17,9 @@ public class Ports_addBindingsTest { private static final ExposedPort TCP_90 = ExposedPort.tcp(90); - private static final Binding BINDING_8080 = Ports.binding(8080); + private static final Binding BINDING_8080 = Ports.binding("8080"); - private static final Binding BINDING_9090 = Ports.binding(9090); + private static final Binding BINDING_9090 = Ports.binding("9090"); private Ports ports; diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index ba05ab4e3..aee8a60a8 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -1,17 +1,69 @@ package com.github.dockerjava.core; +import com.github.dockerjava.api.async.ResultCallback; +import com.github.dockerjava.api.command.AttachContainerCmd; +import com.github.dockerjava.api.command.AuthCmd.Exec; +import com.github.dockerjava.api.command.BuildImageCmd; +import com.github.dockerjava.api.command.CommitCmd; +import com.github.dockerjava.api.command.ConnectToNetworkCmd; +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; +import com.github.dockerjava.api.command.CreateImageResponse; +import com.github.dockerjava.api.command.CreateNetworkCmd; +import com.github.dockerjava.api.command.CreateNetworkResponse; +import com.github.dockerjava.api.command.CreateVolumeCmd; +import com.github.dockerjava.api.command.CreateVolumeResponse; +import com.github.dockerjava.api.command.DisconnectFromNetworkCmd; +import com.github.dockerjava.api.command.DockerCmdExecFactory; +import com.github.dockerjava.api.command.EventsCmd; +import com.github.dockerjava.api.command.ExecCreateCmd; +import com.github.dockerjava.api.command.ExecStartCmd; +import com.github.dockerjava.api.command.InfoCmd; +import com.github.dockerjava.api.command.InspectContainerCmd; +import com.github.dockerjava.api.command.InspectExecCmd; +import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.InspectNetworkCmd; +import com.github.dockerjava.api.command.InspectVolumeCmd; +import com.github.dockerjava.api.command.KillContainerCmd; +import com.github.dockerjava.api.command.ListContainersCmd; +import com.github.dockerjava.api.command.ListImagesCmd; +import com.github.dockerjava.api.command.ListNetworksCmd; +import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LogContainerCmd; +import com.github.dockerjava.api.command.PauseContainerCmd; +import com.github.dockerjava.api.command.PingCmd; +import com.github.dockerjava.api.command.PullImageCmd; +import com.github.dockerjava.api.command.PushImageCmd; +import com.github.dockerjava.api.command.RemoveContainerCmd; +import com.github.dockerjava.api.command.RemoveImageCmd; +import com.github.dockerjava.api.command.RemoveNetworkCmd; +import com.github.dockerjava.api.command.RemoveVolumeCmd; +import com.github.dockerjava.api.command.RenameContainerCmd; +import com.github.dockerjava.api.command.RestartContainerCmd; +import com.github.dockerjava.api.command.SaveImageCmd; +import com.github.dockerjava.api.command.SearchImagesCmd; +import com.github.dockerjava.api.command.StartContainerCmd; +import com.github.dockerjava.api.command.StatsCmd; +import com.github.dockerjava.api.command.StopContainerCmd; +import com.github.dockerjava.api.command.TagImageCmd; +import com.github.dockerjava.api.command.TopContainerCmd; +import com.github.dockerjava.api.command.UnpauseContainerCmd; +import com.github.dockerjava.api.command.UpdateContainerCmd; +import com.github.dockerjava.api.command.VersionCmd; +import com.github.dockerjava.api.command.WaitContainerCmd; +import com.github.dockerjava.api.model.BuildResponseItem; + +import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; -import javax.net.ssl.SSLContext; - -import com.github.dockerjava.api.async.ResultCallback; -import com.github.dockerjava.api.command.*; -import com.github.dockerjava.api.command.AuthCmd.Exec; -import com.github.dockerjava.api.model.BuildResponseItem; - /** * Special {@link DockerCmdExecFactory} implementation that collects container and image creations while test execution for the purpose of * automatically cleanup. diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index 99eefb4de..9ae4e3e98 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -263,7 +263,7 @@ public void testBuildFromPrivateRegistry() throws Exception { CreateContainerResponse testregistry = dockerClient .createContainerCmd("testregistry:2") .withName("registry") - .withPortBindings(new PortBinding(new Ports.Binding(5000), ExposedPort.tcp(5000))) + .withPortBindings(new PortBinding(Ports.Binding.forPort("5000"), ExposedPort.tcp(5000))) .withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key") diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index f2fd32b6a..05d2b6d0d 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -361,9 +361,9 @@ public void createContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11023)); - portBindings.bind(tcp23, Ports.binding(11024)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11023")); + portBindings.bind(tcp23, Ports.binding("11024")); CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE).withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -377,13 +377,13 @@ public void createContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding(11022)))); + is(equalTo(Ports.binding("11022")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding(11023)))); + is(equalTo(Ports.binding("11023")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding(11024)))); + is(equalTo(Ports.binding("11024")))); } diff --git a/src/test/java/com/github/dockerjava/core/command/RenameContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RenameContainerCmdImplTest.java index 9f503a87b..582ab2556 100644 --- a/src/test/java/com/github/dockerjava/core/command/RenameContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RenameContainerCmdImplTest.java @@ -6,12 +6,17 @@ import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.client.AbstractDockerClientTest; import org.testng.ITestResult; -import org.testng.annotations.*; +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 java.lang.reflect.Method; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; @Test(groups = "integration") public class RenameContainerCmdImplTest extends AbstractDockerClientTest { diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java index a2f1e51d8..4437eaaa7 100644 --- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java @@ -1,31 +1,5 @@ package com.github.dockerjava.core.command; -import static com.github.dockerjava.api.model.AccessMode.ro; -import static com.github.dockerjava.api.model.Capability.MKNOD; -import static com.github.dockerjava.api.model.Capability.NET_ADMIN; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.startsWith; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -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.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; @@ -42,6 +16,31 @@ import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; import com.github.dockerjava.client.AbstractDockerClientTest; +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 java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static com.github.dockerjava.api.model.AccessMode.ro; +import static com.github.dockerjava.api.model.Capability.MKNOD; +import static com.github.dockerjava.api.model.Capability.NET_ADMIN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; @Test(groups = "integration") public class StartContainerCmdImplTest extends AbstractDockerClientTest { @@ -189,9 +188,9 @@ public void startContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11023)); - portBindings.bind(tcp23, Ports.binding(11024)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11023")); + portBindings.bind(tcp23, Ports.binding("11024")); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -209,13 +208,13 @@ public void startContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding(11022)))); + is(equalTo(Ports.binding("11022")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding(11023)))); + is(equalTo(Ports.binding("11023")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding(11024)))); + is(equalTo(Ports.binding("11024")))); } @@ -243,10 +242,10 @@ public void startContainerWithRandomPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPort(), - is(not(equalTo(tcp22.getPort())))); + is(not(equalTo(String.valueOf(tcp22.getPort()))))); assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPort(), - is(not(equalTo(tcp23.getPort())))); + is(not(equalTo(String.valueOf(tcp23.getPort()))))); } @@ -257,8 +256,8 @@ public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11022)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11022")); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); diff --git a/src/test/java/com/github/dockerjava/core/util/FiltersBuilderTest.java b/src/test/java/com/github/dockerjava/core/util/FiltersBuilderTest.java index 25027ae76..e70a3b057 100644 --- a/src/test/java/com/github/dockerjava/core/util/FiltersBuilderTest.java +++ b/src/test/java/com/github/dockerjava/core/util/FiltersBuilderTest.java @@ -1,13 +1,12 @@ package com.github.dockerjava.core.util; -import com.github.dockerjava.core.util.FiltersBuilder; import com.google.common.collect.Maps; - import org.testng.annotations.Test; import java.util.Map; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; /** * @author Vincent Latombe diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index 1299cf6ae..2f9ac934c 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -255,7 +255,7 @@ public void testBuildFromPrivateRegistry() throws Exception { CreateContainerResponse testregistry = dockerClient .createContainerCmd("testregistry:2") .withName("registry") - .withPortBindings(new PortBinding(new Ports.Binding(5000), ExposedPort.tcp(5000))) + .withPortBindings(new PortBinding(Ports.Binding.forPort("5000"), ExposedPort.tcp(5000))) .withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key") diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index 02c5cc54e..0daf4fb46 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -1,33 +1,5 @@ package com.github.dockerjava.netty.exec; -import static com.github.dockerjava.api.model.Capability.MKNOD; -import static com.github.dockerjava.api.model.Capability.NET_ADMIN; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItemInArray; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.startsWith; - -import java.lang.reflect.Method; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -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.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.exception.ConflictException; @@ -43,6 +15,33 @@ import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +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 java.lang.reflect.Method; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.github.dockerjava.api.model.Capability.MKNOD; +import static com.github.dockerjava.api.model.Capability.NET_ADMIN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItemInArray; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; @Test(groups = "integration") public class CreateContainerCmdExecTest extends AbstractNettyDockerClientTest { @@ -352,9 +351,9 @@ public void createContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11023)); - portBindings.bind(tcp23, Ports.binding(11024)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11023")); + portBindings.bind(tcp23, Ports.binding("11024")); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -368,13 +367,13 @@ public void createContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding(11022)))); + is(equalTo(Ports.binding("11022")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding(11023)))); + is(equalTo(Ports.binding("11023")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding(11024)))); + is(equalTo(Ports.binding("11024")))); } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RenameContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RenameContainerCmdExecTest.java index c176bc1d6..100a7d772 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RenameContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RenameContainerCmdExecTest.java @@ -6,12 +6,17 @@ import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; import org.testng.ITestResult; -import org.testng.annotations.*; +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 java.lang.reflect.Method; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; @Test(groups = "integration") public class RenameContainerCmdExecTest extends AbstractNettyDockerClientTest { diff --git a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java index 6c70c1f07..844274887 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java @@ -1,31 +1,5 @@ package com.github.dockerjava.netty.exec; -import static com.github.dockerjava.api.model.AccessMode.ro; -import static com.github.dockerjava.api.model.Capability.MKNOD; -import static com.github.dockerjava.api.model.Capability.NET_ADMIN; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.startsWith; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -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.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; @@ -43,6 +17,31 @@ import com.github.dockerjava.api.model.VolumesFrom; import com.github.dockerjava.core.command.WaitContainerResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +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 java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static com.github.dockerjava.api.model.AccessMode.ro; +import static com.github.dockerjava.api.model.Capability.MKNOD; +import static com.github.dockerjava.api.model.Capability.NET_ADMIN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; @Test(groups = "integration") public class StartContainerCmdExecTest extends AbstractNettyDockerClientTest { @@ -192,9 +191,9 @@ public void startContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11023)); - portBindings.bind(tcp23, Ports.binding(11024)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11023")); + portBindings.bind(tcp23, Ports.binding("11024")); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -212,13 +211,13 @@ public void startContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding(11022)))); + is(equalTo(Ports.binding("11022")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding(11023)))); + is(equalTo(Ports.binding("11023")))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding(11024)))); + is(equalTo(Ports.binding("11024")))); } @@ -246,10 +245,10 @@ public void startContainerWithRandomPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPort(), - is(not(equalTo(tcp22.getPort())))); + is(not(equalTo(String.valueOf(tcp22.getPort()))))); assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPort(), - is(not(equalTo(tcp23.getPort())))); + is(not(equalTo(String.valueOf(tcp23.getPort()))))); } @@ -260,8 +259,8 @@ public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(11022)); - portBindings.bind(tcp23, Ports.binding(11022)); + portBindings.bind(tcp22, Ports.binding("11022")); + portBindings.bind(tcp23, Ports.binding("11022")); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); From 9641b01d0559aa23299bdf229c07a29e065d4398 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 8 May 2016 19:07:39 +0300 Subject: [PATCH 023/780] Fixes copyArchiveToContainerCmdImpl fail when hostResource has an empty dir which gets added as last entry to tar CopyArchiveToContainerCmdImpl FAILS with com.github.dockerjava.api.exception.BadRequestException: Unable to perform tar on host resource /path/to/resource, if the resourceHost is a dir that containes an empty dir which will be added as the last entry to the generated .tar file. --- src/main/java/com/github/dockerjava/core/util/TarDirWalker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java index 7c3a9ca29..af263ee9c 100644 --- a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java +++ b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java @@ -26,6 +26,7 @@ public TarDirWalker(Path basePath, TarArchiveOutputStream tarArchiveOutputStream public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (!dir.equals(basePath)) { tarArchiveOutputStream.putArchiveEntry(new TarArchiveEntry(FilePathUtil.relativize(basePath, dir))); + tarArchiveOutputStream.closeArchiveEntry(); } return FileVisitResult.CONTINUE; } From 2edfcb0e0aa08feade900dcd3250a991d9458a85 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Sun, 8 May 2016 22:24:06 +0200 Subject: [PATCH 024/780] Polish binding for port ranges --- .../github/dockerjava/api/model/Ports.java | 103 ++++++++++-------- .../dockerjava/api/model/BindingTest.java | 8 +- .../dockerjava/api/model/PortBindingTest.java | 12 +- .../api/model/Ports_addBindingsTest.java | 4 +- .../core/command/BuildImageCmdImplTest.java | 2 +- .../command/CreateContainerCmdImplTest.java | 14 ++- .../command/StartContainerCmdImplTest.java | 26 +++-- .../netty/exec/BuildImageCmdExecTest.java | 3 +- .../exec/CreateContainerCmdExecTest.java | 14 ++- .../netty/exec/StartContainerCmdExecTest.java | 26 +++-- 10 files changed, 119 insertions(+), 93 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/Ports.java b/src/main/java/com/github/dockerjava/api/model/Ports.java index 17b2ad432..904a31c4e 100644 --- a/src/main/java/com/github/dockerjava/api/model/Ports.java +++ b/src/main/java/com/github/dockerjava/api/model/Ports.java @@ -107,24 +107,10 @@ public Map getBindings() { // return bindings.toArray(new PortBinding[bindings.size()]); // } - /** - * Creates a {@link Binding} for the given IP address and port number. - */ - public static Binding binding(String hostIp, String hostPort) { - return new Binding(hostIp, hostPort); - } - - /** - * Creates a {@link Binding} for the given port number, leaving the IP address undefined. - */ - public static Binding binding(String hostPort) { - return new Binding(null, hostPort); - } - /** * A {@link Binding} represents a socket on the Docker host that is used in a {@link PortBinding}. It is characterized by an - * {@link #getHostIp() IP address} and a {@link #getHostPort() port number}. Both properties may be null in order to let - * Docker assign them dynamically/using defaults. + * {@link #getHostIp() IP address} and a {@link #getHostPortSpec() port spec}. Both properties may be null in order to + * let Docker assign them dynamically/using defaults. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort @@ -132,44 +118,74 @@ public static Binding binding(String hostPort) { public static class Binding { /** - * Creates a {@link Binding} for the given {@link #getHostPort() port number or range}, leaving the {@link #getHostIp() IP address} + * Creates a {@link Binding} for the given {@link #getHostPortSpec() port spec}, leaving the {@link #getHostIp() IP address} * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ - public static Binding forPort(String port) { - return new Binding(null, port); + public static Binding bindPortSpec(String portSpec) { + return new Binding(null, portSpec); } /** - * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number} + * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPortSpec() port spec} * undefined. */ - public static Binding forIp(String hostIp) { + public static Binding bindIp(String hostIp) { return new Binding(hostIp, null); } + /** + * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port number. + */ + public static Binding bindIpAndPort(String hostIp, int port) { + return new Binding(hostIp, "" + port); + } + + /** + * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port range. + */ + public static Binding bindIpAndPortRange(String hostIp, int lowPort, int highPort) { + return new Binding(hostIp, lowPort + "-" + highPort); + } + + /** + * Creates a {@link Binding} for the given port range, leaving the {@link #getHostIp() IP address} + * undefined. + */ + public static Binding bindPortRange(int lowPort, int highPort) { + return bindIpAndPortRange(null, lowPort, highPort); + } + + /** + * Creates a {@link Binding} for the given port leaving the {@link #getHostIp() IP address} + * undefined. + */ + public static Binding bindPort(int port) { + return bindIpAndPort(null, port); + } + + /** + * Creates an empty {@link Binding}. + */ + public static Binding empty() { + return new Binding(null, null); + } + private final String hostIp; - private final String hostPort; + private final String hostPortSpec; /** - * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}. + * Creates a {@link Binding} for the given {@link #getHostIp() host IP address} and {@link #getHostPortSpec() host port spec}. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ - public Binding(String hostIp, String hostPort) { + public Binding(String hostIp, String hostPortSpec) { this.hostIp = isEmpty(hostIp) ? null : hostIp; - this.hostPort = hostPort; - } - - /** - * Creates a {@link Binding} with both {@link #getHostIp() IP address} and {@link #getHostPort() port number} undefined. - */ - public Binding() { - this(null, null); + this.hostPortSpec = hostPortSpec; } /** @@ -181,16 +197,17 @@ public String getHostIp() { } /** - * @return the port number on the Docker host. May be null, in which case Docker will dynamically assign a port. + * @return the port spec for the binding on the Docker host. May reference a single port ("1234"), a port range ("1234-2345") or + * null, in which case Docker will dynamically assign a port. */ - public String getHostPort() { - return hostPort; + public String getHostPortSpec() { + return hostPortSpec; } /** * Parses a textual host and port specification (as used by the Docker CLI) to a {@link Binding}. *

- * Legal syntax: IP|IP:port|port + * Legal syntax: IP|IP:portSpec|portSpec where portSpec is either a single port or a port range * * @param serialized * serialized the specification, e.g. 127.0.0.1:80 @@ -201,7 +218,7 @@ public String getHostPort() { public static Binding parse(String serialized) throws IllegalArgumentException { try { if (serialized.isEmpty()) { - return new Binding(); + return Binding.empty(); } String[] parts = serialized.split(":"); @@ -210,7 +227,7 @@ public static Binding parse(String serialized) throws IllegalArgumentException { return new Binding(parts[0], parts[1]); } case 1: { - return parts[0].contains(".") ? Binding.forIp(parts[0]) : Binding.forPort(parts[0]); + return parts[0].contains(".") ? Binding.bindIp(parts[0]) : Binding.bindPortSpec(parts[0]); } default: { throw new IllegalArgumentException(); @@ -230,11 +247,11 @@ public static Binding parse(String serialized) throws IllegalArgumentException { @Override public String toString() { if (isEmpty(hostIp)) { - return hostPort; - } else if (hostPort == null) { + return hostPortSpec; + } else if (hostPortSpec == null) { return hostIp; } else { - return hostIp + ":" + hostPort; + return hostIp + ":" + hostPortSpec; } } @@ -242,7 +259,7 @@ public String toString() { public boolean equals(Object obj) { if (obj instanceof Binding) { Binding other = (Binding) obj; - return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPort, other.getHostPort()) + return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPortSpec, other.getHostPortSpec()) .isEquals(); } else { return super.equals(obj); @@ -293,7 +310,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvi for (Binding binding : entry.getValue()) { jsonGen.writeStartObject(); jsonGen.writeStringField("HostIp", binding.getHostIp() == null ? "" : binding.getHostIp()); - jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort()); + jsonGen.writeStringField("HostPort", binding.getHostPortSpec() == null ? "" : binding.getHostPortSpec()); jsonGen.writeEndObject(); } jsonGen.writeEndArray(); diff --git a/src/test/java/com/github/dockerjava/api/model/BindingTest.java b/src/test/java/com/github/dockerjava/api/model/BindingTest.java index 290e66b82..3b5ea2f6a 100644 --- a/src/test/java/com/github/dockerjava/api/model/BindingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/BindingTest.java @@ -10,22 +10,22 @@ public class BindingTest { @Test public void parseIpAndPort() { - assertEquals(Binding.parse("127.0.0.1:80"), Ports.binding("127.0.0.1", "80")); + assertEquals(Binding.parse("127.0.0.1:80"), Binding.bindIpAndPort("127.0.0.1", 80)); } @Test public void parsePortOnly() { - assertEquals(Binding.parse("80"), Ports.binding(null, "80")); + assertEquals(Binding.parse("80"), Binding.bindPort(80)); } @Test public void parseIPOnly() { - assertEquals(Binding.parse("127.0.0.1"), Ports.binding("127.0.0.1", null)); + assertEquals(Binding.parse("127.0.0.1"), Binding.bindIp("127.0.0.1")); } @Test public void parseEmptyString() { - assertEquals(Binding.parse(""), Ports.binding(null, null)); + assertEquals(Binding.parse(""), Binding.empty()); } // Strings can be used since it can be a range. Let the docker daemon do the validation. diff --git a/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java b/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java index 296148177..7603c3f1b 100644 --- a/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/PortBindingTest.java @@ -13,32 +13,32 @@ public class PortBindingTest { @Test public void fullDefinition() { assertEquals(PortBinding.parse("127.0.0.1:80:8080/tcp"), - new PortBinding(new Binding("127.0.0.1", "80"), TCP_8080)); + new PortBinding(Binding.bindIpAndPort("127.0.0.1", 80), TCP_8080)); } @Test public void noProtocol() { - assertEquals(PortBinding.parse("127.0.0.1:80:8080"), new PortBinding(new Binding("127.0.0.1", "80"), TCP_8080)); + assertEquals(PortBinding.parse("127.0.0.1:80:8080"), new PortBinding(Binding.bindIpAndPort("127.0.0.1", 80), TCP_8080)); } @Test public void noHostIp() { - assertEquals(PortBinding.parse("80:8080/tcp"), new PortBinding(Binding.forPort("80"), TCP_8080)); + assertEquals(PortBinding.parse("80:8080/tcp"), new PortBinding(Binding.bindPort(80), TCP_8080)); } @Test public void portsOnly() { - assertEquals(PortBinding.parse("80:8080"), new PortBinding(Binding.forPort("80"), TCP_8080)); + assertEquals(PortBinding.parse("80:8080"), new PortBinding(Binding.bindPort(80), TCP_8080)); } @Test public void exposedPortOnly() { - assertEquals(PortBinding.parse("8080"), new PortBinding(new Binding(), TCP_8080)); + assertEquals(PortBinding.parse("8080"), new PortBinding(Binding.empty(), TCP_8080)); } @Test public void dynamicHostPort() { - assertEquals(PortBinding.parse("127.0.0.1::8080"), new PortBinding(Binding.forIp("127.0.0.1"), TCP_8080)); + assertEquals(PortBinding.parse("127.0.0.1::8080"), new PortBinding(Binding.bindIp("127.0.0.1"), TCP_8080)); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing PortBinding 'nonsense'", enabled = false) diff --git a/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java b/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java index 401ee4b44..26e815f3b 100644 --- a/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java +++ b/src/test/java/com/github/dockerjava/api/model/Ports_addBindingsTest.java @@ -17,9 +17,9 @@ public class Ports_addBindingsTest { private static final ExposedPort TCP_90 = ExposedPort.tcp(90); - private static final Binding BINDING_8080 = Ports.binding("8080"); + private static final Binding BINDING_8080 = Binding.bindPort(8080); - private static final Binding BINDING_9090 = Ports.binding("9090"); + private static final Binding BINDING_9090 = Binding.bindPort(9090); private Ports ports; diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index 9ae4e3e98..8eea40eec 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -263,7 +263,7 @@ public void testBuildFromPrivateRegistry() throws Exception { CreateContainerResponse testregistry = dockerClient .createContainerCmd("testregistry:2") .withName("registry") - .withPortBindings(new PortBinding(Ports.Binding.forPort("5000"), ExposedPort.tcp(5000))) + .withPortBindings(new PortBinding(Ports.Binding.bindPortSpec("5000"), ExposedPort.tcp(5000))) .withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key") diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 05d2b6d0d..bc5a7d940 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -15,7 +15,9 @@ import com.github.dockerjava.api.model.Ulimit; import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; + import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -361,9 +363,9 @@ public void createContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11023")); - portBindings.bind(tcp23, Ports.binding("11024")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11023)); + portBindings.bind(tcp23, Binding.bindPort(11024)); CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE).withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -377,13 +379,13 @@ public void createContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding("11022")))); + is(equalTo(Binding.bindPort(11022)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding("11023")))); + is(equalTo(Binding.bindPort(11023)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding("11024")))); + is(equalTo(Binding.bindPort(11024)))); } diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java index 4437eaaa7..2b32e00c5 100644 --- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java @@ -15,7 +15,9 @@ import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; + import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -188,9 +190,9 @@ public void startContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11023")); - portBindings.bind(tcp23, Ports.binding("11024")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11023)); + portBindings.bind(tcp23, Binding.bindPort(11024)); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -208,13 +210,13 @@ public void startContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding("11022")))); + is(equalTo(Binding.bindPort(11022)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding("11023")))); + is(equalTo(Binding.bindPort(11023)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding("11024")))); + is(equalTo(Binding.bindPort(11024)))); } @@ -225,8 +227,8 @@ public void startContainerWithRandomPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(null)); - portBindings.bind(tcp23, Ports.binding(null)); + portBindings.bind(tcp22, Binding.empty()); + portBindings.bind(tcp23, Binding.empty()); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).withPublishAllPorts(true).exec(); @@ -241,10 +243,10 @@ public void startContainerWithRandomPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPort(), + assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPortSpec(), is(not(equalTo(String.valueOf(tcp22.getPort()))))); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPort(), + assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPortSpec(), is(not(equalTo(String.valueOf(tcp23.getPort()))))); } @@ -256,8 +258,8 @@ public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11022")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11022)); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index 2f9ac934c..92975f38f 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -34,6 +34,7 @@ import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.core.command.BuildImageResultCallback; import com.github.dockerjava.core.command.PushImageResultCallback; import com.github.dockerjava.core.command.WaitContainerResultCallback; @@ -255,7 +256,7 @@ public void testBuildFromPrivateRegistry() throws Exception { CreateContainerResponse testregistry = dockerClient .createContainerCmd("testregistry:2") .withName("registry") - .withPortBindings(new PortBinding(Ports.Binding.forPort("5000"), ExposedPort.tcp(5000))) + .withPortBindings(new PortBinding(Binding.bindPort(5000), ExposedPort.tcp(5000))) .withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key") diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index 0daf4fb46..4231a5f72 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -10,11 +10,13 @@ import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.LogConfig; import com.github.dockerjava.api.model.Ports; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.api.model.Ulimit; import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; + import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -351,9 +353,9 @@ public void createContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11023")); - portBindings.bind(tcp23, Ports.binding("11024")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11023)); + portBindings.bind(tcp23, Binding.bindPort(11024)); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -367,13 +369,13 @@ public void createContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding("11022")))); + is(equalTo(Binding.bindPort(11022)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding("11023")))); + is(equalTo(Binding.bindPort(11023)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding("11024")))); + is(equalTo(Binding.bindPort(11024)))); } diff --git a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java index 844274887..f4a36c2b1 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java @@ -15,8 +15,10 @@ import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.api.model.VolumesFrom; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.core.command.WaitContainerResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; + import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -191,9 +193,9 @@ public void startContainerWithPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11023")); - portBindings.bind(tcp23, Ports.binding("11024")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11023)); + portBindings.bind(tcp23, Binding.bindPort(11024)); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); @@ -211,13 +213,13 @@ public void startContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], - is(equalTo(Ports.binding("11022")))); + is(equalTo(Binding.bindPort(11022)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], - is(equalTo(Ports.binding("11023")))); + is(equalTo(Binding.bindPort(11023)))); assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], - is(equalTo(Ports.binding("11024")))); + is(equalTo(Binding.bindPort(11024)))); } @@ -228,8 +230,8 @@ public void startContainerWithRandomPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding(null)); - portBindings.bind(tcp23, Ports.binding(null)); + portBindings.bind(tcp22, Binding.empty()); + portBindings.bind(tcp23, Binding.empty()); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).withPublishAllPorts(true).exec(); @@ -244,10 +246,10 @@ public void startContainerWithRandomPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPort(), + assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp22)[0].getHostPortSpec(), is(not(equalTo(String.valueOf(tcp22.getPort()))))); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPort(), + assertThat(inspectContainerResponse.getNetworkSettings().getPorts().getBindings().get(tcp23)[0].getHostPortSpec(), is(not(equalTo(String.valueOf(tcp23.getPort()))))); } @@ -259,8 +261,8 @@ public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp23 = ExposedPort.tcp(23); Ports portBindings = new Ports(); - portBindings.bind(tcp22, Ports.binding("11022")); - portBindings.bind(tcp23, Ports.binding("11022")); + portBindings.bind(tcp22, Binding.bindPort(11022)); + portBindings.bind(tcp23, Binding.bindPort(11022)); CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("true") .withExposedPorts(tcp22, tcp23).withPortBindings(portBindings).exec(); From 61869c8a75cd9e3e295aadacc74b92471b591d1f Mon Sep 17 00:00:00 2001 From: AE Date: Mon, 9 May 2016 19:33:43 +0200 Subject: [PATCH 025/780] Adds tests for inspect command when size is used. --- .../command/InspectContainerCmdImplTest.java | 17 +++++++++++++++++ .../netty/exec/InspectContainerCmdExecTest.java | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java index 47ed11201..2a20edc6e 100644 --- a/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java @@ -63,6 +63,23 @@ public void inspectContainer() throws DockerException { } + @Test() + public void inspectContainerWithSize() throws DockerException { + + String containerName = "generated_" + new SecureRandom().nextInt(); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("top") + .withName(containerName).exec(); + LOG.info("Created container {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(container.getId()) + .withSize(true) + .exec(); + assertNotNull(containerInfo.getSizeRootFs()); + assertEquals(containerInfo.getId(), container.getId()); + } + @Test(expectedExceptions = NotFoundException.class) public void inspectNonExistingContainer() throws DockerException { dockerClient.inspectContainerCmd("non-existing").exec(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java index 87fe3b48b..8f38dde79 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java @@ -63,6 +63,21 @@ public void inspectContainer() throws DockerException { } + @Test() + public void inspectContainerWithSize() throws DockerException { + + String containerName = "generated_" + new SecureRandom().nextInt(); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("top") + .withName(containerName).exec(); + LOG.info("Created container {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(container.getId()).exec(); + assertEquals(containerInfo.getId(), container.getId()); + assertNotNull(containerInfo.getSizeRootFs()); + } + @Test(expectedExceptions = NotFoundException.class) public void inspectNonExistingContainer() throws DockerException { dockerClient.inspectContainerCmd("non-existing").exec(); From d2b2a2dde55f367831a749f6246438d08e4522b5 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Mon, 9 May 2016 20:41:27 +0300 Subject: [PATCH 026/780] Added Test Case that simulates failure on copyArchiveToContainerCmdImpl when last tar entry is an empty dir --- .../CopyArchiveToContainerCmdImplTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 0f8f2164b..06967706f 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -90,5 +90,32 @@ public void copyToNonExistingContainer() throws Exception { } catch (NotFoundException ignored) { } } + + @Test + public void copyDirWithLastAddedTarEnryEmptyDir() throws Exception{ + // create a temp dir + Path localDir = Files.createTempDirectory(""); + localDir.toFile().deleteOnExit(); + // create sub-dir with name b + Path emptyDir = Files.createTempDirectory(localDir.resolve("b"), ""); + emptyDir.toFile().deleteOnExit(); + // creaet sub-dir with name a + Path dirWithFile = Files.createTempDirectory(localDir.resolve("a"), ""); + dirWithFile.toFile().deleteOnExit(); + // create file in sub-dir b, name or conter are irrelevant + Path file = Files.createTempFile(dirWithFile.resolve("file"), "", ""); + file.toFile().deleteOnExit(); + + // create a test container + CreateContainerResponse container = dockerClient.createContainerCmd("progrium/busybox:latest") + .withCmd("/bin/sh", "-c", "while true; do sleep 9999; done") + .exec(); + // start the container + dockerClient.startContainerCmd(container.getId()).exec(); + // copy data from local dir to container + dockerClient.copyArchiveToContainerCmd(container.getId()) + .withHostResource(localDir.toString()) + .exec(); + } } From 72b2e73a686c39851c177cc440725ef2f888de9d Mon Sep 17 00:00:00 2001 From: AE Date: Mon, 9 May 2016 19:58:00 +0200 Subject: [PATCH 027/780] Strenghten tests for withSize in InspectContainer. --- .../core/command/InspectContainerCmdImplTest.java | 10 ++++++---- .../netty/exec/InspectContainerCmdExecTest.java | 7 ++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java index 2a20edc6e..c0eaab3a6 100644 --- a/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/InspectContainerCmdImplTest.java @@ -8,6 +8,7 @@ import java.lang.reflect.Method; import java.security.SecureRandom; +import com.github.dockerjava.api.command.InspectContainerCmd; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.ITestResult; @@ -73,11 +74,12 @@ public void inspectContainerWithSize() throws DockerException { LOG.info("Created container {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); - InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(container.getId()) - .withSize(true) - .exec(); - assertNotNull(containerInfo.getSizeRootFs()); + InspectContainerCmd command = dockerClient.inspectContainerCmd(container.getId()).withSize(true); + assertTrue(command.getSize()); + InspectContainerResponse containerInfo = command.exec(); assertEquals(containerInfo.getId(), container.getId()); + assertNotNull(containerInfo.getSizeRootFs()); + assertTrue(containerInfo.getSizeRootFs().intValue() > 0 ); } @Test(expectedExceptions = NotFoundException.class) diff --git a/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java index 8f38dde79..af32cebce 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/InspectContainerCmdExecTest.java @@ -8,6 +8,7 @@ import java.lang.reflect.Method; import java.security.SecureRandom; +import com.github.dockerjava.api.command.InspectContainerCmd; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.ITestResult; @@ -73,9 +74,13 @@ public void inspectContainerWithSize() throws DockerException { LOG.info("Created container {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); - InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(container.getId()).exec(); + InspectContainerCmd command = dockerClient.inspectContainerCmd(container.getId()) + .withSize(true); + assertTrue(command.getSize()); + InspectContainerResponse containerInfo = command.exec(); assertEquals(containerInfo.getId(), container.getId()); assertNotNull(containerInfo.getSizeRootFs()); + assertTrue(containerInfo.getSizeRootFs().intValue() > 0 ); } @Test(expectedExceptions = NotFoundException.class) From 8af6f2f6437aec20c4ce3501d8843eb4c60d69d7 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Mon, 9 May 2016 21:54:53 +0200 Subject: [PATCH 028/780] Polish test and comment --- src/main/java/com/github/dockerjava/api/model/ExposedPort.java | 2 +- .../github/dockerjava/core/command/BuildImageCmdImplTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java index 4e30c8df0..ec95f6273 100644 --- a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java +++ b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java @@ -65,7 +65,7 @@ public ExposedPort(int port) { * @param scheme * the {@link #getScheme() scheme}, tcp or udp * @param port - * the {@link #getPort() port number or port range} + * the {@link #getPort() port number} * @deprecated use {@link #ExposedPort(int, InternetProtocol)} */ @Deprecated diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index 8eea40eec..c0dc967d4 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -34,6 +34,7 @@ import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; +import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; import com.github.dockerjava.core.util.CompressArchiveUtil; @@ -263,7 +264,7 @@ public void testBuildFromPrivateRegistry() throws Exception { CreateContainerResponse testregistry = dockerClient .createContainerCmd("testregistry:2") .withName("registry") - .withPortBindings(new PortBinding(Ports.Binding.bindPortSpec("5000"), ExposedPort.tcp(5000))) + .withPortBindings(new PortBinding(Binding.bindPort(5000), ExposedPort.tcp(5000))) .withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key") From 8b5badadca35dfb8f96f398aad5aaa942a064fe1 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Mon, 9 May 2016 22:35:55 +0200 Subject: [PATCH 029/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f88303a1c..235b87622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Notes All changes +* [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory Included in 3.0.0-RC5 From 572a1eafe84397abaf4c93f882e71b6b49c2d27e Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Mon, 9 May 2016 23:27:56 +0200 Subject: [PATCH 030/780] Polish tests --- .../CopyArchiveToContainerCmdImpl.java | 8 ++--- .../CopyArchiveToContainerCmdImplTest.java | 33 ++++++++++--------- .../CopyArchiveToContainerCmdExecTest.java | 28 ++++++++++++++++ 3 files changed, 49 insertions(+), 20 deletions(-) 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 3a35b3508..0f734fde9 100644 --- a/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImpl.java @@ -12,7 +12,7 @@ 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.DockerClientException; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.core.util.CompressArchiveUtil; @@ -127,7 +127,7 @@ public Void exec() throws NotFoundException { if (StringUtils.isNotEmpty(this.hostResource)) { // User set host resource and not directly a stream if (this.tarInputStream != null) { - throw new BadRequestException( + throw new DockerClientException( "Only one of host resource or tar input stream should be defined to perform the copy, not both"); } // We compress the given path, call exec so that the stream is consumed and then close it our self @@ -135,10 +135,10 @@ public Void exec() throws NotFoundException { this.tarInputStream = uploadStream; return super.exec(); } catch (IOException e) { - throw new BadRequestException("Unable to perform tar on host resource " + this.hostResource); + throw new DockerClientException("Unable to perform tar on host resource " + this.hostResource, e); } } else if (this.tarInputStream == null) { - throw new BadRequestException( + throw new DockerClientException( "One of host resource or tar input stream must be defined to perform the copy"); } // User set a stream, so we will just consume it and let the user close it by him self 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 06967706f..b8ede3416 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; +import org.apache.commons.io.FileUtils; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -90,32 +91,32 @@ public void copyToNonExistingContainer() throws Exception { } catch (NotFoundException ignored) { } } - - @Test - public void copyDirWithLastAddedTarEnryEmptyDir() throws Exception{ + + @Test + public void copyDirWithLastAddedTarEntryEmptyDir() throws Exception{ // create a temp dir - Path localDir = Files.createTempDirectory(""); + Path localDir = Files.createTempDirectory(null); localDir.toFile().deleteOnExit(); - // create sub-dir with name b - Path emptyDir = Files.createTempDirectory(localDir.resolve("b"), ""); - emptyDir.toFile().deleteOnExit(); - // creaet sub-dir with name a - Path dirWithFile = Files.createTempDirectory(localDir.resolve("a"), ""); - dirWithFile.toFile().deleteOnExit(); + // create empty sub-dir with name b + Files.createDirectory(localDir.resolve("b")); + // create sub-dir with name a + Path dirWithFile = Files.createDirectory(localDir.resolve("a")); // create file in sub-dir b, name or conter are irrelevant - Path file = Files.createTempFile(dirWithFile.resolve("file"), "", ""); - file.toFile().deleteOnExit(); - + Files.createFile(dirWithFile.resolve("file")); + // create a test container - CreateContainerResponse container = dockerClient.createContainerCmd("progrium/busybox:latest") - .withCmd("/bin/sh", "-c", "while true; do sleep 9999; done") + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("sleep", "9999") .exec(); // start the container dockerClient.startContainerCmd(container.getId()).exec(); - // copy data from local dir to container + // copy data from local dir to container dockerClient.copyArchiveToContainerCmd(container.getId()) .withHostResource(localDir.toString()) .exec(); + + // cleanup dir + FileUtils.deleteDirectory(localDir.toFile()); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java index d755dfcba..9e9b0c731 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; +import org.apache.commons.io.FileUtils; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -91,4 +92,31 @@ public void copyToNonExistingContainer() throws Exception { } } + @Test + public void copyDirWithLastAddedTarEntryEmptyDir() throws Exception{ + // create a temp dir + Path localDir = Files.createTempDirectory(null); + localDir.toFile().deleteOnExit(); + // create empty sub-dir with name b + Files.createDirectory(localDir.resolve("b")); + // create sub-dir with name a + Path dirWithFile = Files.createDirectory(localDir.resolve("a")); + // create file in sub-dir b, name or conter are irrelevant + Files.createFile(dirWithFile.resolve("file")); + + // create a test container + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("sleep", "9999") + .exec(); + // start the container + dockerClient.startContainerCmd(container.getId()).exec(); + // copy data from local dir to container + dockerClient.copyArchiveToContainerCmd(container.getId()) + .withHostResource(localDir.toString()) + .exec(); + + // cleanup dir + FileUtils.deleteDirectory(localDir.toFile()); + } + } From 1f85b7dfacc447cfdf5e66df4e142620a6753ce0 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Mon, 9 May 2016 23:30:44 +0200 Subject: [PATCH 031/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 235b87622..4e93dd737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Notes All changes * [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges +* [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory Included in 3.0.0-RC5 From 28e11ed2af5ea3ef3dc73a067467d9fb9f8bda19 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Wed, 11 May 2016 21:23:51 +0200 Subject: [PATCH 032/780] Fix issue #551 --- .../core/command/BuildImageCmdImpl.java | 2 +- .../core/dockerfile/Dockerfile.java | 26 ++++++++++++------- .../core/command/BuildImageCmdImplTest.java | 19 ++++++++++++-- .../DockerfileAddMultipleFilesTest.java | 2 +- .../core/dockerfile/DockerfileTest.java | 2 +- .../dockerfileFolder/Dockerfile | 7 +++++ .../testrunFolder/testrun.sh | 3 +++ 7 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile create mode 100755 src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java index 58f148cb6..487f0b264 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java @@ -272,7 +272,7 @@ public BuildImageCmdImpl withDockerfile(File dockerfile) { this.dockerFile = dockerfile; try { - withTarInputStream(new Dockerfile(dockerfile).parse().buildDockerFolderTar(baseDirectory)); + withTarInputStream(new Dockerfile(dockerfile, baseDirectory).parse().buildDockerFolderTar()); } catch (IOException e) { // we just created the file this should never happen. throw new RuntimeException(e); diff --git a/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java b/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java index 8c1c34e2a..c970d6c2d 100644 --- a/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java +++ b/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java @@ -31,8 +31,9 @@ public class Dockerfile { public final File dockerFile; - public Dockerfile(File dockerFile) { + private final File baseDirectory; + public Dockerfile(File dockerFile, File baseDirectory) { if (!dockerFile.exists()) { throw new IllegalStateException(String.format("Dockerfile %s does not exist", dockerFile.getAbsolutePath())); } @@ -43,6 +44,15 @@ public Dockerfile(File dockerFile) { this.dockerFile = dockerFile; + if (!baseDirectory.exists()) { + throw new IllegalStateException(String.format("Base directory %s does not exist", baseDirectory.getAbsolutePath())); + } + + if (!baseDirectory.isDirectory()) { + throw new IllegalStateException(String.format("Base directory %s is not a directory", baseDirectory.getAbsolutePath())); + } + + this.baseDirectory = baseDirectory; } private static class LineTransformer implements Function> { @@ -76,7 +86,7 @@ public Iterable getStatements() throws IOException { public List getIgnores() throws IOException { List ignores = new ArrayList(); - File dockerIgnoreFile = new File(getDockerFolder(), ".dockerignore"); + File dockerIgnoreFile = new File(baseDirectory, ".dockerignore"); if (dockerIgnoreFile.exists()) { int lineNumber = 0; List dockerIgnoreFileContent = FileUtils.readLines(dockerIgnoreFile); @@ -102,10 +112,6 @@ public ScannedResult parse() throws IOException { return new ScannedResult(); } - public File getDockerFolder() { - return dockerFile.getParentFile(); - } - /** * Result of scanning / parsing a docker file. */ @@ -116,7 +122,7 @@ public class ScannedResult { final List filesToAdd = new ArrayList(); public InputStream buildDockerFolderTar() { - return buildDockerFolderTar(getDockerFolder()); + return buildDockerFolderTar(baseDirectory); } public InputStream buildDockerFolderTar(File directory) { @@ -180,7 +186,7 @@ public ScannedResult() throws IOException { "Dockerfile is excluded by pattern '%s' in .dockerignore file", matchingIgnorePattern)); } - Collection filesInBuildContext = FileUtils.listFiles(getDockerFolder(), TrueFileFilter.INSTANCE, + Collection filesInBuildContext = FileUtils.listFiles(baseDirectory, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); for (File f : filesInBuildContext) { @@ -217,7 +223,7 @@ private List matchingIgnorePatterns(String fileName) { * will be respected. */ private String effectiveMatchingIgnorePattern(File file) { - String relativeFilename = FilePathUtil.relativize(getDockerFolder(), file); + String relativeFilename = FilePathUtil.relativize(baseDirectory, file); List matchingPattern = matchingIgnorePatterns(relativeFilename); @@ -242,6 +248,6 @@ private String effectiveMatchingIgnorePattern(File file) { } return lastMatchingPattern; - } + } } } diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index c0dc967d4..950b80a24 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -24,16 +24,15 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.command.InspectImageResponse; +import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.AuthConfigurations; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.PortBinding; -import com.github.dockerjava.api.model.Ports; import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; import com.github.dockerjava.core.util.CompressArchiveUtil; @@ -319,4 +318,20 @@ public void testBuildArgs() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + + public void testDockerfileNotInBaseDirectory() throws Exception { + File baseDirectory = getResource("testDockerfileNotInBaseDirectory"); + File dockerfile = getResource("testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); + BuildImageCmd command = dockerClient.buildImageCmd() + .withBaseDirectory(baseDirectory) + .withDockerfile(dockerfile); + + String response = execBuild(command); + + assertThat(response, containsString("Successfully executed testrun.sh")); + } + + private File getResource(String path) { + return new File(Thread.currentThread().getContextClassLoader().getResource(path).getFile()); + } } diff --git a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java index 0752aded5..8997a6d80 100644 --- a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java +++ b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java @@ -29,7 +29,7 @@ public String apply(File file) { public void testAddMultipleFiles() throws IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddMultipleFiles") .getFile()); - Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile")); + Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile"), baseDir); Dockerfile.ScannedResult result = dockerfile.parse(); Collection filesToAdd = transform(result.filesToAdd, TO_FILE_NAMES); diff --git a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java index ba96ad2eb..390bcf647 100644 --- a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java +++ b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java @@ -26,7 +26,7 @@ public void testAllItems() throws IOException { for (File child : root.listFiles()) { if (new File(child, "Dockerfile").exists()) { - Dockerfile dockerfile = new Dockerfile(new File(child, "Dockerfile")); + Dockerfile dockerfile = new Dockerfile(new File(child, "Dockerfile"), baseDir); dockerfiles.put(child.getName(), dockerfile); } } diff --git a/src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile b/src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile new file mode 100644 index 000000000..9bf10088b --- /dev/null +++ b/src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile @@ -0,0 +1,7 @@ +FROM ubuntu:latest + +ADD testrunFolder/testrun.sh /tmp/ + +RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh + +CMD ["testrun.sh"] \ No newline at end of file diff --git a/src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh b/src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh new file mode 100755 index 000000000..14259aa77 --- /dev/null +++ b/src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Successfully executed testrun.sh" \ No newline at end of file From f6edaaad38a3c0451f3c6d923a27e3592fca830f Mon Sep 17 00:00:00 2001 From: "Ciro S. Costa" Date: Thu, 12 May 2016 13:47:10 -0300 Subject: [PATCH 033/780] Adds namefilteer to netty's ListimagesCmdExec Previously just jaxrs had implemented the feature of filtering by image name. Even though the `withFilter` was exposed, netty's implemntation didn't checked for its presence. The commits adds a test for such feature and the correctionn to the mentioned problem. --- .../dockerjava/netty/exec/ListImagesCmdExec.java | 4 ++++ .../dockerjava/netty/exec/ListImagesCmdExecTest.java | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/java/com/github/dockerjava/netty/exec/ListImagesCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/ListImagesCmdExec.java index 0d1b81962..a1a38add5 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/ListImagesCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/ListImagesCmdExec.java @@ -33,6 +33,10 @@ protected List execute(ListImagesCmd command) { webTarget = webTarget.queryParam("filters", urlPathSegmentEscaper().escape(FiltersEncoder.jsonEncode(command.getFilters()))); } + if (command.getImageNameFilter() != null) { + webTarget = webTarget.queryParam("filter", urlPathSegmentEscaper().escape(command.getImageNameFilter())); + } + LOGGER.trace("GET: {}", webTarget); List images = webTarget.request().accept(MediaType.APPLICATION_JSON) diff --git a/src/test/java/com/github/dockerjava/netty/exec/ListImagesCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ListImagesCmdExecTest.java index c83fa7ef9..170a8479f 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/ListImagesCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/ListImagesCmdExecTest.java @@ -75,6 +75,18 @@ public void listImagesWithDanglingFilter() throws DockerException { assertTrue(imageInFilteredList); } + @Test + public void listImagesWithNameFilter() throws DockerException { + String imageId = createDanglingImage(); + dockerClient.tagImageCmd(imageId, "test_repository", "latest").exec(); + List images = dockerClient.listImagesCmd().withImageNameFilter("test_repository:latest").exec(); + assertThat(images, notNullValue()); + LOG.info("Images List: {}", images); + assertThat(images.size(), is(equalTo(1))); + Boolean imageInFilteredList = isImageInFilteredList(images, imageId); + assertTrue(imageInFilteredList); + } + private boolean isImageInFilteredList(List images, String expectedImageId) { for (Image image : images) { if (expectedImageId.equals(image.getId())) { From 7ab0418022e9a1591c8c76c2213e946c58914b91 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 12 May 2016 19:35:25 +0200 Subject: [PATCH 034/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e93dd737..242d575f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Notes All changes +* [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context * [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges * [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory From 0533459c533bf58ff3fcd66603849f7589d62cf7 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Thu, 12 May 2016 20:13:39 +0200 Subject: [PATCH 035/780] Polish inspect container with rootFS size --- .../com/github/dockerjava/api/command/InspectContainerCmd.java | 2 +- .../dockerjava/core/command/InspectContainerCmdImpl.java | 2 +- .../com/github/dockerjava/jaxrs/InspectContainerCmdExec.java | 3 ++- .../github/dockerjava/netty/exec/InspectContainerCmdExec.java | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java index c0f666fa3..bbb0159f8 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java @@ -14,7 +14,7 @@ public interface InspectContainerCmd extends SyncDockerCmd() { From d4b3be163fc8fc01a2c16d578eda1a7eeebd9fa4 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 12 May 2016 20:15:32 +0200 Subject: [PATCH 036/780] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 242d575f3..44358e876 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,10 @@ Notes All changes -* [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context +* [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context * [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges * [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug +* [#572] (https://github.com/docker-java/docker-java/pull/572) Inspect container command now shows sizes if requested * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory Included in 3.0.0-RC5 From 763559fbfa371d40bc96d3955d4fd8562718c090 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 12 May 2016 21:04:58 +0200 Subject: [PATCH 037/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44358e876..ad9ddbba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All changes * [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug * [#572] (https://github.com/docker-java/docker-java/pull/572) Inspect container command now shows sizes if requested * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory +* [#550] (https://github.com/docker-java/docker-java/pull/550) Add ability to configure IPAM config for CreateNetworkCmd Included in 3.0.0-RC5 From e0d418b401308fe24814b249944036be01b4affd Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 12 May 2016 23:53:57 +0200 Subject: [PATCH 038/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad9ddbba7..75f0f9dc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Notes All changes +* [#579] (https://github.com/docker-java/docker-java/pull/579) Adds missing name filter evaluation to netty version of ListImagesCmdExec * [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context * [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges * [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug From f4dc5637965064c8627137c08511dfc2a84b2aec Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sat, 14 May 2016 23:58:45 +0300 Subject: [PATCH 039/780] Fixes execute permissions for files inside a dir added to tar using copyArchiveToContainerCmdIml. Files added to tar are stored with 644 permission mode. As a result, execute permissions are discarded. This fix retains permissions for files inside directories copied with copyArchiveToContainerCmdIml. --- .../java/com/github/dockerjava/core/util/TarDirWalker.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java index af263ee9c..3c5336a28 100644 --- a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java +++ b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java @@ -33,8 +33,11 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, - new TarArchiveEntry(FilePathUtil.relativize(basePath, file)), file); + TarArchiveEntry tarEntry = new TarArchiveEntry(FilePathUtil.relativize(basePath, file)); + if (filePath.toFile().canExecute()) { + tarEntry.setMode(tarEntry.getMode() | 0755); + } + CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, tarEntry, file); return FileVisitResult.CONTINUE; } From e229005fd43e9e8d89d52f115ad096947cfd6b14 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 00:02:44 +0300 Subject: [PATCH 040/780] Fixes execute permissions for files not contained in any dir that are added to tar using copyArchiveToContainerCmdIml. --- .../github/dockerjava/core/util/CompressArchiveUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 5052dda40..a4616514e 100644 --- a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java @@ -67,7 +67,11 @@ public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean try (TarArchiveOutputStream tarArchiveOutputStream = buildTarStream(outputPath, gZipped)) { if (!Files.isDirectory(inputPath)) { - putTarEntry(tarArchiveOutputStream, new TarArchiveEntry(inputPath.getFileName().toString()), inputPath); + TarArchiveEntry tarEntry = new TarArchiveEntry(inputPath.getFileName().toString()); + if (filePath.toFile().canExecute()) { + tarEntry.setMode(tarEntry.getMode() | 0755); + } + putTarEntry(tarArchiveOutputStream, tarEntry, inputPath); } else { Path sourcePath = inputPath; if (!childrenOnly) { From cc93a1fb54bea392cf0c2da5c82ab190a2f921bd Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 01:15:58 +0300 Subject: [PATCH 041/780] Added Test Case for CopyArchiveToContainerCmdImpl when copying files with execute permission. Test Case that simulates a scenario where a script file with permission to execute is copied to the containers with CopyArchiveToContainerCmdImpl and then it is executed. --- .../CopyArchiveToContainerCmdImplTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) 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 06967706f..04117aba7 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.equalTo; import java.io.IOException; import java.io.InputStream; @@ -117,5 +118,39 @@ public void copyDirWithLastAddedTarEnryEmptyDir() throws Exception{ .withHostResource(localDir.toString()) .exec(); } + + @Test + public void copyFileWithExecutePermission() throws Exception { + // create script file, add permission to execute + scriptPath = Files.createTempFile("run", ".sh"); + boolean executable = scriptPath.toFile().setExecutable(true, false); + if (!executable){ + throw new Exception("Execute permission on file not set!"); + } + String snippet = "Running script with execute permission."; + String scriptTextStr = "#!/bin/sh\necho \"" + snippet + "\""; + // write content for created script + Files.write(scriptPath, scriptTextStr.getBytes()); + // create a test container which starts and waits 3 seconds for the + // script to be copied to the container's home dir and then executes it + String containerCmd = "sleep 3; /home/" + scriptPath.getFileName().toString(); + CreateContainerResponse container = docker.createContainerCmd("busybox") + .withName("test") + .withCmd("/bin/sh", "-c", containerCmd) + .exec(); + // start the container + docker.startContainerCmd(container.getId()).exec(); + // copy script to container home dir + docker.copyArchiveToContainerCmd(container.getId()) + .withRemotePath("/home") + .withHostResource(scriptPath.toString()) + .exec(); + // await exid code + int exitCode = docker.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) + .awaitStatusCode(); + // check result + assertThat(exitCode, equalTo(0)); + } } From d3918c3ff3e17dbb4cf3442bae0aa1b22c8ef857 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 01:52:35 +0300 Subject: [PATCH 042/780] Fixed input file name --- .../com/github/dockerjava/core/util/CompressArchiveUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a4616514e..2e75bcc41 100644 --- a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java @@ -68,7 +68,7 @@ public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean try (TarArchiveOutputStream tarArchiveOutputStream = buildTarStream(outputPath, gZipped)) { if (!Files.isDirectory(inputPath)) { TarArchiveEntry tarEntry = new TarArchiveEntry(inputPath.getFileName().toString()); - if (filePath.toFile().canExecute()) { + if (inputPath.toFile().canExecute()) { tarEntry.setMode(tarEntry.getMode() | 0755); } putTarEntry(tarArchiveOutputStream, tarEntry, inputPath); From c93a1fca4a062a7d90d361c061aa3a6a2edf6057 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 01:55:10 +0300 Subject: [PATCH 043/780] Fixed name for variable --- src/main/java/com/github/dockerjava/core/util/TarDirWalker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java index 3c5336a28..bbe834ee6 100644 --- a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java +++ b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java @@ -34,7 +34,7 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { TarArchiveEntry tarEntry = new TarArchiveEntry(FilePathUtil.relativize(basePath, file)); - if (filePath.toFile().canExecute()) { + if (file.toFile().canExecute()) { tarEntry.setMode(tarEntry.getMode() | 0755); } CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, tarEntry, file); From 7ee187b7ee025ac2a798842f1db06ea198ad6666 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 02:01:14 +0300 Subject: [PATCH 044/780] Added missing variable type declaration --- .../core/command/CopyArchiveToContainerCmdImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 04117aba7..a1652456e 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -122,7 +122,7 @@ public void copyDirWithLastAddedTarEnryEmptyDir() throws Exception{ @Test public void copyFileWithExecutePermission() throws Exception { // create script file, add permission to execute - scriptPath = Files.createTempFile("run", ".sh"); + Path scriptPath = Files.createTempFile("run", ".sh"); boolean executable = scriptPath.toFile().setExecutable(true, false); if (!executable){ throw new Exception("Execute permission on file not set!"); From 381b7db28fd1007dea34b491c57fcd2ba8108591 Mon Sep 17 00:00:00 2001 From: Lappas Dionysis Date: Sun, 15 May 2016 02:07:25 +0300 Subject: [PATCH 045/780] Fixed docker client name --- .../core/command/CopyArchiveToContainerCmdImplTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 a1652456e..d96a6ad25 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -134,19 +134,19 @@ public void copyFileWithExecutePermission() throws Exception { // create a test container which starts and waits 3 seconds for the // script to be copied to the container's home dir and then executes it String containerCmd = "sleep 3; /home/" + scriptPath.getFileName().toString(); - CreateContainerResponse container = docker.createContainerCmd("busybox") + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") .withName("test") .withCmd("/bin/sh", "-c", containerCmd) .exec(); // start the container - docker.startContainerCmd(container.getId()).exec(); + dockerClient.startContainerCmd(container.getId()).exec(); // copy script to container home dir - docker.copyArchiveToContainerCmd(container.getId()) + dockerClient.copyArchiveToContainerCmd(container.getId()) .withRemotePath("/home") .withHostResource(scriptPath.toString()) .exec(); // await exid code - int exitCode = docker.waitContainerCmd(container.getId()) + int exitCode = dockerClient.waitContainerCmd(container.getId()) .exec(new WaitContainerResultCallback()) .awaitStatusCode(); // check result From 328cd6745af14f57c43b948eaa742d1424ace50a Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Tue, 24 May 2016 20:58:51 +0200 Subject: [PATCH 046/780] Add test for netty impl --- .../CopyArchiveToContainerCmdExecTest.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java index 9e9b0c731..eb43b54de 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java @@ -1,6 +1,7 @@ package com.github.dockerjava.netty.exec; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; @@ -21,6 +22,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.core.command.WaitContainerResultCallback; import com.github.dockerjava.core.util.CompressArchiveUtil; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; @@ -119,4 +121,38 @@ public void copyDirWithLastAddedTarEntryEmptyDir() throws Exception{ FileUtils.deleteDirectory(localDir.toFile()); } + @Test + public void copyFileWithExecutePermission() throws Exception { + // create script file, add permission to execute + Path scriptPath = Files.createTempFile("run", ".sh"); + boolean executable = scriptPath.toFile().setExecutable(true, false); + if (!executable){ + throw new Exception("Execute permission on file not set!"); + } + String snippet = "Running script with execute permission."; + String scriptTextStr = "#!/bin/sh\necho \"" + snippet + "\""; + // write content for created script + Files.write(scriptPath, scriptTextStr.getBytes()); + // create a test container which starts and waits 3 seconds for the + // script to be copied to the container's home dir and then executes it + String containerCmd = "sleep 3; /home/" + scriptPath.getFileName().toString(); + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withName("test") + .withCmd("/bin/sh", "-c", containerCmd) + .exec(); + // start the container + dockerClient.startContainerCmd(container.getId()).exec(); + // copy script to container home dir + dockerClient.copyArchiveToContainerCmd(container.getId()) + .withRemotePath("/home") + .withHostResource(scriptPath.toString()) + .exec(); + // await exid code + int exitCode = dockerClient.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) + .awaitStatusCode(); + // check result + assertThat(exitCode, equalTo(0)); + } + } From 0758623f4763fe4e45618beba5c0233874e2266e Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Tue, 24 May 2016 20:59:41 +0200 Subject: [PATCH 047/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75f0f9dc7..429f4b275 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Notes All changes +* [#580] (https://github.com/docker-java/docker-java/pull/580) Fixes execute permissions for files when copied to container * [#579] (https://github.com/docker-java/docker-java/pull/579) Adds missing name filter evaluation to netty version of ListImagesCmdExec * [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context * [#575] (https://github.com/docker-java/docker-java/pull/575) Support binding of port ranges From a1d1e3dfda7a2ade9304c990f73d42aa573ef342 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 24 May 2016 14:19:28 -0600 Subject: [PATCH 048/780] Fixes Issue #584 Adds RootDir property to GraphData. This was seen on a CentOS system without aufs support. --- .../dockerjava/api/command/GraphData.java | 26 ++- .../api/command/InspectImageResponseTest.java | 197 +++++++++--------- 2 files changed, 122 insertions(+), 101 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/GraphData.java b/src/main/java/com/github/dockerjava/api/command/GraphData.java index dc55810ba..a00f44e5d 100644 --- a/src/main/java/com/github/dockerjava/api/command/GraphData.java +++ b/src/main/java/com/github/dockerjava/api/command/GraphData.java @@ -1,17 +1,23 @@ package com.github.dockerjava.api.command; -import com.fasterxml.jackson.annotation.JsonProperty; +import javax.annotation.CheckForNull; + import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; -import javax.annotation.CheckForNull; +import com.fasterxml.jackson.annotation.JsonProperty; /** * part of {@link GraphDriver} + * * @author Kanstantsin Shautsou */ public class GraphData { + + @JsonProperty("RootDir") + private String rootDir; + @JsonProperty("DeviceId") private String deviceId; @@ -21,6 +27,22 @@ public class GraphData { @JsonProperty("DeviceSize") private String deviceSize; + /** + * @see #rootDir + */ + @CheckForNull + public String getRootDir() { + return rootDir; + } + + /** + * @see #deviceId + */ + public GraphData withRootDir(String rootDir) { + this.rootDir = rootDir; + return this; + } + /** * @see #deviceId */ diff --git a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java index 410d5b32a..e7cd2aaa8 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java @@ -1,13 +1,5 @@ package com.github.dockerjava.api.command; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.dockerjava.api.model.ContainerConfig; -import org.testng.annotations.Test; - -import java.io.IOException; -import java.util.Collections; - import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_22; import static com.github.dockerjava.test.serdes.JSONSamples.testRoundTrip; import static org.hamcrest.MatcherAssert.assertThat; @@ -21,65 +13,72 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import java.io.IOException; +import java.util.Collections; + +import org.testng.annotations.Test; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.ContainerConfig; + /** * @author Kanstantsin Shautsou */ public class InspectImageResponseTest { + @Test public void serder1_22Json() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, - "images/image1/inspect1.json", - type - ); - - final ContainerConfig config = new ContainerConfig() - .withAttachStderr(false) - .withAttachStdin(false) - .withAttachStdout(false) - .withCmd(null) - .withDomainName("") - .withEntrypoint(null) - .withEnv(new String[]{"HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) - .withExposedPorts(null) - .withHostName("aee9ba801acc") - .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") - .withLabels(null) - .withMacAddress(null) - .withNetworkDisabled(null) - .withOnBuild(new String[]{}) - .withStdinOpen(false) - .withPortSpecs(null) - .withStdInOnce(false) - .withTty(false) - .withUser("") - .withVolumes(null) - .withWorkingDir(""); - - final ContainerConfig containerConfig = new ContainerConfig() - .withAttachStderr(false) - .withAttachStdin(false) - .withAttachStdout(false) - .withCmd(new String[]{"/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net"}) - .withDomainName("") - .withEntrypoint(null) - .withEnv(new String[]{"HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) - .withExposedPorts(null) - .withHostName("aee9ba801acc") - .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") - .withLabels(null) - .withMacAddress(null) - .withNetworkDisabled(null) - .withOnBuild(new String[]{}) - .withStdinOpen(false) - .withPortSpecs(null) - .withStdInOnce(false) - .withTty(false) - .withUser("") - .withVolumes(null) - .withWorkingDir(""); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/image1/inspect1.json", type); + + final ContainerConfig config = new ContainerConfig().withAttachStderr(false) + .withAttachStdin(false) + .withAttachStdout(false) + .withCmd(null) + .withDomainName("") + .withEntrypoint(null) + .withEnv(new String[] { "HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }) + .withExposedPorts(null) + .withHostName("aee9ba801acc") + .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") + .withLabels(null) + .withMacAddress(null) + .withNetworkDisabled(null) + .withOnBuild(new String[] {}) + .withStdinOpen(false) + .withPortSpecs(null) + .withStdInOnce(false) + .withTty(false) + .withUser("") + .withVolumes(null) + .withWorkingDir(""); + + final ContainerConfig containerConfig = new ContainerConfig().withAttachStderr(false) + .withAttachStdin(false) + .withAttachStdout(false) + .withCmd(new String[] { "/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net" }) + .withDomainName("") + .withEntrypoint(null) + .withEnv(new String[] { "HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }) + .withExposedPorts(null) + .withHostName("aee9ba801acc") + .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") + .withLabels(null) + .withMacAddress(null) + .withNetworkDisabled(null) + .withOnBuild(new String[] {}) + .withStdinOpen(false) + .withPortSpecs(null) + .withStdInOnce(false) + .withTty(false) + .withUser("") + .withVolumes(null) + .withWorkingDir(""); assertThat(inspectImage, notNullValue()); assertThat(inspectImage.getArch(), is("amd64")); @@ -113,52 +112,41 @@ public void serder1_22Json() throws IOException { assertThat(inspectImage.getVirtualSize(), is(0L)); - final InspectImageResponse inspectImageResponse = new InspectImageResponse().withArch("amd64") - .withAuthor("hack@worldticket.net") - .withComment("") - .withConfig(config) - .withContainer("aee9ba801acca0e648ffd91df204ba82ae85d97608a4864a019e2004d7e1b133") - .withContainerConfig(containerConfig) - .withCreated("2014-04-29T19:59:10.84997669Z") - .withDockerVersion("0.8.1") - .withId("sha256:ee45fe0d1fcdf1a0f9c2d1e36c6f4b3202bbb2032f14d7c9312b27bfcf6aee24") - .withOs("linux") - .withParent("") - .withSize(0L) - .withRepoTags(Collections.singletonList("hackmann/empty:latest")) - .withRepoDigests(Collections.emptyList()) - .withVirtualSize(0L) - .withGraphDriver(aufsGraphDriver); + .withAuthor("hack@worldticket.net") + .withComment("") + .withConfig(config) + .withContainer("aee9ba801acca0e648ffd91df204ba82ae85d97608a4864a019e2004d7e1b133") + .withContainerConfig(containerConfig) + .withCreated("2014-04-29T19:59:10.84997669Z") + .withDockerVersion("0.8.1") + .withId("sha256:ee45fe0d1fcdf1a0f9c2d1e36c6f4b3202bbb2032f14d7c9312b27bfcf6aee24") + .withOs("linux") + .withParent("") + .withSize(0L) + .withRepoTags(Collections.singletonList("hackmann/empty:latest")) + .withRepoDigests(Collections. emptyList()) + .withVirtualSize(0L) + .withGraphDriver(aufsGraphDriver); assertThat(inspectImage, equalTo(inspectImageResponse)); } - @Test public void serder1_22_doc() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, - "images/docImage/doc.json", - type - ); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/docImage/doc.json", type); assertThat(inspectImage, notNullValue()); assertThat(inspectImage.getRepoDigests(), hasSize(1)); assertThat(inspectImage.getRepoDigests(), - contains("localhost:5000/test/busybox/example@" + - "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf") - ); + contains("localhost:5000/test/busybox/example@" + "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf")); assertThat(inspectImage.getRepoTags(), hasSize(3)); - assertThat(inspectImage.getRepoTags(), containsInAnyOrder( - "example:1.0", - "example:latest", - "example:stable" - )); + assertThat(inspectImage.getRepoTags(), containsInAnyOrder("example:1.0", "example:latest", "example:stable")); } @Test @@ -166,15 +154,11 @@ public void serder1_22_inspect_doc() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, - "images/docImage/inspect_doc.json", - type - ); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/docImage/inspect_doc.json", type); - GraphData newGraphData = new GraphData() - .withDeviceId("5") - .withDeviceName("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47") - .withDeviceSize("171798691840"); + GraphData newGraphData = new GraphData().withDeviceId("5") + .withDeviceName("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47") + .withDeviceSize("171798691840"); assertThat(inspectImage, notNullValue()); GraphDriver graphDriver = inspectImage.getGraphDriver(); @@ -184,9 +168,24 @@ public void serder1_22_inspect_doc() throws IOException { assertThat(data, is(newGraphData)); assertThat(data.getDeviceId(), is("5")); - assertThat(data.getDeviceName(), - is("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47")); - assertThat(data.getDeviceSize(), - is("171798691840")); + assertThat(data.getDeviceName(), is("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47")); + assertThat(data.getDeviceSize(), is("171798691840")); + } + + @Test + private void testOverlayNetworkRootDir() throws IOException { + final ObjectMapper mapper = new ObjectMapper(); + final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); + + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/overlay/inspectOverlay.json", type); + + final GraphData overlayGraphData = new GraphData().withRootDir("/var/lib/docker/overlay/7e8d362d6b78d47eafe4863fd129cbcada35dbd419d7188cc1dbf1233d505576/root"); + final GraphDriver overlayGraphDriver = new GraphDriver().withName("overlay").withData(overlayGraphData); + final GraphDriver graphDriver = inspectImage.getGraphDriver(); + assertThat(graphDriver, notNullValue()); + assertThat(graphDriver, equalTo(overlayGraphDriver)); + assertThat(graphDriver.getName(), is("overlay")); + assertThat(graphDriver.getData(), equalTo(overlayGraphData)); + } } \ No newline at end of file From 3f71f1f165d652ceb044151c9abea2b1707d56c9 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 24 May 2016 14:19:28 -0600 Subject: [PATCH 049/780] Fixes Issue #584 Adds RootDir property to GraphData. This was seen on a CentOS system without aufs support. --- .../api/command/InspectImageResponseTest.java | 128 +++++++++--------- .../1.22/images/overlay/inspectOverlay.json | 93 +++++++++++++ 2 files changed, 157 insertions(+), 64 deletions(-) create mode 100644 src/test/resources/samples/1.22/images/overlay/inspectOverlay.json diff --git a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java index e7cd2aaa8..5bce25a48 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java @@ -34,51 +34,49 @@ public void serder1_22Json() throws IOException { final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/image1/inspect1.json", type); - final ContainerConfig config = new ContainerConfig().withAttachStderr(false) - .withAttachStdin(false) - .withAttachStdout(false) - .withCmd(null) - .withDomainName("") - .withEntrypoint(null) - .withEnv(new String[] { "HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }) - .withExposedPorts(null) - .withHostName("aee9ba801acc") - .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") - .withLabels(null) - .withMacAddress(null) - .withNetworkDisabled(null) - .withOnBuild(new String[] {}) - .withStdinOpen(false) - .withPortSpecs(null) - .withStdInOnce(false) - .withTty(false) - .withUser("") - .withVolumes(null) - .withWorkingDir(""); + final ContainerConfig config = new ContainerConfig().withAttachStdout(false) + .withCmd(null) + .withDomainName("") + .withEntrypoint(null) + .withEnv(new String[] {"HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) + .withExposedPorts(null) + .withHostName("aee9ba801acc") + .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") + .withLabels(null) + .withMacAddress(null) + .withNetworkDisabled(null) + .withOnBuild(new String[] {}) + .withStdinOpen(false) + .withPortSpecs(null) + .withStdInOnce(false) + .withTty(false) + .withUser("") + .withVolumes(null) + .withWorkingDir(""); final ContainerConfig containerConfig = new ContainerConfig().withAttachStderr(false) - .withAttachStdin(false) - .withAttachStdout(false) - .withCmd(new String[] { "/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net" }) - .withDomainName("") - .withEntrypoint(null) - .withEnv(new String[] { "HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }) - .withExposedPorts(null) - .withHostName("aee9ba801acc") - .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") - .withLabels(null) - .withMacAddress(null) - .withNetworkDisabled(null) - .withOnBuild(new String[] {}) - .withStdinOpen(false) - .withPortSpecs(null) - .withStdInOnce(false) - .withTty(false) - .withUser("") - .withVolumes(null) - .withWorkingDir(""); + .withAttachStdin(false) + .withAttachStdout(false) + .withCmd(new String[] {"/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net"}) + .withDomainName("") + .withEntrypoint(null) + .withEnv(new String[] {"HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) + .withExposedPorts(null) + .withHostName("aee9ba801acc") + .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") + .withLabels(null) + .withMacAddress(null) + .withNetworkDisabled(null) + .withOnBuild(new String[] {}) + .withStdinOpen(false) + .withPortSpecs(null) + .withStdInOnce(false) + .withTty(false) + .withUser("") + .withVolumes(null) + .withWorkingDir(""); assertThat(inspectImage, notNullValue()); assertThat(inspectImage.getArch(), is("amd64")); @@ -113,21 +111,21 @@ public void serder1_22Json() throws IOException { assertThat(inspectImage.getVirtualSize(), is(0L)); final InspectImageResponse inspectImageResponse = new InspectImageResponse().withArch("amd64") - .withAuthor("hack@worldticket.net") - .withComment("") - .withConfig(config) - .withContainer("aee9ba801acca0e648ffd91df204ba82ae85d97608a4864a019e2004d7e1b133") - .withContainerConfig(containerConfig) - .withCreated("2014-04-29T19:59:10.84997669Z") - .withDockerVersion("0.8.1") - .withId("sha256:ee45fe0d1fcdf1a0f9c2d1e36c6f4b3202bbb2032f14d7c9312b27bfcf6aee24") - .withOs("linux") - .withParent("") - .withSize(0L) - .withRepoTags(Collections.singletonList("hackmann/empty:latest")) - .withRepoDigests(Collections. emptyList()) - .withVirtualSize(0L) - .withGraphDriver(aufsGraphDriver); + .withAuthor("hack@worldticket.net") + .withComment("") + .withConfig(config) + .withContainer("aee9ba801acca0e648ffd91df204ba82ae85d97608a4864a019e2004d7e1b133") + .withContainerConfig(containerConfig) + .withCreated("2014-04-29T19:59:10.84997669Z") + .withDockerVersion("0.8.1") + .withId("sha256:ee45fe0d1fcdf1a0f9c2d1e36c6f4b3202bbb2032f14d7c9312b27bfcf6aee24") + .withOs("linux") + .withParent("") + .withSize(0L) + .withRepoTags(Collections.singletonList("hackmann/empty:latest")) + .withRepoDigests(Collections. emptyList()) + .withVirtualSize(0L) + .withGraphDriver(aufsGraphDriver); assertThat(inspectImage, equalTo(inspectImageResponse)); } @@ -143,7 +141,9 @@ public void serder1_22_doc() throws IOException { assertThat(inspectImage.getRepoDigests(), hasSize(1)); assertThat(inspectImage.getRepoDigests(), - contains("localhost:5000/test/busybox/example@" + "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf")); + + contains("localhost:5000/test/busybox/example@" + + "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf")); assertThat(inspectImage.getRepoTags(), hasSize(3)); assertThat(inspectImage.getRepoTags(), containsInAnyOrder("example:1.0", "example:latest", "example:stable")); @@ -157,9 +157,8 @@ public void serder1_22_inspect_doc() throws IOException { final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/docImage/inspect_doc.json", type); GraphData newGraphData = new GraphData().withDeviceId("5") - .withDeviceName("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47") - .withDeviceSize("171798691840"); - + .withDeviceName("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47") + .withDeviceSize("171798691840"); assertThat(inspectImage, notNullValue()); GraphDriver graphDriver = inspectImage.getGraphDriver(); assertThat(graphDriver, notNullValue()); @@ -179,7 +178,8 @@ private void testOverlayNetworkRootDir() throws IOException { final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/overlay/inspectOverlay.json", type); - final GraphData overlayGraphData = new GraphData().withRootDir("/var/lib/docker/overlay/7e8d362d6b78d47eafe4863fd129cbcada35dbd419d7188cc1dbf1233d505576/root"); + final GraphData overlayGraphData = new GraphData() + .withRootDir("/var/lib/docker/overlay/7e8d362d6b78d47eafe4863fd129cbcada35dbd419d7188cc1dbf1233d505576/root"); final GraphDriver overlayGraphDriver = new GraphDriver().withName("overlay").withData(overlayGraphData); final GraphDriver graphDriver = inspectImage.getGraphDriver(); assertThat(graphDriver, notNullValue()); @@ -188,4 +188,4 @@ private void testOverlayNetworkRootDir() throws IOException { assertThat(graphDriver.getData(), equalTo(overlayGraphData)); } -} \ No newline at end of file +} diff --git a/src/test/resources/samples/1.22/images/overlay/inspectOverlay.json b/src/test/resources/samples/1.22/images/overlay/inspectOverlay.json new file mode 100644 index 000000000..7e3fe0bea --- /dev/null +++ b/src/test/resources/samples/1.22/images/overlay/inspectOverlay.json @@ -0,0 +1,93 @@ +{ + "Id": "sha256:0ac989a7cba2ce7f5fbe5d520b338e780055ec251371ee35f7462ae9944696c5", + "RepoTags": [ + "test-image:latest" + ], + "RepoDigests": [], + "Parent": "", + "Comment": "", + "Created": "2016-05-24T19:25:01.31608131Z", + "Container": "221f000eccdec85b74cd4f4f37c7c0392d0f620bee45e9618cac3e57409a6d2c", + "ContainerConfig": { + "Hostname": "6ea525e7ec5c", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ENTRYPOINT [\"bin/run.sh\"]" + ], + "Image": "sha256:f8321fac5b5484874c1c5c02719905ec815c8ad20c2bc66222cfde19cd0491b7", + "Volumes": { + "/var/lib/docker": {} + }, + "WorkingDir": "/opt", + "Entrypoint": [ + "bin/run.sh" + ], + "OnBuild": [], + "Labels": {} + }, + "DockerVersion": "1.11.1", + "Author": "", + "Config": { + "Hostname": "6ea525e7ec5c", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": null, + "Image": "sha256:f8321fac5b5484874c1c5c02719905ec815c8ad20c2bc66222cfde19cd0491b7", + "Volumes": { + "/var/lib/docker": {} + }, + "WorkingDir": "/opt", + "Entrypoint": [ + "bin/run.sh" + ], + "OnBuild": [], + "Labels": {} + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 345943268, + "VirtualSize": 345943268, + "GraphDriver": { + "Name": "overlay", + "Data": { + "RootDir": "/var/lib/docker/overlay/7e8d362d6b78d47eafe4863fd129cbcada35dbd419d7188cc1dbf1233d505576/root" + } + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:bd8153423e4131205018c431283e0a08298b291838db9bc6c19620523f5a818c", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:bb0716c3f5f5be1e5ee6912f7e9f44193898e0b3ed9031a0416f8ca262e89975", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", + "sha256:58845ae9bfa7659900a9b30abb2c96330eff09bfbc6521ea77937ba60f8cc131", + "sha256:8c22161a61c24eb6f7aa130d45189354fd8dbe9467e5b2debf828908113eacb0", + "sha256:0c0c9045d2542e7845a2bdd8ead0e0fb2722be2c07c5553838dd61ffe051d672" + ] + } +} \ No newline at end of file From 9b8ca72947b771c6fbeda00d17b9382fed2c09a6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 24 May 2016 14:19:28 -0600 Subject: [PATCH 050/780] Fixes Issue #584 Adds RootDir property to GraphData. This was seen on a CentOS system without aufs support. --- .../dockerjava/api/command/GraphData.java | 6 +- .../api/command/InspectImageResponseTest.java | 80 ++++++++++++------- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/GraphData.java b/src/main/java/com/github/dockerjava/api/command/GraphData.java index a00f44e5d..1aac8db84 100644 --- a/src/main/java/com/github/dockerjava/api/command/GraphData.java +++ b/src/main/java/com/github/dockerjava/api/command/GraphData.java @@ -1,16 +1,14 @@ package com.github.dockerjava.api.command; -import javax.annotation.CheckForNull; - +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; -import com.fasterxml.jackson.annotation.JsonProperty; +import javax.annotation.CheckForNull; /** * part of {@link GraphDriver} - * * @author Kanstantsin Shautsou */ public class GraphData { diff --git a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java index 5bce25a48..4c604e6a0 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectImageResponseTest.java @@ -1,5 +1,13 @@ package com.github.dockerjava.api.command; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.ContainerConfig; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.Collections; + import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_22; import static com.github.dockerjava.test.serdes.JSONSamples.testRoundTrip; import static org.hamcrest.MatcherAssert.assertThat; @@ -13,40 +21,35 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import java.io.IOException; -import java.util.Collections; - -import org.testng.annotations.Test; - -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.dockerjava.api.model.ContainerConfig; - /** * @author Kanstantsin Shautsou */ public class InspectImageResponseTest { - @Test public void serder1_22Json() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/image1/inspect1.json", type); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, + "images/image1/inspect1.json", + type + ); - final ContainerConfig config = new ContainerConfig().withAttachStdout(false) + final ContainerConfig config = new ContainerConfig() + .withAttachStderr(false) + .withAttachStdin(false) + .withAttachStdout(false) .withCmd(null) .withDomainName("") .withEntrypoint(null) - .withEnv(new String[] {"HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) + .withEnv(new String[]{"HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) .withExposedPorts(null) .withHostName("aee9ba801acc") .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") .withLabels(null) .withMacAddress(null) .withNetworkDisabled(null) - .withOnBuild(new String[] {}) + .withOnBuild(new String[]{}) .withStdinOpen(false) .withPortSpecs(null) .withStdInOnce(false) @@ -55,21 +58,21 @@ public void serder1_22Json() throws IOException { .withVolumes(null) .withWorkingDir(""); - final ContainerConfig containerConfig = new ContainerConfig().withAttachStderr(false) + final ContainerConfig containerConfig = new ContainerConfig() + .withAttachStderr(false) .withAttachStdin(false) .withAttachStdout(false) - .withCmd(new String[] {"/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net"}) + .withCmd(new String[]{"/bin/sh", "-c", "#(nop) MAINTAINER hack@worldticket.net"}) .withDomainName("") .withEntrypoint(null) - .withEnv(new String[] {"HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) + .withEnv(new String[]{"HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) .withExposedPorts(null) .withHostName("aee9ba801acc") .withImage("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158") .withLabels(null) .withMacAddress(null) .withNetworkDisabled(null) - .withOnBuild(new String[] {}) + .withOnBuild(new String[]{}) .withStdinOpen(false) .withPortSpecs(null) .withStdInOnce(false) @@ -110,6 +113,7 @@ public void serder1_22Json() throws IOException { assertThat(inspectImage.getVirtualSize(), is(0L)); + final InspectImageResponse inspectImageResponse = new InspectImageResponse().withArch("amd64") .withAuthor("hack@worldticket.net") .withComment("") @@ -123,30 +127,38 @@ public void serder1_22Json() throws IOException { .withParent("") .withSize(0L) .withRepoTags(Collections.singletonList("hackmann/empty:latest")) - .withRepoDigests(Collections. emptyList()) + .withRepoDigests(Collections.emptyList()) .withVirtualSize(0L) .withGraphDriver(aufsGraphDriver); assertThat(inspectImage, equalTo(inspectImageResponse)); } + @Test public void serder1_22_doc() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/docImage/doc.json", type); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, + "images/docImage/doc.json", + type + ); assertThat(inspectImage, notNullValue()); assertThat(inspectImage.getRepoDigests(), hasSize(1)); assertThat(inspectImage.getRepoDigests(), - - contains("localhost:5000/test/busybox/example@" - + "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf")); + contains("localhost:5000/test/busybox/example@" + + "sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf") + ); assertThat(inspectImage.getRepoTags(), hasSize(3)); - assertThat(inspectImage.getRepoTags(), containsInAnyOrder("example:1.0", "example:latest", "example:stable")); + assertThat(inspectImage.getRepoTags(), containsInAnyOrder( + "example:1.0", + "example:latest", + "example:stable" + )); } @Test @@ -154,11 +166,16 @@ public void serder1_22_inspect_doc() throws IOException { final ObjectMapper mapper = new ObjectMapper(); final JavaType type = mapper.getTypeFactory().constructType(InspectImageResponse.class); - final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, "images/docImage/inspect_doc.json", type); + final InspectImageResponse inspectImage = testRoundTrip(VERSION_1_22, + "images/docImage/inspect_doc.json", + type + ); - GraphData newGraphData = new GraphData().withDeviceId("5") + GraphData newGraphData = new GraphData() + .withDeviceId("5") .withDeviceName("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47") .withDeviceSize("171798691840"); + assertThat(inspectImage, notNullValue()); GraphDriver graphDriver = inspectImage.getGraphDriver(); assertThat(graphDriver, notNullValue()); @@ -167,8 +184,10 @@ public void serder1_22_inspect_doc() throws IOException { assertThat(data, is(newGraphData)); assertThat(data.getDeviceId(), is("5")); - assertThat(data.getDeviceName(), is("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47")); - assertThat(data.getDeviceSize(), is("171798691840")); + assertThat(data.getDeviceName(), + is("docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47")); + assertThat(data.getDeviceSize(), + is("171798691840")); } @Test @@ -186,6 +205,5 @@ private void testOverlayNetworkRootDir() throws IOException { assertThat(graphDriver, equalTo(overlayGraphDriver)); assertThat(graphDriver.getName(), is("overlay")); assertThat(graphDriver.getData(), equalTo(overlayGraphData)); - } } From d05e38078117c8e1f20ab4ecc20575b64cb801bc Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 24 May 2016 14:19:28 -0600 Subject: [PATCH 051/780] Fixes Issue #584 Adds RootDir property to GraphData. This was seen on a CentOS system without aufs support. --- src/main/java/com/github/dockerjava/api/command/GraphData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/api/command/GraphData.java b/src/main/java/com/github/dockerjava/api/command/GraphData.java index 1aac8db84..5130fafc7 100644 --- a/src/main/java/com/github/dockerjava/api/command/GraphData.java +++ b/src/main/java/com/github/dockerjava/api/command/GraphData.java @@ -34,7 +34,7 @@ public String getRootDir() { } /** - * @see #deviceId + * @see #rootDir */ public GraphData withRootDir(String rootDir) { this.rootDir = rootDir; From 4ac56af0ee3fe02e4e50c30c05e435fbfe7bf9e8 Mon Sep 17 00:00:00 2001 From: Logan O'Sullivan Bruns Date: Tue, 24 May 2016 10:27:27 -0700 Subject: [PATCH 052/780] Always use HTTP to connect to proxy even when proxying HTTPS The intention of the current implementation seems to be to have the normal proxy settings accomplish the same results with docker-java as they would in java in general. I think the one accidental divergence from that is that for the HTTPS case setting https.{proxy,port} would normally still use HTTP but in this case the code is- I think unintentionally- switching to the proxy connection to HTTPS. This change makes it so it corresponds better with how the java proxy properties work as well. Even when proxying HTTPS the connection to the actually proxy is done over HTTP and it makes a CONNECT call to stream the HTTPS over. Most proxies are still used via HTTP and for better or worse this is the assumption built into the java proxy configuration which docker-java is using. The apache client is more flexible and perhaps the docker-java configuration should be too but I'd like to argue that until then that the docker-java match the behavior of java. Also this allows me to use docker-java through the corporate proxy when proxying HTTPS. Otherwise HTTP works but HTTPS fails since the proxy is not configured with HTTPS. --- .../com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index f64cf4e2b..5d489bbc5 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -231,7 +231,7 @@ private void configureProxy(ClientConfig clientConfig, String protocol) { String hostname = address.getHostName(); int port = address.getPort(); - clientConfig.property(ClientProperties.PROXY_URI, protocol + "://" + hostname + ":" + port); + clientConfig.property(ClientProperties.PROXY_URI, "http://" + hostname + ":" + port); String httpProxyUser = System.getProperty(protocol + ".proxyUser"); if (httpProxyUser != null) { From fac1ba22dc904f86774d16c56754a280a7ac4e97 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Thu, 2 Jun 2016 20:22:40 +0200 Subject: [PATCH 053/780] Add ignore unknown properties annotation --- src/main/java/com/github/dockerjava/api/command/GraphData.java | 3 +++ .../java/com/github/dockerjava/api/command/GraphDriver.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/command/GraphData.java b/src/main/java/com/github/dockerjava/api/command/GraphData.java index 5130fafc7..5a2944e0b 100644 --- a/src/main/java/com/github/dockerjava/api/command/GraphData.java +++ b/src/main/java/com/github/dockerjava/api/command/GraphData.java @@ -1,6 +1,8 @@ package com.github.dockerjava.api.command; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; + import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; @@ -11,6 +13,7 @@ * part of {@link GraphDriver} * @author Kanstantsin Shautsou */ +@JsonIgnoreProperties(ignoreUnknown = true) public class GraphData { @JsonProperty("RootDir") diff --git a/src/main/java/com/github/dockerjava/api/command/GraphDriver.java b/src/main/java/com/github/dockerjava/api/command/GraphDriver.java index 0d41364aa..1394e866e 100644 --- a/src/main/java/com/github/dockerjava/api/command/GraphDriver.java +++ b/src/main/java/com/github/dockerjava/api/command/GraphDriver.java @@ -1,6 +1,8 @@ package com.github.dockerjava.api.command; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; + import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; @@ -13,6 +15,7 @@ * @author Kanstantsin Shautsou * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_21} */ +@JsonIgnoreProperties(ignoreUnknown = true) public class GraphDriver { /** * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_21} From ad83c3adc410a901f25e22f20185dea5b0beb0cf Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 2 Jun 2016 20:24:31 +0200 Subject: [PATCH 054/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 429f4b275..c4a771d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Notes All changes +* [#585] (https://github.com/docker-java/docker-java/pull/585) Add RootDir property to GraphData * [#580] (https://github.com/docker-java/docker-java/pull/580) Fixes execute permissions for files when copied to container * [#579] (https://github.com/docker-java/docker-java/pull/579) Adds missing name filter evaluation to netty version of ListImagesCmdExec * [#578] (https://github.com/docker-java/docker-java/pull/578) Fix error during image build when Dockerfile in subdirectory of build context From 0c48b5fe0984388a27a65a3e4fbc2383a3821a30 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Thu, 2 Jun 2016 21:52:06 +0200 Subject: [PATCH 055/780] Add missing tests for netty impl --- .../exec/ConnectToNetworkCmdExecTest.java | 98 +++++++++++++++++++ .../DisconnectFromNetworkCmdExecTest.java | 82 ++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java create mode 100644 src/test/java/com/github/dockerjava/netty/exec/DisconnectFromNetworkCmdExecTest.java diff --git a/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java new file mode 100644 index 000000000..ee1a681b6 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java @@ -0,0 +1,98 @@ +package com.github.dockerjava.netty.exec; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.CreateNetworkResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.ContainerNetwork; +import com.github.dockerjava.api.model.Network; +import com.github.dockerjava.netty.AbstractNettyDockerClientTest; + +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 java.lang.reflect.Method; +import java.util.Collections; + +@Test(groups = "integration") +public class ConnectToNetworkCmdExecTest extends AbstractNettyDockerClientTest { + + @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 connectToNetwork() throws InterruptedException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + dockerClient.startContainerCmd(container.getId()).exec(); + + CreateNetworkResponse network = dockerClient.createNetworkCmd().withName("testNetwork").exec(); + + dockerClient.connectToNetworkCmd().withNetworkId(network.getId()).withContainerId(container.getId()).exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + + assertTrue(updatedNetwork.getContainers().containsKey(container.getId())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + assertNotNull(inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork")); + } + + @Test + public void connectToNetworkWithContainerNetwork() throws InterruptedException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + dockerClient.startContainerCmd(container.getId()).exec(); + + CreateNetworkResponse network = dockerClient.createNetworkCmd() + .withName("testNetwork") + .withIpam(new Network.Ipam() + .withConfig(new Network.Ipam.Config() + .withSubnet("10.100.100.0/24"))) + .exec(); + + dockerClient.connectToNetworkCmd() + .withNetworkId(network.getId()) + .withContainerId(container.getId()) + .withContainerNetwork(new ContainerNetwork() + .withAliases("testing") + .withIpamConfig(new ContainerNetwork.Ipam() + .withIpv4Address("10.100.100.100"))) + .exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + + Network.ContainerNetworkConfig containerNetworkConfig = updatedNetwork.getContainers().get(container.getId()); + assertNotNull(containerNetworkConfig); + assertEquals(containerNetworkConfig.getIpv4Address(), "10.100.100.100/24"); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork"); + assertNotNull(testNetwork); + assertEquals(testNetwork.getAliases(), Collections.singletonList("testing")); + assertEquals(testNetwork.getGateway(), "10.100.100.1"); + assertEquals(testNetwork.getIpAddress(), "10.100.100.100"); + } +} diff --git a/src/test/java/com/github/dockerjava/netty/exec/DisconnectFromNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/DisconnectFromNetworkCmdExecTest.java new file mode 100644 index 000000000..1f2563dec --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/exec/DisconnectFromNetworkCmdExecTest.java @@ -0,0 +1,82 @@ +package com.github.dockerjava.netty.exec; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.CreateNetworkResponse; +import com.github.dockerjava.api.model.Network; +import com.github.dockerjava.netty.AbstractNettyDockerClientTest; + +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 java.lang.reflect.Method; + +@Test(groups = "integration") +public class DisconnectFromNetworkCmdExecTest extends AbstractNettyDockerClientTest { + + @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 disconnectFromNetwork() throws InterruptedException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + dockerClient.startContainerCmd(container.getId()).exec(); + + CreateNetworkResponse network = dockerClient.createNetworkCmd().withName("testNetwork").exec(); + + dockerClient.connectToNetworkCmd().withNetworkId(network.getId()).withContainerId(container.getId()).exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + + assertTrue(updatedNetwork.getContainers().containsKey(container.getId())); + + dockerClient.disconnectFromNetworkCmd().withNetworkId(network.getId()).withContainerId(container.getId()).exec(); + + updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + + assertFalse(updatedNetwork.getContainers().containsKey(container.getId())); + } + + @Test + public void forceDisconnectFromNetwork() throws InterruptedException { + + CreateNetworkResponse network = dockerClient.createNetworkCmd().withName("testNetwork").exec(); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withNetworkMode("testNetwork") + .withCmd("sleep", "9999") + .exec(); + + dockerClient.startContainerCmd(container.getId()).exec(); + + dockerClient.disconnectFromNetworkCmd() + .withNetworkId(network.getId()) + .withContainerId(container.getId()) + .withForce(true) + .exec(); + + Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); + assertFalse(updatedNetwork.getContainers().containsKey(container.getId())); + } +} From 19acfcc8496ace6fe52c25d1359c7f891c01a04b Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 2 Jun 2016 21:54:43 +0200 Subject: [PATCH 056/780] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a771d25..7a6bae5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,8 @@ All changes * [#574] (https://github.com/docker-java/docker-java/pull/574) Fix for copyArchiveToContainerCmd bug * [#572] (https://github.com/docker-java/docker-java/pull/572) Inspect container command now shows sizes if requested * [#563] (https://github.com/docker-java/docker-java/pull/563) Fix memory leak in netty implementation of DockerCmdExecFactory -* [#550] (https://github.com/docker-java/docker-java/pull/550) Add ability to configure IPAM config for CreateNetworkCmd +* [#550] (https://github.com/docker-java/docker-java/pull/550) Add ability to configure IPAM config for CreateNetworkCmd +* [#484] (https://github.com/docker-java/docker-java/pull/484) Implement missing network api options for v1.22 Included in 3.0.0-RC5 From 7d1f64f7678b9857b3605558434c76d140aac172 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Thu, 2 Jun 2016 23:19:50 +0200 Subject: [PATCH 057/780] Fix issue #480 --- .../dockerjava/core/DockerClientConfig.java | 16 ++++++++++------ ...b.dockerjava.api.command.DockerCmdExecFactory | 1 - src/main/resources/docker-java.properties | 12 +++--------- .../dockerjava/core/DockerClientConfigTest.java | 10 +++------- 4 files changed, 16 insertions(+), 23 deletions(-) delete mode 100644 src/main/resources/META-INF/services/com.github.dockerjava.api.command.DockerCmdExecFactory diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index a03d6e086..31cfc0c58 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -109,14 +109,16 @@ private String checkDockerCertPath(boolean dockerTlsVerify, String dockerCertPat if (!certPath.exists()) { throw new DockerClientException( - "Certificate path (DOCKER_CERT_PATH) '" + dockerCertPath + "' doesn't exist."); + "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + dockerCertPath + + "' doesn't exist."); } if (certPath.isDirectory()) { return dockerCertPath; } else { throw new DockerClientException( - "Certificate path (DOCKER_CERT_PATH) '" + dockerCertPath + "' doesn't point to a directory."); + "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + dockerCertPath + + "' doesn't point to a directory."); } } } else { @@ -375,7 +377,6 @@ public final DockerClientConfigBuilder withDockerHost(String dockerHost) { return this; } - public final DockerClientConfigBuilder withApiVersion(RemoteApiVersion apiVersion) { this.apiVersion = apiVersion.getVersion(); return this; @@ -417,8 +418,12 @@ public final DockerClientConfigBuilder withDockerConfig(String dockerConfig) { } public final DockerClientConfigBuilder withDockerTlsVerify(String dockerTlsVerify) { - String trimmed = dockerTlsVerify.trim(); - this.dockerTlsVerify = "true".equalsIgnoreCase(trimmed) || "1".equals(trimmed); + if (dockerTlsVerify != null) { + String trimmed = dockerTlsVerify.trim(); + this.dockerTlsVerify = "true".equalsIgnoreCase(trimmed) || "1".equals(trimmed); + } else { + this.dockerTlsVerify = false; + } return this; } @@ -433,4 +438,3 @@ public DockerClientConfig build() { } } } - diff --git a/src/main/resources/META-INF/services/com.github.dockerjava.api.command.DockerCmdExecFactory b/src/main/resources/META-INF/services/com.github.dockerjava.api.command.DockerCmdExecFactory deleted file mode 100644 index f0686bc9f..000000000 --- a/src/main/resources/META-INF/services/com.github.dockerjava.api.command.DockerCmdExecFactory +++ /dev/null @@ -1 +0,0 @@ -com.github.dockerjava.jaxrs.DockerCmdExecFactoryImpl \ No newline at end of file diff --git a/src/main/resources/docker-java.properties b/src/main/resources/docker-java.properties index ea85f6c01..fc9209c97 100644 --- a/src/main/resources/docker-java.properties +++ b/src/main/resources/docker-java.properties @@ -1,13 +1,7 @@ -#docker.io.url=https://localhost:2376 -#docker.io.dockerCertPath=${user.home}/.docker -#docker.io.dockerCfgPath=${user.home}/.dockercfg -#docker.io.username=${user.name} -#docker.io.serverAddress=https://index.docker.io/v1/ -# -DOCKER_HOST=tcp://localhost:2376 -DOCKER_TLS_VERIFY=1 +DOCKER_HOST=unix:///var/run/docker.sock DOCKER_CONFIG=${user.home}/.docker -DOCKER_CERT_PATH=${user.home}/.docker/certs +#DOCKER_TLS_VERIFY=1 +#DOCKER_CERT_PATH=${user.home}/.docker/certs api.version= registry.url=https://index.docker.io/v1/ diff --git a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java index a363e12ec..ee679a0af 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java @@ -4,8 +4,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.core.Is.is; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertNull; import java.lang.reflect.Field; import java.net.URI; @@ -54,8 +53,6 @@ public void environmentDockerHost() throws Exception { // and it looks to be SSL disabled env.remove("DOCKER_CERT_PATH"); - - // given default cert path Properties systemProperties = new Properties(); systemProperties.setProperty("user.name", "someUserName"); @@ -82,7 +79,6 @@ public void environment() throws Exception { env.put(DockerClientConfig.DOCKER_CERT_PATH, dockerCertPath()); env.put(DockerClientConfig.DOCKER_TLS_VERIFY, "1"); - // when you build a config DockerClientConfig config = buildConfig(env, new Properties()); @@ -106,12 +102,12 @@ public void defaults() throws Exception { DockerClientConfig config = buildConfig(Collections. emptyMap(), systemProperties); // then the cert path is as expected - assertEquals(config.getDockerHost(), URI.create("tcp://localhost:2376")); + assertEquals(config.getDockerHost(), URI.create("unix:///var/run/docker.sock")); assertEquals(config.getRegistryUsername(), "someUserName"); assertEquals(config.getRegistryUrl(), AuthConfig.DEFAULT_SERVER_ADDRESS); assertEquals(config.getApiVersion(), RemoteApiVersion.unknown()); assertEquals(config.getDockerConfig(), homeDir() + "/.docker"); - assertEquals(config.getDockerCertPath(), homeDir() + "/.docker/certs"); + assertNull(config.getDockerCertPath()); } @Test From 94e860e574d7eebc64ee8e7fa4090d1d4c82d8a7 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Fri, 3 Jun 2016 21:12:42 +0200 Subject: [PATCH 058/780] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a6bae5af..ee0dae776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Notes * The configuration has been changed to better match the docker CLI configuration options. The properties file was renamed from `docker.io.properties` to `docker-java.properties`. See README.md for details. All changes - +* [#590] (https://github.com/docker-java/docker-java/pull/590) Fix default docker.properties to match with docker CLI defaults * [#585] (https://github.com/docker-java/docker-java/pull/585) Add RootDir property to GraphData * [#580] (https://github.com/docker-java/docker-java/pull/580) Fixes execute permissions for files when copied to container * [#579] (https://github.com/docker-java/docker-java/pull/579) Adds missing name filter evaluation to netty version of ListImagesCmdExec From fc38f319311821f790c1dcb8f1990676cc0e44f3 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 3 Jun 2016 21:53:02 +0200 Subject: [PATCH 059/780] [maven-release-plugin] prepare release docker-java-3.0.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9ee5cad51..3b77e6e98 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.0-SNAPSHOT + 3.0.0 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + docker-java-3.0.0 From 37afc15c5baeb5f479a56ca5e858bf230adb1102 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 3 Jun 2016 21:53:10 +0200 Subject: [PATCH 060/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3b77e6e98..bee178a6d 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.0 + 3.0.1-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - docker-java-3.0.0 + HEAD From 2f3d90c0a6bd564f8f8c53696198f9d74cdcd045 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Fri, 3 Jun 2016 22:02:41 +0200 Subject: [PATCH 061/780] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee0dae776..f55b2cd75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ Change Log === -3.0.0-SNAPSHOT +v3.0.0 --- Notes -* The upcoming release will contain multiple API breaking changes therefore the major version switch. It will support a subset of v.1.22 of the docker remote API. It also includes an experimental netty based implementation of `DockerCmdExecFactory` that probably will replace the current jersey/httpclient based one in a later release. +* The 3.0.0 release contains multiple API breaking changes compared to 2.x therefore the major version switch. It supports a subset of v.1.22 of the docker remote API. It also includes an experimental netty based implementation of `DockerCmdExecFactory` that probably will replace the current jersey/httpclient based one in a later release. Take a look at the [Wiki](https://github.com/docker-java/docker-java/wiki#intialize-docker-client-advanced) how to use it. * The configuration has been changed to better match the docker CLI configuration options. The properties file was renamed from `docker.io.properties` to `docker-java.properties`. See README.md for details. All changes From 9a59b10c5a28e6ae4d29af770f2412b1f88fc7dd Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Fri, 3 Jun 2016 22:54:02 +0200 Subject: [PATCH 062/780] Update README.md --- README.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f2135f61b..1b39ebab3 100644 --- a/README.md +++ b/README.md @@ -58,21 +58,12 @@ Run build without integration tests: ## Docker-Java maven dependencies ### Latest release version -Supports a subset of the Docker Remote API [v1.19](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.19.md), Docker Server version 1.7.x - - - com.github.docker-java - docker-java - 2.2.3 - - -### Latest release candidate Supports a subset of the Docker Remote API [v1.22](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.22.md), Docker Server version 1.10.x com.github.docker-java docker-java - 3.0.0-RC5 + 3.0.0 ### Latest development version @@ -83,7 +74,7 @@ You can find the latest development version including javadoc and source files o com.github.docker-java docker-java - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT From 0a1b34c3b2a201f82a16821e1f3f6ca0337854ca Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Sat, 4 Jun 2016 00:16:29 +0200 Subject: [PATCH 063/780] Update README.md --- README.md | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1b39ebab3..e47b6e5a4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") Developer forum for [docker-java](https://groups.google.com/forum/?#!forum/docker-java-dev "docker-java") +[Changelog](https://github.com/docker-java/docker-java/blob/master/CHANGELOG.md)
+[Wiki](https://github.com/docker-java/docker-java/wiki) + ## Build with Maven ###### Prerequisites: @@ -15,10 +18,6 @@ Developer forum for [docker-java](https://groups.google.com/forum/?#!forum/docke * Java 1.7 * Maven 3.0.5 -If you need SSL, then you'll need to put your `*.pem` file into `~/.docker/`, if you're using boot2docker, do this: - - $ ln -s /Users/alex.collins/.boot2docker/certs/boot2docker-vm .docker - Build and run integration tests as follows: $ mvn clean install @@ -27,35 +26,22 @@ If you do not have access to a Docker server or just want to execute the build q $ mvn clean install -DskipITs -By default Docker server is using UNIX sockets for communication with the Docker client, however docker-java -client uses TCP/IP to connect to the Docker server by default, so you will need to make sure that your Docker server is -listening on TCP port. To allow Docker server to use TCP add the following line to /etc/default/docker +By default the docker engine is using local UNIX sockets for communication with the docker CLI so docker-java +client also uses UNIX domain sockets to connect to the docker daemon by default. To make the docker daemon listening on a TCP (http/https) port you have to configure it by setting the DOCKER_OPTS environment variable to something like the following: DOCKER_OPTS="-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock" - -However you can force docker-java to use UNIX socket communication by configure the following (see [Configuration](.#Configuration) for details): - - DOCKER_HOST=unix:///var/run/docker.sock - DOCKER_TLS_VERIFY=0 - + More details about setting up Docker server can be found in official documentation: http://docs.docker.io/en/latest/use/basics/ -Now make sure that docker is up: +To force docker-java to use TCP (http) configure the following (see [Configuration](https://github.com/docker-java/docker-java#configuration) for details): - $ docker -H tcp://127.0.0.1:2375 version - - Client version: 0.8.0 - Go version (client): go1.2 - Git commit (client): cc3a8c8 - Server version: 1.2.0 - Git commit (server): fa7b24f - Go version (server): go1.3.1 - -Run build without integration tests: - - $ mvn clean install -DskipITs + DOCKER_HOST=tcp://127.0.0.1:2375 + +For secure tls (https) communication: -## Docker-Java maven dependencies + DOCKER_HOST=tcp://127.0.0.1:2376 + DOCKER_TLS_VERIFY=1 + DOCKER_CERT_PATH=/Users/marcus/.docker/machine/machines/docker-1.10.2 ### Latest release version Supports a subset of the Docker Remote API [v1.22](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.22.md), Docker Server version 1.10.x @@ -128,11 +114,11 @@ In your application, e.g. ##### System Properties: - java -Dregistry.username=dockeruser pkg.Main + java -DDOCKER_HOST=tcp://localhost:2375 -Dregistry.username=dockeruser pkg.Main ##### System Environment - export DOCKER_URL=tcp://localhost:2376 + export DOCKER_HOST=tcp://localhost:2376 export DOCKER_TLS_VERIFY=1 export DOCKER_CERT_PATH=/home/user/.docker/certs export DOCKER_CONFIG=/home/user/.docker From 3a3318282a4cf5d37b20b7d85ac00ef7549df84d Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Sun, 5 Jun 2016 15:30:00 +0200 Subject: [PATCH 064/780] Reorganize image build tests --- .../client/AbstractDockerClientTest.java | 2 - .../core/command/BuildImageCmdImplTest.java | 144 +++++----------- .../DockerfileAddMultipleFilesTest.java | 14 +- .../core/dockerfile/DockerfileTest.java | 49 ------ .../netty/exec/BuildImageCmdExecTest.java | 159 +++++++----------- .../ADD/file}/Dockerfile | 0 .../ADD/file}/testrun.sh | 0 .../ADD/fileInSubfolder}/Dockerfile | 0 .../ADD/fileInSubfolder}/files/testrun.sh | 0 .../ADD/files}/Dockerfile | 0 .../ADD/files}/src1 | 0 .../ADD/files}/src2 | 0 .../ADD/filesViaWildcard}/Dockerfile | 0 .../ADD/filesViaWildcard}/folder1/testrun.sh | 0 .../filesViaWildcard}/folder2/testinclude1.sh | 0 .../filesViaWildcard}/ignore/testinclude2.sh | 0 .../ADD/folder}/Dockerfile | 0 .../ADD/folder}/folderA/testAddFolder.sh | 0 .../ADD/url}/Dockerfile | 2 +- .../resources/buildTests/ADD/url/testrun.sh | 4 + .../{nginx => buildTests/AUTHOR}/Dockerfile | 2 +- .../ENV}/Dockerfile | 0 .../ENV}/subst-file-2-abc123.txt | 0 .../ENV}/subst-file-abc123.txt | 0 .../ENV}/testrun.sh | 0 .../FROM/privateRegistry}/Dockerfile | 0 .../ONBUILD/child}/Dockerfile | 0 .../ONBUILD/child}/testrun.sh | 0 .../ONBUILD/parent}/Dockerfile | 0 .../buildArgs}/Dockerfile | 0 .../dockerfileFolder/Dockerfile | 0 .../testrunFolder/testrun.sh | 0 .../DockerfileIgnored}/.dockerignore | 0 .../DockerfileIgnored}/Dockerfile | 0 .../DockerfileIgnored}/testrun.sh | 0 .../DockerfileNotIgnored}/.dockerignore | 0 .../DockerfileNotIgnored}/Dockerfile | 0 .../InvalidDockerignorePattern}/.dockerignore | 0 .../InvalidDockerignorePattern}/Dockerfile | 0 .../InvalidDockerignorePattern}/testrun.sh | 0 .../ValidDockerignorePattern}/.dockerignore | 0 .../ValidDockerignorePattern}/Dockerfile | 0 .../ValidDockerignorePattern}/a/a | 0 .../ValidDockerignorePattern}/a/b | 0 .../ValidDockerignorePattern}/a/c | 0 .../ValidDockerignorePattern}/a/d | 0 .../ValidDockerignorePattern}/testrun.sh | 0 src/test/resources/netcat/Dockerfile | 11 -- .../subdirectory/Dockerfile-nonstandard | 12 -- src/test/resources/testAddUrl/testrun.sh | 4 - src/test/resources/testEnv/Dockerfile | 10 -- .../resources/testEnv/subFolder/testrun.sh | 3 - 52 files changed, 111 insertions(+), 305 deletions(-) delete mode 100644 src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java rename src/test/resources/{testAddFile => buildTests/ADD/file}/Dockerfile (100%) rename src/test/resources/{testAddFile => buildTests/ADD/file}/testrun.sh (100%) rename src/test/resources/{testAddFileInSubfolder => buildTests/ADD/fileInSubfolder}/Dockerfile (100%) rename src/test/resources/{testAddFileInSubfolder => buildTests/ADD/fileInSubfolder}/files/testrun.sh (100%) rename src/test/resources/{testAddMultipleFiles => buildTests/ADD/files}/Dockerfile (100%) rename src/test/resources/{testAddMultipleFiles => buildTests/ADD/files}/src1 (100%) rename src/test/resources/{testAddMultipleFiles => buildTests/ADD/files}/src2 (100%) rename src/test/resources/{testAddFilesViaWildcard => buildTests/ADD/filesViaWildcard}/Dockerfile (100%) rename src/test/resources/{testAddFilesViaWildcard => buildTests/ADD/filesViaWildcard}/folder1/testrun.sh (100%) rename src/test/resources/{testAddFilesViaWildcard => buildTests/ADD/filesViaWildcard}/folder2/testinclude1.sh (100%) rename src/test/resources/{testAddFilesViaWildcard => buildTests/ADD/filesViaWildcard}/ignore/testinclude2.sh (100%) rename src/test/resources/{testAddFolder => buildTests/ADD/folder}/Dockerfile (100%) rename src/test/resources/{testAddFolder => buildTests/ADD/folder}/folderA/testAddFolder.sh (100%) rename src/test/resources/{testAddUrl => buildTests/ADD/url}/Dockerfile (71%) create mode 100755 src/test/resources/buildTests/ADD/url/testrun.sh rename src/test/resources/{nginx => buildTests/AUTHOR}/Dockerfile (81%) rename src/test/resources/{testENVSubstitution => buildTests/ENV}/Dockerfile (100%) rename src/test/resources/{testENVSubstitution => buildTests/ENV}/subst-file-2-abc123.txt (100%) rename src/test/resources/{testENVSubstitution => buildTests/ENV}/subst-file-abc123.txt (100%) rename src/test/resources/{testENVSubstitution => buildTests/ENV}/testrun.sh (100%) rename src/test/resources/{testBuildFromPrivateRegistry => buildTests/FROM/privateRegistry}/Dockerfile (100%) rename src/test/resources/{testAddOnBuild/test => buildTests/ONBUILD/child}/Dockerfile (100%) rename src/test/resources/{testAddOnBuild/test => buildTests/ONBUILD/child}/testrun.sh (100%) rename src/test/resources/{testAddOnBuild/onbuild => buildTests/ONBUILD/parent}/Dockerfile (100%) rename src/test/resources/{testBuildArgs => buildTests/buildArgs}/Dockerfile (100%) rename src/test/resources/{testDockerfileNotInBaseDirectory => buildTests/dockerfileNotInBaseDirectory}/dockerfileFolder/Dockerfile (100%) rename src/test/resources/{testDockerfileNotInBaseDirectory => buildTests/dockerfileNotInBaseDirectory}/testrunFolder/testrun.sh (100%) rename src/test/resources/{testDockerfileIgnored => buildTests/dockerignore/DockerfileIgnored}/.dockerignore (100%) rename src/test/resources/{testDockerfileIgnored => buildTests/dockerignore/DockerfileIgnored}/Dockerfile (100%) rename src/test/resources/{testDockerfileIgnored => buildTests/dockerignore/DockerfileIgnored}/testrun.sh (100%) rename src/test/resources/{testDockerfileNotIgnored => buildTests/dockerignore/DockerfileNotIgnored}/.dockerignore (100%) rename src/test/resources/{testDockerfileNotIgnored => buildTests/dockerignore/DockerfileNotIgnored}/Dockerfile (100%) rename src/test/resources/{testInvalidDockerignorePattern => buildTests/dockerignore/InvalidDockerignorePattern}/.dockerignore (100%) rename src/test/resources/{testInvalidDockerignorePattern => buildTests/dockerignore/InvalidDockerignorePattern}/Dockerfile (100%) rename src/test/resources/{testInvalidDockerignorePattern => buildTests/dockerignore/InvalidDockerignorePattern}/testrun.sh (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/.dockerignore (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/Dockerfile (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/a/a (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/a/b (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/a/c (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/a/d (100%) rename src/test/resources/{testDockerignore => buildTests/dockerignore/ValidDockerignorePattern}/testrun.sh (100%) delete mode 100644 src/test/resources/netcat/Dockerfile delete mode 100644 src/test/resources/nonstandard/subdirectory/Dockerfile-nonstandard delete mode 100755 src/test/resources/testAddUrl/testrun.sh delete mode 100644 src/test/resources/testEnv/Dockerfile delete mode 100755 src/test/resources/testEnv/subFolder/testrun.sh diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index 4c8750ecc..231e709c1 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -228,8 +228,6 @@ public static class LogContainerTestCallback extends LogContainerResultCallback @Override public void onNext(Frame frame) { log.append(new String(frame.getPayload())); - System.err.println("LogContainerTestCallback: " + log.toString()); - // super.onNext(frame); } @Override diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index 950b80a24..31f3c3045 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import java.io.File; @@ -26,7 +25,6 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.command.InspectImageResponse; import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.model.AuthConfig; @@ -61,10 +59,9 @@ public void afterMethod(ITestResult result) { } @Test - public void testNginxDockerfileBuilder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); + public void author() throws Exception { - String imageId = buildImage(baseDir); + String imageId = buildImage(fileFromBuildTestResource("AUTHOR")); InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); assertThat(inspectImageResponse, not(nullValue())); @@ -73,27 +70,9 @@ public void testNginxDockerfileBuilder() throws Exception { assertThat(inspectImageResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); } - @Test(groups = "ignoreInCircleCi") - public void testNonstandard1() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile()); - - buildImage(baseDir); - } - - @Test(groups = "ignoreInCircleCi") - public void testNonstandard2() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nonstandard").getFile()); - File dockerFile = new File(Thread.currentThread().getContextClassLoader() - .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile()); - - dockerClient.buildImageCmd().withBaseDirectory(baseDir).withDockerfile(dockerFile).withNoCache(true) - .exec(new BuildImageResultCallback()).awaitImageId(); - } - @Test - public void testDockerBuilderFromTar() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile()); + public void buildImageFromTar() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/file"); Collection files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString()); String response = dockerfileBuild(new FileInputStream(tarFile)); @@ -101,54 +80,45 @@ public void testDockerBuilderFromTar() throws Exception { } @Test - public void testDockerBuildWithOnBuild() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddOnBuild/onbuild") - .getFile()); + public void onBuild() throws Exception { + File baseDir = fileFromBuildTestResource("ONBUILD/parent"); + dockerClient.buildImageCmd(baseDir).withNoCache(true).withTag("docker-java-onbuild") .exec(new BuildImageResultCallback()).awaitImageId(); - baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddOnBuild/test").getFile()); + baseDir = fileFromBuildTestResource("ONBUILD/child"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("Successfully executed testrun.sh")); } @Test - public void testDockerBuilderAddUrl() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddUrl").getFile()); + public void addUrl() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/url"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Docker")); + assertThat(response, containsString("Example Domain")); } @Test - public void testDockerBuilderAddFileInSubfolder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFileInSubfolder") - .getFile()); + public void addFileInSubfolder() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/fileInSubfolder"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("Successfully executed testrun.sh")); } @Test - public void testDockerBuilderAddFilesViaWildcard() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFilesViaWildcard") - .getFile()); + public void addFilesViaWildcard() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/filesViaWildcard"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("Successfully executed testinclude1.sh")); assertThat(response, not(containsString("Successfully executed testinclude2.sh"))); } @Test - public void testDockerBuilderAddFolder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile()); + public void addFolder() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/folder"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("Successfully executed testAddFolder.sh")); } - @Test - public void testDockerBuilderEnv() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testEnv").getFile()); - String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Successfully executed testrun.sh")); - } - private String dockerfileBuild(InputStream tarInputStream) throws Exception { return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream)); @@ -175,80 +145,42 @@ private String execBuild(BuildImageCmd buildImageCmd) throws Exception { } @Test(expectedExceptions = {DockerClientException.class}) - public void testDockerfileIgnored() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileIgnored") - .getFile()); + public void dockerignoreDockerfileIgnored() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/DockerfileIgnored"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } @Test - public void testDockerfileNotIgnored() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileNotIgnored") - .getFile()); + public void dockerignoreDockerfileNotIgnored() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/DockerfileNotIgnored"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } @Test(expectedExceptions = {DockerClientException.class}) - public void testInvalidDockerIgnorePattern() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("testInvalidDockerignorePattern").getFile()); + public void dockerignoreInvalidDockerIgnorePattern() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/InvalidDockerignorePattern"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } - @Test(groups = "ignoreInCircleCi") - public void testDockerIgnore() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerignore") - .getFile()); + @Test() + public void dockerignoreValidDockerIgnorePattern() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/ValidDockerignorePattern"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("/tmp/a/a /tmp/a/c /tmp/a/d")); } @Test - public void testNetCatDockerfileBuilder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); - - String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()) - .awaitImageId(); - - assertNotNull(imageId, "Not successful in build"); - - InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); - assertThat(inspectImageResponse, not(nullValue())); - assertThat(inspectImageResponse.getId(), not(nullValue())); - LOG.info("Image Inspect: {}", inspectImageResponse.toString()); - - CreateContainerResponse container = dockerClient.createContainerCmd(inspectImageResponse.getId()).exec(); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainerCmd(container.getId()).exec(); - - InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - - assertThat(inspectContainerResponse.getId(), notNullValue()); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts(), notNullValue()); - - // No use as such if not running on the server - // for (Ports.Port p : inspectContainerResponse.getNetworkSettings().getPorts().getAllPorts()) { - // int port = Integer.valueOf(p.getHostPort()); - // LOG.info("Checking port {} is open", port); - // assertThat(available(port), is(false)); - // } - dockerClient.stopContainerCmd(container.getId()).withTimeout(0).exec(); - - } - - @Test - public void testAddAndCopySubstitution() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testENVSubstitution") - .getFile()); + public void env() throws Exception { + File baseDir = fileFromBuildTestResource("ENV"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("testENVSubstitution successfully completed")); } @Test - public void testBuildFromPrivateRegistry() throws Exception { + public void fromPrivateRegistry() throws Exception { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("privateRegistry").getFile()); String imageId = buildImage(baseDir); @@ -289,8 +221,7 @@ public void testBuildFromPrivateRegistry() throws Exception { dockerClient.removeImageCmd("localhost:5000/testuser/busybox").withForce(true).exec(); - baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testBuildFromPrivateRegistry") - .getFile()); + baseDir = fileFromBuildTestResource("FROM/privateRegistry"); AuthConfigurations authConfigurations = new AuthConfigurations(); authConfigurations.addConfig(authConfig); @@ -305,8 +236,8 @@ public void testBuildFromPrivateRegistry() throws Exception { } @Test - public void testBuildArgs() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testBuildArgs").getFile()); + public void buildArgs() throws Exception { + File baseDir = fileFromBuildTestResource("buildArgs"); String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).withBuildArg("testArg", "abc") .exec(new BuildImageResultCallback()) @@ -319,9 +250,9 @@ public void testBuildArgs() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } - public void testDockerfileNotInBaseDirectory() throws Exception { - File baseDirectory = getResource("testDockerfileNotInBaseDirectory"); - File dockerfile = getResource("testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); + public void dockerfileNotInBaseDirectory() throws Exception { + File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); + File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); BuildImageCmd command = dockerClient.buildImageCmd() .withBaseDirectory(baseDirectory) .withDockerfile(dockerfile); @@ -331,7 +262,8 @@ public void testDockerfileNotInBaseDirectory() throws Exception { assertThat(response, containsString("Successfully executed testrun.sh")); } - private File getResource(String path) { - return new File(Thread.currentThread().getContextClassLoader().getResource(path).getFile()); + private File fileFromBuildTestResource(String resource) { + return new File(Thread.currentThread().getContextClassLoader() + .getResource("buildTests/" + resource).getFile()); } } diff --git a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java index 8997a6d80..164246957 100644 --- a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java +++ b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java @@ -1,7 +1,7 @@ package com.github.dockerjava.core.dockerfile; import com.google.common.base.Function; -import junit.framework.TestCase; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; @@ -14,7 +14,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; -public class DockerfileAddMultipleFilesTest extends TestCase { +public class DockerfileAddMultipleFilesTest { private static final Logger log = LoggerFactory.getLogger(DockerfileAddMultipleFilesTest.class); @@ -26,13 +26,17 @@ public String apply(File file) { }; @Test - public void testAddMultipleFiles() throws IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddMultipleFiles") - .getFile()); + public void addFiles() throws IOException { + File baseDir = fileFromBuildTestResource("ADD/files"); Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile"), baseDir); Dockerfile.ScannedResult result = dockerfile.parse(); Collection filesToAdd = transform(result.filesToAdd, TO_FILE_NAMES); assertThat(filesToAdd, containsInAnyOrder("Dockerfile", "src1", "src2")); } + + private File fileFromBuildTestResource(String resource) { + return new File(Thread.currentThread().getContextClassLoader() + .getResource("buildTests/" + resource).getFile()); + } } diff --git a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java deleted file mode 100644 index 390bcf647..000000000 --- a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.dockerjava.core.dockerfile; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import junit.framework.TestCase; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.Test; - -public class DockerfileTest extends TestCase { - - private static final Logger log = LoggerFactory.getLogger(DockerfileTest.class); - - @Test - public void testAllItems() throws IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); - - File root = baseDir.getParentFile(); - - Map dockerfiles = new HashMap(); - Map results = new HashMap(); - - for (File child : root.listFiles()) { - if (new File(child, "Dockerfile").exists()) { - Dockerfile dockerfile = new Dockerfile(new File(child, "Dockerfile"), baseDir); - dockerfiles.put(child.getName(), dockerfile); - } - } - - for (String name : dockerfiles.keySet()) { - log.info("Scanning {}", name); - try { - results.put(name, dockerfiles.get(name).parse()); - } catch (Exception ex) { - log.error("Error in {}", name, ex); - } - - } - - for (String name : results.keySet()) { - log.info("Name: {} = {}", name, results.get(name)); - } - } - -} diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index 92975f38f..1474ef25f 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import java.io.File; @@ -65,10 +64,9 @@ public void afterMethod(ITestResult result) { } @Test - public void testNginxDockerfileBuilder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); + public void author() throws Exception { - String imageId = buildImage(baseDir); + String imageId = buildImage(fileFromBuildTestResource("AUTHOR")); InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); assertThat(inspectImageResponse, not(nullValue())); @@ -77,27 +75,9 @@ public void testNginxDockerfileBuilder() throws Exception { assertThat(inspectImageResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); } - @Test(groups = "ignoreInCircleCi") - public void testNonstandard1() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile()); - - buildImage(baseDir); - } - - @Test(groups = "ignoreInCircleCi") - public void testNonstandard2() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nonstandard").getFile()); - File dockerFile = new File(Thread.currentThread().getContextClassLoader() - .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile()); - - dockerClient.buildImageCmd().withBaseDirectory(baseDir).withDockerfile(dockerFile).withNoCache(true) - .exec(new BuildImageResultCallback()).awaitImageId(); - } - @Test - public void testDockerBuilderFromTar() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile()); + public void buildImageFromTar() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/file"); Collection files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString()); String response = dockerfileBuild(new FileInputStream(tarFile)); @@ -105,41 +85,43 @@ public void testDockerBuilderFromTar() throws Exception { } @Test - public void testDockerBuilderAddUrl() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddUrl").getFile()); + public void onBuild() throws Exception { + File baseDir = fileFromBuildTestResource("ONBUILD/parent"); + + dockerClient.buildImageCmd(baseDir).withNoCache(true).withTag("docker-java-onbuild") + .exec(new BuildImageResultCallback()).awaitImageId(); + baseDir = fileFromBuildTestResource("ONBUILD/child"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Docker")); + assertThat(response, containsString("Successfully executed testrun.sh")); } @Test - public void testDockerBuilderAddFileInSubfolder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFileInSubfolder") - .getFile()); + public void addUrl() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/url"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Successfully executed testrun.sh")); + assertThat(response, containsString("Example Domain")); } @Test - public void testDockerBuilderAddFilesViaWildcard() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFilesViaWildcard") - .getFile()); + public void addFileInSubfolder() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/fileInSubfolder"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Successfully executed testinclude1.sh")); - assertThat(response, not(containsString("Successfully executed testinclude2.sh"))); + assertThat(response, containsString("Successfully executed testrun.sh")); } @Test - public void testDockerBuilderAddFolder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile()); + public void addFilesViaWildcard() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/filesViaWildcard"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Successfully executed testAddFolder.sh")); + assertThat(response, containsString("Successfully executed testinclude1.sh")); + assertThat(response, not(containsString("Successfully executed testinclude2.sh"))); } @Test - public void testDockerBuilderEnv() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testEnv").getFile()); + public void addFolder() throws Exception { + File baseDir = fileFromBuildTestResource("ADD/folder"); String response = dockerfileBuild(baseDir); - assertThat(response, containsString("Successfully executed testrun.sh")); + assertThat(response, containsString("Successfully executed testAddFolder.sh")); } private String dockerfileBuild(InputStream tarInputStream) throws Exception { @@ -168,80 +150,42 @@ private String execBuild(BuildImageCmd buildImageCmd) throws Exception { } @Test(expectedExceptions = {DockerClientException.class}) - public void testDockerfileIgnored() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileIgnored") - .getFile()); + public void dockerignoreDockerfileIgnored() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/DockerfileIgnored"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } @Test - public void testDockerfileNotIgnored() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileNotIgnored") - .getFile()); + public void dockerignoreDockerfileNotIgnored() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/DockerfileNotIgnored"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } @Test(expectedExceptions = {DockerClientException.class}) - public void testInvalidDockerIgnorePattern() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("testInvalidDockerignorePattern").getFile()); + public void dockerignoreInvalidDockerIgnorePattern() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/InvalidDockerignorePattern"); dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId(); } - @Test(groups = "ignoreInCircleCi") - public void testDockerIgnore() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerignore") - .getFile()); + @Test() + public void dockerignoreValidDockerIgnorePattern() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/ValidDockerignorePattern"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("/tmp/a/a /tmp/a/c /tmp/a/d")); } @Test - public void testNetCatDockerfileBuilder() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); - - String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()) - .awaitImageId(); - - assertNotNull(imageId, "Not successful in build"); - - InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); - assertThat(inspectImageResponse, not(nullValue())); - assertThat(inspectImageResponse.getId(), not(nullValue())); - LOG.info("Image Inspect: {}", inspectImageResponse.toString()); - - CreateContainerResponse container = dockerClient.createContainerCmd(inspectImageResponse.getId()).exec(); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainerCmd(container.getId()).exec(); - - InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - - assertThat(inspectContainerResponse.getId(), notNullValue()); - assertThat(inspectContainerResponse.getNetworkSettings().getPorts(), notNullValue()); - - // No use as such if not running on the server - // for (Ports.Port p : inspectContainerResponse.getNetworkSettings().getPorts().getAllPorts()) { - // int port = Integer.valueOf(p.getHostPort()); - // LOG.info("Checking port {} is open", port); - // assertThat(available(port), is(false)); - // } - dockerClient.stopContainerCmd(container.getId()).withTimeout(0).exec(); - - } - - @Test - public void testAddAndCopySubstitution() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testENVSubstitution") - .getFile()); + public void env() throws Exception { + File baseDir = fileFromBuildTestResource("ENV"); String response = dockerfileBuild(baseDir); assertThat(response, containsString("testENVSubstitution successfully completed")); } @Test - public void testBuildFromPrivateRegistry() throws Exception { + public void fromPrivateRegistry() throws Exception { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("privateRegistry").getFile()); String imageId = buildImage(baseDir); @@ -282,17 +226,13 @@ public void testBuildFromPrivateRegistry() throws Exception { dockerClient.removeImageCmd("localhost:5000/testuser/busybox").withForce(true).exec(); - baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testBuildFromPrivateRegistry") - .getFile()); + baseDir = fileFromBuildTestResource("FROM/privateRegistry"); AuthConfigurations authConfigurations = new AuthConfigurations(); authConfigurations.addConfig(authConfig); - imageId = dockerClient.buildImageCmd(baseDir) - .withNoCache(true) - .withBuildAuthConfigs(authConfigurations) - .exec(new BuildImageResultCallback()) - .awaitImageId(); + imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).withBuildAuthConfigs(authConfigurations) + .exec(new BuildImageResultCallback()).awaitImageId(); inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); assertThat(inspectImageResponse, not(nullValue())); @@ -301,8 +241,8 @@ public void testBuildFromPrivateRegistry() throws Exception { } @Test - public void testBuildArgs() throws Exception { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testBuildArgs").getFile()); + public void buildArgs() throws Exception { + File baseDir = fileFromBuildTestResource("buildArgs"); String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).withBuildArg("testArg", "abc") .exec(new BuildImageResultCallback()) @@ -314,4 +254,21 @@ public void testBuildArgs() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + + public void dockerfileNotInBaseDirectory() throws Exception { + File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); + File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); + BuildImageCmd command = dockerClient.buildImageCmd() + .withBaseDirectory(baseDirectory) + .withDockerfile(dockerfile); + + String response = execBuild(command); + + assertThat(response, containsString("Successfully executed testrun.sh")); + } + + private File fileFromBuildTestResource(String resource) { + return new File(Thread.currentThread().getContextClassLoader() + .getResource("buildTests/" + resource).getFile()); + } } diff --git a/src/test/resources/testAddFile/Dockerfile b/src/test/resources/buildTests/ADD/file/Dockerfile similarity index 100% rename from src/test/resources/testAddFile/Dockerfile rename to src/test/resources/buildTests/ADD/file/Dockerfile diff --git a/src/test/resources/testAddFile/testrun.sh b/src/test/resources/buildTests/ADD/file/testrun.sh similarity index 100% rename from src/test/resources/testAddFile/testrun.sh rename to src/test/resources/buildTests/ADD/file/testrun.sh diff --git a/src/test/resources/testAddFileInSubfolder/Dockerfile b/src/test/resources/buildTests/ADD/fileInSubfolder/Dockerfile similarity index 100% rename from src/test/resources/testAddFileInSubfolder/Dockerfile rename to src/test/resources/buildTests/ADD/fileInSubfolder/Dockerfile diff --git a/src/test/resources/testAddFileInSubfolder/files/testrun.sh b/src/test/resources/buildTests/ADD/fileInSubfolder/files/testrun.sh similarity index 100% rename from src/test/resources/testAddFileInSubfolder/files/testrun.sh rename to src/test/resources/buildTests/ADD/fileInSubfolder/files/testrun.sh diff --git a/src/test/resources/testAddMultipleFiles/Dockerfile b/src/test/resources/buildTests/ADD/files/Dockerfile similarity index 100% rename from src/test/resources/testAddMultipleFiles/Dockerfile rename to src/test/resources/buildTests/ADD/files/Dockerfile diff --git a/src/test/resources/testAddMultipleFiles/src1 b/src/test/resources/buildTests/ADD/files/src1 similarity index 100% rename from src/test/resources/testAddMultipleFiles/src1 rename to src/test/resources/buildTests/ADD/files/src1 diff --git a/src/test/resources/testAddMultipleFiles/src2 b/src/test/resources/buildTests/ADD/files/src2 similarity index 100% rename from src/test/resources/testAddMultipleFiles/src2 rename to src/test/resources/buildTests/ADD/files/src2 diff --git a/src/test/resources/testAddFilesViaWildcard/Dockerfile b/src/test/resources/buildTests/ADD/filesViaWildcard/Dockerfile similarity index 100% rename from src/test/resources/testAddFilesViaWildcard/Dockerfile rename to src/test/resources/buildTests/ADD/filesViaWildcard/Dockerfile diff --git a/src/test/resources/testAddFilesViaWildcard/folder1/testrun.sh b/src/test/resources/buildTests/ADD/filesViaWildcard/folder1/testrun.sh similarity index 100% rename from src/test/resources/testAddFilesViaWildcard/folder1/testrun.sh rename to src/test/resources/buildTests/ADD/filesViaWildcard/folder1/testrun.sh diff --git a/src/test/resources/testAddFilesViaWildcard/folder2/testinclude1.sh b/src/test/resources/buildTests/ADD/filesViaWildcard/folder2/testinclude1.sh similarity index 100% rename from src/test/resources/testAddFilesViaWildcard/folder2/testinclude1.sh rename to src/test/resources/buildTests/ADD/filesViaWildcard/folder2/testinclude1.sh diff --git a/src/test/resources/testAddFilesViaWildcard/ignore/testinclude2.sh b/src/test/resources/buildTests/ADD/filesViaWildcard/ignore/testinclude2.sh similarity index 100% rename from src/test/resources/testAddFilesViaWildcard/ignore/testinclude2.sh rename to src/test/resources/buildTests/ADD/filesViaWildcard/ignore/testinclude2.sh diff --git a/src/test/resources/testAddFolder/Dockerfile b/src/test/resources/buildTests/ADD/folder/Dockerfile similarity index 100% rename from src/test/resources/testAddFolder/Dockerfile rename to src/test/resources/buildTests/ADD/folder/Dockerfile diff --git a/src/test/resources/testAddFolder/folderA/testAddFolder.sh b/src/test/resources/buildTests/ADD/folder/folderA/testAddFolder.sh similarity index 100% rename from src/test/resources/testAddFolder/folderA/testAddFolder.sh rename to src/test/resources/buildTests/ADD/folder/folderA/testAddFolder.sh diff --git a/src/test/resources/testAddUrl/Dockerfile b/src/test/resources/buildTests/ADD/url/Dockerfile similarity index 71% rename from src/test/resources/testAddUrl/Dockerfile rename to src/test/resources/buildTests/ADD/url/Dockerfile index d9a0676d4..2b10c34e5 100644 --- a/src/test/resources/testAddUrl/Dockerfile +++ b/src/test/resources/buildTests/ADD/url/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:latest # Copy testrun.sh files into the container -ADD https://hub.docker.com/r/marcuslinke/busybox/ /tmp/docker_home.html +ADD http://www.example.com/index.html /tmp/some.html ADD ./testrun.sh /tmp/ RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh diff --git a/src/test/resources/buildTests/ADD/url/testrun.sh b/src/test/resources/buildTests/ADD/url/testrun.sh new file mode 100755 index 000000000..4d240d5ae --- /dev/null +++ b/src/test/resources/buildTests/ADD/url/testrun.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cat /tmp/some.html + diff --git a/src/test/resources/nginx/Dockerfile b/src/test/resources/buildTests/AUTHOR/Dockerfile similarity index 81% rename from src/test/resources/nginx/Dockerfile rename to src/test/resources/buildTests/AUTHOR/Dockerfile index 2d0fa24cb..32ffcedc7 100644 --- a/src/test/resources/nginx/Dockerfile +++ b/src/test/resources/buildTests/AUTHOR/Dockerfile @@ -9,4 +9,4 @@ MAINTAINER Guillaume J. Charmes "guillaume@dotcloud.com" RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list RUN apt-get update -RUN apt-get install -y inotify-tools nginx apache2 openssh-server \ No newline at end of file +RUN apt-get install -y nginx \ No newline at end of file diff --git a/src/test/resources/testENVSubstitution/Dockerfile b/src/test/resources/buildTests/ENV/Dockerfile similarity index 100% rename from src/test/resources/testENVSubstitution/Dockerfile rename to src/test/resources/buildTests/ENV/Dockerfile diff --git a/src/test/resources/testENVSubstitution/subst-file-2-abc123.txt b/src/test/resources/buildTests/ENV/subst-file-2-abc123.txt similarity index 100% rename from src/test/resources/testENVSubstitution/subst-file-2-abc123.txt rename to src/test/resources/buildTests/ENV/subst-file-2-abc123.txt diff --git a/src/test/resources/testENVSubstitution/subst-file-abc123.txt b/src/test/resources/buildTests/ENV/subst-file-abc123.txt similarity index 100% rename from src/test/resources/testENVSubstitution/subst-file-abc123.txt rename to src/test/resources/buildTests/ENV/subst-file-abc123.txt diff --git a/src/test/resources/testENVSubstitution/testrun.sh b/src/test/resources/buildTests/ENV/testrun.sh similarity index 100% rename from src/test/resources/testENVSubstitution/testrun.sh rename to src/test/resources/buildTests/ENV/testrun.sh diff --git a/src/test/resources/testBuildFromPrivateRegistry/Dockerfile b/src/test/resources/buildTests/FROM/privateRegistry/Dockerfile similarity index 100% rename from src/test/resources/testBuildFromPrivateRegistry/Dockerfile rename to src/test/resources/buildTests/FROM/privateRegistry/Dockerfile diff --git a/src/test/resources/testAddOnBuild/test/Dockerfile b/src/test/resources/buildTests/ONBUILD/child/Dockerfile similarity index 100% rename from src/test/resources/testAddOnBuild/test/Dockerfile rename to src/test/resources/buildTests/ONBUILD/child/Dockerfile diff --git a/src/test/resources/testAddOnBuild/test/testrun.sh b/src/test/resources/buildTests/ONBUILD/child/testrun.sh similarity index 100% rename from src/test/resources/testAddOnBuild/test/testrun.sh rename to src/test/resources/buildTests/ONBUILD/child/testrun.sh diff --git a/src/test/resources/testAddOnBuild/onbuild/Dockerfile b/src/test/resources/buildTests/ONBUILD/parent/Dockerfile similarity index 100% rename from src/test/resources/testAddOnBuild/onbuild/Dockerfile rename to src/test/resources/buildTests/ONBUILD/parent/Dockerfile diff --git a/src/test/resources/testBuildArgs/Dockerfile b/src/test/resources/buildTests/buildArgs/Dockerfile similarity index 100% rename from src/test/resources/testBuildArgs/Dockerfile rename to src/test/resources/buildTests/buildArgs/Dockerfile diff --git a/src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile b/src/test/resources/buildTests/dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile similarity index 100% rename from src/test/resources/testDockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile rename to src/test/resources/buildTests/dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile diff --git a/src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh b/src/test/resources/buildTests/dockerfileNotInBaseDirectory/testrunFolder/testrun.sh similarity index 100% rename from src/test/resources/testDockerfileNotInBaseDirectory/testrunFolder/testrun.sh rename to src/test/resources/buildTests/dockerfileNotInBaseDirectory/testrunFolder/testrun.sh diff --git a/src/test/resources/testDockerfileIgnored/.dockerignore b/src/test/resources/buildTests/dockerignore/DockerfileIgnored/.dockerignore similarity index 100% rename from src/test/resources/testDockerfileIgnored/.dockerignore rename to src/test/resources/buildTests/dockerignore/DockerfileIgnored/.dockerignore diff --git a/src/test/resources/testDockerfileIgnored/Dockerfile b/src/test/resources/buildTests/dockerignore/DockerfileIgnored/Dockerfile similarity index 100% rename from src/test/resources/testDockerfileIgnored/Dockerfile rename to src/test/resources/buildTests/dockerignore/DockerfileIgnored/Dockerfile diff --git a/src/test/resources/testDockerfileIgnored/testrun.sh b/src/test/resources/buildTests/dockerignore/DockerfileIgnored/testrun.sh similarity index 100% rename from src/test/resources/testDockerfileIgnored/testrun.sh rename to src/test/resources/buildTests/dockerignore/DockerfileIgnored/testrun.sh diff --git a/src/test/resources/testDockerfileNotIgnored/.dockerignore b/src/test/resources/buildTests/dockerignore/DockerfileNotIgnored/.dockerignore similarity index 100% rename from src/test/resources/testDockerfileNotIgnored/.dockerignore rename to src/test/resources/buildTests/dockerignore/DockerfileNotIgnored/.dockerignore diff --git a/src/test/resources/testDockerfileNotIgnored/Dockerfile b/src/test/resources/buildTests/dockerignore/DockerfileNotIgnored/Dockerfile similarity index 100% rename from src/test/resources/testDockerfileNotIgnored/Dockerfile rename to src/test/resources/buildTests/dockerignore/DockerfileNotIgnored/Dockerfile diff --git a/src/test/resources/testInvalidDockerignorePattern/.dockerignore b/src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/.dockerignore similarity index 100% rename from src/test/resources/testInvalidDockerignorePattern/.dockerignore rename to src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/.dockerignore diff --git a/src/test/resources/testInvalidDockerignorePattern/Dockerfile b/src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/Dockerfile similarity index 100% rename from src/test/resources/testInvalidDockerignorePattern/Dockerfile rename to src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/Dockerfile diff --git a/src/test/resources/testInvalidDockerignorePattern/testrun.sh b/src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/testrun.sh similarity index 100% rename from src/test/resources/testInvalidDockerignorePattern/testrun.sh rename to src/test/resources/buildTests/dockerignore/InvalidDockerignorePattern/testrun.sh diff --git a/src/test/resources/testDockerignore/.dockerignore b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/.dockerignore similarity index 100% rename from src/test/resources/testDockerignore/.dockerignore rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/.dockerignore diff --git a/src/test/resources/testDockerignore/Dockerfile b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/Dockerfile similarity index 100% rename from src/test/resources/testDockerignore/Dockerfile rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/Dockerfile diff --git a/src/test/resources/testDockerignore/a/a b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/a similarity index 100% rename from src/test/resources/testDockerignore/a/a rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/a diff --git a/src/test/resources/testDockerignore/a/b b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/b similarity index 100% rename from src/test/resources/testDockerignore/a/b rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/b diff --git a/src/test/resources/testDockerignore/a/c b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/c similarity index 100% rename from src/test/resources/testDockerignore/a/c rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/c diff --git a/src/test/resources/testDockerignore/a/d b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/d similarity index 100% rename from src/test/resources/testDockerignore/a/d rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/a/d diff --git a/src/test/resources/testDockerignore/testrun.sh b/src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/testrun.sh similarity index 100% rename from src/test/resources/testDockerignore/testrun.sh rename to src/test/resources/buildTests/dockerignore/ValidDockerignorePattern/testrun.sh diff --git a/src/test/resources/netcat/Dockerfile b/src/test/resources/netcat/Dockerfile deleted file mode 100644 index 1974f1063..000000000 --- a/src/test/resources/netcat/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -# Firefox over VNC -# -# VERSION 0.3 - -FROM ubuntu:latest - -#install netcat -RUN apt-get install -y netcat - -EXPOSE 6900 -CMD ["nc", "-l", "6900"] \ No newline at end of file diff --git a/src/test/resources/nonstandard/subdirectory/Dockerfile-nonstandard b/src/test/resources/nonstandard/subdirectory/Dockerfile-nonstandard deleted file mode 100644 index 2d0fa24cb..000000000 --- a/src/test/resources/nonstandard/subdirectory/Dockerfile-nonstandard +++ /dev/null @@ -1,12 +0,0 @@ -# Nginx -# -# VERSION 0.0.1 - -FROM ubuntu:latest -MAINTAINER Guillaume J. Charmes "guillaume@dotcloud.com" - -# make sure the package repository is up to date -RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list -RUN apt-get update - -RUN apt-get install -y inotify-tools nginx apache2 openssh-server \ No newline at end of file diff --git a/src/test/resources/testAddUrl/testrun.sh b/src/test/resources/testAddUrl/testrun.sh deleted file mode 100755 index 8eb4630b3..000000000 --- a/src/test/resources/testAddUrl/testrun.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cat /tmp/docker_home.html - diff --git a/src/test/resources/testEnv/Dockerfile b/src/test/resources/testEnv/Dockerfile deleted file mode 100644 index a0a084633..000000000 --- a/src/test/resources/testEnv/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:latest - -ENV varA ./subFolder -ENV varB $varA/testrun.sh - -ADD $varB /tmp/ - -RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh - -CMD ["testrun.sh"] diff --git a/src/test/resources/testEnv/subFolder/testrun.sh b/src/test/resources/testEnv/subFolder/testrun.sh deleted file mode 100755 index 14259aa77..000000000 --- a/src/test/resources/testEnv/subFolder/testrun.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo "Successfully executed testrun.sh" \ No newline at end of file From 4280ee7c639605291f8acda039051395055414ae Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Tue, 7 Jun 2016 22:08:41 +0200 Subject: [PATCH 065/780] Use expectExceptions in test annotation --- .../github/dockerjava/netty/exec/AuthCmdExecTest.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java index 66ac1bce3..690d478f4 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java @@ -44,14 +44,8 @@ public void testAuth() throws Exception { assertEquals(response.getStatus(), "Login Succeeded"); } - @Test() + @Test(expectedExceptions = UnauthorizedException.class) public void testAuthInvalid() throws Exception { - - try { - DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); - fail("Expected a UnauthorizedException caused by a bad password."); - } catch (UnauthorizedException e) { - assertEquals(e.getMessage(), "Wrong login/password, please try again\n"); - } + DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); } } From 84cf070278343867bf2a984a6fa18839a5a635e5 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Tue, 7 Jun 2016 22:09:59 +0200 Subject: [PATCH 066/780] Fix test for v.1.23 --- .../netty/exec/ExecStartCmdExecTest.java | 60 +++++++++++++------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java index 2938ac8c0..e87c56d74 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java @@ -46,7 +46,7 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - @Test(groups = "ignoreInCircleCi") + @Test() public void execStart() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); @@ -58,9 +58,14 @@ public void execStart() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) - .withAttachStdout(true).withCmd("touch", "/execStartTest.log").exec(); - dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false) - .exec(new ExecStartResultCallback(System.out, System.err)).awaitCompletion(); + .withAttachStdout(true) + .withCmd("touch", "/execStartTest.log") + .exec(); + + dockerClient.execStartCmd(execCreateCmdResponse.getId()) + .withDetach(false) + .exec(new ExecStartResultCallback(System.out, System.err)) + .awaitCompletion(); InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "/execStartTest.log").exec(); @@ -73,7 +78,7 @@ public void execStart() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test(groups = "ignoreInCircleCi") + @Test() public void execStartAttached() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); @@ -85,9 +90,14 @@ public void execStartAttached() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) - .withAttachStdout(true).withCmd("touch", "/execStartTest.log").exec(); - dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false) - .exec(new ExecStartResultCallback(System.out, System.err)).awaitCompletion(); + .withAttachStdout(true) + .withCmd("touch", "/execStartTest.log") + .exec(); + + dockerClient.execStartCmd(execCreateCmdResponse.getId()) + .withDetach(false) + .exec(new ExecStartResultCallback(System.out, System.err)) + .awaitCompletion(); InputStream response = dockerClient.copyArchiveFromContainerCmd(container.getId(), "/execStartTest.log").exec(); Boolean bytesAvailable = response.available() > 0; @@ -99,7 +109,7 @@ public void execStartAttached() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test(groups = "ignoreInCircleCi") + @Test() public void execStartAttachStdin() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); @@ -115,14 +125,23 @@ public void execStartAttachStdin() throws Exception { ByteArrayOutputStream stdout = new ByteArrayOutputStream(); ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) - .withAttachStdout(true).withAttachStdin(true).withCmd("cat").exec(); - boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false).withTty(true).withStdIn(stdin) - .exec(new ExecStartResultCallback(stdout, System.err)).awaitCompletion(5, TimeUnit.SECONDS); + .withAttachStdout(true) + .withAttachStdin(true) + .withCmd("cat") + .exec(); + + boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId()) + .withDetach(false) + .withTty(true) + .withStdIn(stdin) + .exec(new ExecStartResultCallback(stdout, System.err)) + .awaitCompletion(5, TimeUnit.SECONDS); assertTrue(completed, "The process was not finished."); assertEquals(stdout.toString("UTF-8"), "STDIN\n"); } + @Test() public void execStartAttachStdinToShell() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); @@ -156,7 +175,7 @@ public void execStartAttachStdinToShell() throws Exception { assertThat(stdout.toString(), containsString("etc\n")); } - @Test(groups = "ignoreInCircleCi") + @Test() public void execStartNotAttachedStdin() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); @@ -172,11 +191,18 @@ public void execStartNotAttachedStdin() throws Exception { ByteArrayOutputStream stdout = new ByteArrayOutputStream(); ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) - .withAttachStdout(true).withAttachStdin(false).withCmd("/bin/sh").exec(); - boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false).withStdIn(stdin) - .exec(new ExecStartResultCallback(stdout, System.err)).awaitCompletion(5, TimeUnit.SECONDS); + .withAttachStdout(true) + .withAttachStdin(false) + .withCmd("/bin/sh").exec(); - assertTrue(completed, "The process was not finished."); + boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId()) + .withDetach(false) + .withStdIn(stdin) + .exec(new ExecStartResultCallback(stdout, System.err)) + .awaitCompletion(5, TimeUnit.SECONDS); + + // with v1.22 of the remote api the server closed the connection when no stdin was attached while exec create, so completed was true + assertFalse(completed, "The process was not finished."); assertEquals(stdout.toString(), ""); } } From 63f276a99c0f5245e47e869431d6c2b11a2dd101 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Tue, 7 Jun 2016 23:36:25 +0200 Subject: [PATCH 067/780] Fix load certs from file system --- .../dockerjava/core/LocalDirectorySSLConfig.java | 15 +++++++++++++-- .../dockerjava/core/util/CertificateUtils.java | 10 +--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java b/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java index e39a2bc40..961c282de 100644 --- a/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java +++ b/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java @@ -2,7 +2,10 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.io.File; import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.Security; import javax.net.ssl.SSLContext; @@ -50,9 +53,17 @@ public SSLContext getSSLContext() { System.setProperty("https.protocols", httpProtocols); } - sslConfig.keyStore(CertificateUtils.createKeyStore(dockerCertPath)); + String caPemPath = dockerCertPath + File.separator + "ca.pem"; + String keyPemPath = dockerCertPath + File.separator + "key.pem"; + String certPemPath = dockerCertPath + File.separator + "cert.pem"; + + String keypem = new String(Files.readAllBytes(Paths.get(keyPemPath))); + String certpem = new String(Files.readAllBytes(Paths.get(certPemPath))); + String capem = new String(Files.readAllBytes(Paths.get(caPemPath))); + + sslConfig.keyStore(CertificateUtils.createKeyStore(keypem, certpem)); sslConfig.keyStorePassword("docker"); - sslConfig.trustStore(CertificateUtils.createTrustStore(dockerCertPath)); + sslConfig.trustStore(CertificateUtils.createTrustStore(capem)); return sslConfig.createSSLContext(); diff --git a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java index 6e1925630..c760331d6 100644 --- a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java +++ b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java @@ -18,6 +18,7 @@ import java.util.List; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; @@ -49,15 +50,6 @@ public static boolean verifyCertificatesExist(String dockerCertPath) { return result; } - /** - * @param dockerCertPath with standard named files. - */ - public static KeyStore createKeyStore(final String dockerCertPath) throws NoSuchAlgorithmException, - InvalidKeySpecException, IOException, CertificateException, KeyStoreException { - return createKeyStore("key.pem", "cert.pem"); - } - - @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public static KeyStore createKeyStore(final String keypem, final String certpem) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, CertificateException, KeyStoreException { From fefd16017d70b29e1d1f337bf9338ce0cb9543a3 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Tue, 7 Jun 2016 23:38:37 +0200 Subject: [PATCH 068/780] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f55b2cd75..6125ab5b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Change Log === +3.0.0-SNAPSHOT +--- + +All changes +* [#529] (https://github.com/docker-java/docker-java/pull/529) Refactor CertUtils. Support ECDSA and PrivateKey + v3.0.0 --- Notes From 605815651521f3270e01b67b0e89b183e10cedbe Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Tue, 7 Jun 2016 23:39:22 +0200 Subject: [PATCH 069/780] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6125ab5b7..1f3b7e9b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Change Log === -3.0.0-SNAPSHOT +3.0.1-SNAPSHOT --- All changes From 3a2dcc490879d345c6c96b215f1e47c995d293f5 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 8 Jun 2016 21:59:57 +0300 Subject: [PATCH 070/780] Implemented Device parser (#593) * Implement Device parser Signed-off-by: Kanstantsin Shautsou * Add more tests, fix. --- .../github/dockerjava/api/model/Device.java | 76 +++++++++++++++ .../dockerjava/api/model/DeviceTest.java | 95 +++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 src/test/java/com/github/dockerjava/api/model/DeviceTest.java diff --git a/src/main/java/com/github/dockerjava/api/model/Device.java b/src/main/java/com/github/dockerjava/api/model/Device.java index 9240239b1..f2b75e3f5 100644 --- a/src/main/java/com/github/dockerjava/api/model/Device.java +++ b/src/main/java/com/github/dockerjava/api/model/Device.java @@ -1,6 +1,8 @@ package com.github.dockerjava.api.model; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.commons.lang.BooleanUtils.isNotTrue; +import static org.apache.commons.lang.StringUtils.isEmpty; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; @@ -9,6 +11,11 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + @JsonInclude(Include.NON_NULL) public class Device { @@ -45,6 +52,75 @@ public String getPathOnHost() { return pathOnHost; } + /** + * @link https://github.com/docker/docker/blob/6b4a46f28266031ce1a1315f17fb69113a06efe1/runconfig/opts/parse_test.go#L468 + */ + @Nonnull + public static Device parse(@Nonnull String deviceStr) { + String src = ""; + String dst = ""; + String permissions = "rwm"; + final String[] arr = deviceStr.trim().split(":"); + // java String.split() returns wrong length, use tokenizer instead + switch (new StringTokenizer(deviceStr, ":").countTokens()) { + case 3: { + // Mismatches docker code logic. While there is no validations after parsing, checking heregit + if (validDeviceMode(arr[2])) { + permissions = arr[2]; + } else { + throw new IllegalArgumentException("Invalid device specification: " + deviceStr); + } + } + case 2: { + if (validDeviceMode(arr[1])) { + permissions = arr[1]; + } else { + dst = arr[1]; + } + } + case 1: { + src = arr[0]; + break; + } + default: { + throw new IllegalArgumentException("Invalid device specification: " + deviceStr); + } + } + + if (isEmpty(dst)) { + dst = src; + } + + return new Device(permissions, dst, src); + } + + /** + * ValidDeviceMode checks if the mode for device is valid or not. + * Valid mode is a composition of r (read), w (write), and m (mknod). + * + * @link https://github.com/docker/docker/blob/6b4a46f28266031ce1a1315f17fb69113a06efe1/runconfig/opts/parse.go#L796 + */ + private static boolean validDeviceMode(String deviceMode) { + Map validModes = new HashMap<>(3); + validModes.put("r", true); + validModes.put("w", true); + validModes.put("m", true); + + if (isEmpty(deviceMode)) { + return false; + } + + for (char ch : deviceMode.toCharArray()) { + final String mode = String.valueOf(ch); + if (isNotTrue(validModes.get(mode))) { + return false; // wrong mode + } + validModes.put(mode, false); + } + + return true; + } + @Override public boolean equals(Object obj) { if (obj instanceof Device) { diff --git a/src/test/java/com/github/dockerjava/api/model/DeviceTest.java b/src/test/java/com/github/dockerjava/api/model/DeviceTest.java new file mode 100644 index 000000000..5c48c4886 --- /dev/null +++ b/src/test/java/com/github/dockerjava/api/model/DeviceTest.java @@ -0,0 +1,95 @@ +package com.github.dockerjava.api.model; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static junit.framework.Assert.fail; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +/** + * @author Kanstantsin Shautsou + */ +public class DeviceTest { + + public static List validPaths = Arrays.asList( + "/home", + "/home:/home", + "/home:/something/else", + "/with space", + "/home:/with space", + "relative:/absolute-path", + "hostPath:/containerPath:r", + "/hostPath:/containerPath:rw", + "/hostPath:/containerPath:mrw" + ); + + public static HashMap badPaths = new LinkedHashMap() {{ + put("", "bad format for path: "); + // TODO implement ValidatePath +// put("./", "./ is not an absolute path"); +// put("../", "../ is not an absolute path"); +// put("/:../", "../ is not an absolute path"); +// put("/:path", "path is not an absolute path"); +// put(":", "bad format for path: :"); +// put("/tmp:", " is not an absolute path"); +// put(":test", "bad format for path: :test"); +// put(":/test", "bad format for path: :/test"); +// put("tmp:", " is not an absolute path"); +// put(":test:", "bad format for path: :test:"); +// put("::", "bad format for path: ::"); +// put(":::", "bad format for path: :::"); +// put("/tmp:::", "bad format for path: /tmp:::"); +// put(":/tmp::", "bad format for path: :/tmp::"); +// put("path:ro", "ro is not an absolute path"); +// put("path:rr", "rr is not an absolute path"); + put("a:/b:ro", "bad mode specified: ro"); + put("a:/b:rr", "bad mode specified: rr"); + }}; + + @Test + public void testParse() throws Exception { + assertThat(Device.parse("/dev/sda:/dev/xvdc:r"), + equalTo(new Device("r", "/dev/xvdc", "/dev/sda"))); + + assertThat(Device.parse("/dev/snd:rw"), + equalTo(new Device("rw", "/dev/snd", "/dev/snd"))); + + assertThat(Device.parse("/dev/snd:/something"), + equalTo(new Device("rwm", "/something", "/dev/snd"))); + + assertThat(Device.parse("/dev/snd:/something:rw"), + equalTo(new Device("rw", "/something", "/dev/snd"))); + + } + + @Test + public void testParseBadPaths() { + for (Map.Entry entry : badPaths.entrySet()) { + final String deviceStr = entry.getKey(); + try { + Device.parse(deviceStr); + fail("Should fail because: " + entry.getValue() + " '" + deviceStr + "'"); + } catch (IllegalArgumentException ex) { + assertThat(ex.getMessage(), containsString("Invalid device specification:")); + } + } + } + + @Test + public void testParseValidPaths() { + for (String path : validPaths) { + Device.parse(path); + } + } +} From 72597d723e56d84890d3821d734a46cc2e0a9441 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Thu, 9 Jun 2016 23:44:04 +0200 Subject: [PATCH 071/780] Complement logging tests --- .../client/AbstractDockerClientTest.java | 18 ++++ .../core/command/LogContainerCmdImplTest.java | 93 ++++++++++++++----- .../netty/exec/LogContainerCmdExecTest.java | 93 ++++++++++++++----- 3 files changed, 162 insertions(+), 42 deletions(-) diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index 231e709c1..1a52bbd3f 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -225,8 +225,21 @@ protected String containerLog(String containerId) throws Exception { public static class LogContainerTestCallback extends LogContainerResultCallback { protected final StringBuffer log = new StringBuffer(); + List collectedFrames = new ArrayList(); + + boolean collectFrames = false; + + public LogContainerTestCallback() { + this(false); + } + + public LogContainerTestCallback(boolean collectFrames) { + this.collectFrames = collectFrames; + } + @Override public void onNext(Frame frame) { + if(collectFrames) collectedFrames.add(frame); log.append(new String(frame.getPayload())); } @@ -234,6 +247,11 @@ public void onNext(Frame frame) { public String toString() { return log.toString(); } + + + public List getCollectedFrames() { + return collectedFrames; + } } protected String buildImage(File baseDir) throws Exception { diff --git a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java index 817179eb2..869bcbb1a 100644 --- a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; @@ -17,6 +18,7 @@ import org.testng.annotations.Test; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.StreamType; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; @@ -44,31 +46,65 @@ public void afterMethod(ITestResult result) { } @Test - public void asyncLogContainer() throws Exception { + public void asyncLogContainerWithTtyEnabled() throws Exception { - String snippet = "hello world"; - - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/sh", "-c", "while true; do echo hello; sleep 1; done") + .withTty(true) .exec(); LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainerCmd(container.getId()).exec(); + dockerClient.startContainerCmd(container.getId()) + .exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) - .awaitStatusCode(); + LogContainerTestCallback loggingCallback = new LogContainerTestCallback(true); - assertThat(exitCode, equalTo(0)); + // this essentially test the since=0 case + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .withTailAll() + .exec(loggingCallback); - LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); + + assertTrue(loggingCallback.toString().contains("hello")); + + assertEquals(loggingCallback.getCollectedFrames().get(0).getStreamType(), StreamType.RAW); + } + + @Test + public void asyncLogContainerWithTtyDisabled() throws Exception { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/sh", "-c", "while true; do echo hello; sleep 1; done") + .withTty(false) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()) + .exec(); + + LogContainerTestCallback loggingCallback = new LogContainerTestCallback(true); // this essentially test the since=0 case - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .withTailAll() + .exec(loggingCallback); - loggingCallback.awaitCompletion(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); - assertTrue(loggingCallback.toString().contains(snippet)); + assertTrue(loggingCallback.toString().contains("hello")); + + assertEquals(loggingCallback.getCollectedFrames().get(0).getStreamType(), StreamType.STDOUT); } @Test @@ -105,7 +141,8 @@ public void asyncMultipleLogContainer() throws Exception { String snippet = "hello world"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/echo", snippet) .exec(); LOG.info("Created container: {}", container.toString()); @@ -113,26 +150,36 @@ public void asyncMultipleLogContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) + int exitCode = dockerClient.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) .awaitStatusCode(); assertThat(exitCode, equalTo(0)); LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.close(); loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.close(); loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.awaitCompletion(); @@ -143,7 +190,8 @@ public void asyncMultipleLogContainer() throws Exception { public void asyncLogContainerWithSince() throws Exception { String snippet = "hello world"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/echo", snippet) .exec(); LOG.info("Created container: {}", container.toString()); @@ -153,19 +201,22 @@ public void asyncLogContainerWithSince() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) + int exitCode = dockerClient.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) .awaitStatusCode(); assertThat(exitCode, equalTo(0)); LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withSince(timestamp) + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withSince(timestamp) .exec(loggingCallback); loggingCallback.awaitCompletion(); assertThat(loggingCallback.toString(), containsString(snippet)); } - } diff --git a/src/test/java/com/github/dockerjava/netty/exec/LogContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/LogContainerCmdExecTest.java index 310994755..fe408ac18 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/LogContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/LogContainerCmdExecTest.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; @@ -18,6 +19,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.StreamType; import com.github.dockerjava.core.command.WaitContainerResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; @@ -45,31 +47,65 @@ public void afterMethod(ITestResult result) { } @Test - public void asyncLogContainer() throws Exception { + public void asyncLogContainerWithTtyEnabled() throws Exception { - String snippet = "hello world"; - - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/sh", "-c", "while true; do echo hello; sleep 1; done") + .withTty(true) .exec(); LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainerCmd(container.getId()).exec(); + dockerClient.startContainerCmd(container.getId()) + .exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) - .awaitStatusCode(); + LogContainerTestCallback loggingCallback = new LogContainerTestCallback(true); - assertThat(exitCode, equalTo(0)); + // this essentially test the since=0 case + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .withTailAll() + .exec(loggingCallback); - LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); + + assertTrue(loggingCallback.toString().contains("hello")); + + assertEquals(loggingCallback.getCollectedFrames().get(0).getStreamType(), StreamType.RAW); + } + + @Test + public void asyncLogContainerWithTtyDisabled() throws Exception { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/sh", "-c", "while true; do echo hello; sleep 1; done") + .withTty(false) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()) + .exec(); + + LogContainerTestCallback loggingCallback = new LogContainerTestCallback(true); // this essentially test the since=0 case - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .withTailAll() + .exec(loggingCallback); - loggingCallback.awaitCompletion(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); - assertTrue(loggingCallback.toString().contains(snippet)); + assertTrue(loggingCallback.toString().contains("hello")); + + assertEquals(loggingCallback.getCollectedFrames().get(0).getStreamType(), StreamType.STDOUT); } @Test @@ -106,7 +142,8 @@ public void asyncMultipleLogContainer() throws Exception { String snippet = "hello world"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/echo", snippet) .exec(); LOG.info("Created container: {}", container.toString()); @@ -114,26 +151,36 @@ public void asyncMultipleLogContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) + int exitCode = dockerClient.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) .awaitStatusCode(); assertThat(exitCode, equalTo(0)); LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.close(); loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.close(); loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).exec(loggingCallback); + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .exec(loggingCallback); loggingCallback.awaitCompletion(); @@ -144,7 +191,8 @@ public void asyncMultipleLogContainer() throws Exception { public void asyncLogContainerWithSince() throws Exception { String snippet = "hello world"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/echo", snippet) + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/echo", snippet) .exec(); LOG.info("Created container: {}", container.toString()); @@ -154,19 +202,22 @@ public void asyncLogContainerWithSince() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - int exitCode = dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()) + int exitCode = dockerClient.waitContainerCmd(container.getId()) + .exec(new WaitContainerResultCallback()) .awaitStatusCode(); assertThat(exitCode, equalTo(0)); LogContainerTestCallback loggingCallback = new LogContainerTestCallback(); - dockerClient.logContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withSince(timestamp) + dockerClient.logContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withSince(timestamp) .exec(loggingCallback); loggingCallback.awaitCompletion(); assertThat(loggingCallback.toString(), containsString(snippet)); } - } From 9ae14cb9567b8257be26f41423f94cf61391969c Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Mon, 13 Jun 2016 22:56:48 +0200 Subject: [PATCH 072/780] Refactor configuration of SSL to allow override with custom config (#596) * Refactor configuration of SSL to allow override with custom config * Store SSLConfig instead SSLContext * avoid NPE * prepare release * Coding style changes --- pom.xml | 2 +- .../api/command/DockerCmdExecFactory.java | 4 - .../core/DefaultDockerClientConfig.java | 455 ++++++++++++++++++ .../dockerjava/core/DockerClientBuilder.java | 4 +- .../dockerjava/core/DockerClientConfig.java | 436 +---------------- .../dockerjava/core/DockerClientImpl.java | 4 +- .../jaxrs/DockerCmdExecFactoryImpl.java | 28 +- .../netty/DockerCmdExecFactoryImpl.java | 38 +- .../client/AbstractDockerClientTest.java | 8 +- ...ava => DefaultDockerClientConfigTest.java} | 96 ++-- .../dockerjava/core/DockerClientImplTest.java | 2 +- .../core/TestDockerCmdExecFactory.java | 6 - 12 files changed, 552 insertions(+), 531 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java rename src/test/java/com/github/dockerjava/core/{DockerClientConfigTest.java => DefaultDockerClientConfigTest.java} (54%) diff --git a/pom.xml b/pom.xml index bee178a6d..3f9caa55a 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.1-SNAPSHOT + 3.0.0-kostyasha-3 docker-java https://github.com/docker-java/docker-java 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 ae090e434..0de3afe38 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -3,8 +3,6 @@ import java.io.Closeable; import java.io.IOException; -import javax.net.ssl.SSLContext; - import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.RemoteApiVersion; @@ -117,8 +115,6 @@ public interface DockerCmdExecFactory extends Closeable { DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec(); - DockerCmdExecFactory withSSLContext(SSLContext sslContext); - @Override void close() throws IOException; diff --git a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java new file mode 100644 index 000000000..4641f9d3c --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -0,0 +1,455 @@ +package com.github.dockerjava.core; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.URI; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +import com.github.dockerjava.api.exception.DockerClientException; +import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.api.model.AuthConfigurations; +import com.github.dockerjava.core.NameParser.HostnameReposName; +import com.github.dockerjava.core.NameParser.ReposTag; + +/** + * Respects some of the docker CLI options. See https://docs.docker.com/engine/reference/commandline/cli/#environment-variables + */ +public class DefaultDockerClientConfig implements Serializable, DockerClientConfig { + + private static final long serialVersionUID = -4307357472441531489L; + + public static final String DOCKER_HOST = "DOCKER_HOST"; + + public static final String DOCKER_TLS_VERIFY = "DOCKER_TLS_VERIFY"; + + public static final String DOCKER_CONFIG = "DOCKER_CONFIG"; + + public static final String DOCKER_CERT_PATH = "DOCKER_CERT_PATH"; + + public static final String API_VERSION = "api.version"; + + public static final String REGISTRY_USERNAME = "registry.username"; + + public static final String REGISTRY_PASSWORD = "registry.password"; + + public static final String REGISTRY_EMAIL = "registry.email"; + + public static final String REGISTRY_URL = "registry.url"; + + private static final String DOCKER_JAVA_PROPERTIES = "docker-java.properties"; + + private static final String DOCKER_CFG = ".dockercfg"; + + private static final Set CONFIG_KEYS = new HashSet(); + + static { + CONFIG_KEYS.add(DOCKER_HOST); + CONFIG_KEYS.add(DOCKER_TLS_VERIFY); + CONFIG_KEYS.add(DOCKER_CONFIG); + CONFIG_KEYS.add(DOCKER_CERT_PATH); + CONFIG_KEYS.add(API_VERSION); + CONFIG_KEYS.add(REGISTRY_USERNAME); + CONFIG_KEYS.add(REGISTRY_PASSWORD); + CONFIG_KEYS.add(REGISTRY_EMAIL); + CONFIG_KEYS.add(REGISTRY_URL); + } + + private final URI dockerHost; + + private final String registryUsername, registryPassword, registryEmail, registryUrl, dockerConfig; + + private final SSLConfig sslConfig; + + private final RemoteApiVersion apiVersion; + + DefaultDockerClientConfig(URI dockerHost, String dockerConfig, String apiVersion, String registryUrl, + String registryUsername, String registryPassword, String registryEmail, SSLConfig sslConfig) { + this.dockerHost = checkDockerHostScheme(dockerHost); + this.dockerConfig = dockerConfig; + this.apiVersion = RemoteApiVersion.parseConfigWithDefault(apiVersion); + this.sslConfig = sslConfig; + this.registryUsername = registryUsername; + this.registryPassword = registryPassword; + this.registryEmail = registryEmail; + this.registryUrl = registryUrl; + } + + private URI checkDockerHostScheme(URI dockerHost) { + if ("tcp".equals(dockerHost.getScheme()) || "unix".equals(dockerHost.getScheme())) { + return dockerHost; + } else { + throw new DockerClientException("Unsupported protocol scheme found: '" + dockerHost + + "'. Only 'tcp://' or 'unix://' supported."); + } + } + + private static Properties loadIncludedDockerProperties(Properties systemProperties) { + try (InputStream is = DefaultDockerClientConfig.class.getResourceAsStream("/" + DOCKER_JAVA_PROPERTIES)) { + Properties p = new Properties(); + p.load(is); + replaceProperties(p, systemProperties); + return p; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void replaceProperties(Properties properties, Properties replacements) { + for (Object objectKey : properties.keySet()) { + String key = objectKey.toString(); + properties.setProperty(key, replaceProperties(properties.getProperty(key), replacements)); + } + } + + private static String replaceProperties(String s, Properties replacements) { + for (Map.Entry entry : replacements.entrySet()) { + String key = "${" + entry.getKey() + "}"; + while (s.contains(key)) { + s = s.replace(key, String.valueOf(entry.getValue())); + } + } + return s; + } + + /** + * Creates a new Properties object containing values overridden from ${user.home}/.docker.io.properties + * + * @param p + * The original set of properties to override + * @return A copy of the original Properties with overridden values + */ + private static Properties overrideDockerPropertiesWithSettingsFromUserHome(Properties p, Properties systemProperties) { + Properties overriddenProperties = new Properties(); + overriddenProperties.putAll(p); + + final File usersDockerPropertiesFile = new File(systemProperties.getProperty("user.home"), + "." + DOCKER_JAVA_PROPERTIES); + if (usersDockerPropertiesFile.isFile()) { + try (FileInputStream in = new FileInputStream(usersDockerPropertiesFile)) { + overriddenProperties.load(in); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return overriddenProperties; + } + + private static Properties overrideDockerPropertiesWithEnv(Properties properties, Map env) { + Properties overriddenProperties = new Properties(); + overriddenProperties.putAll(properties); + + // special case which is a sensible default + if (env.containsKey(DOCKER_HOST)) { + overriddenProperties.setProperty(DOCKER_HOST, env.get(DOCKER_HOST)); + } + + for (Map.Entry envEntry : env.entrySet()) { + String envKey = envEntry.getKey(); + if (CONFIG_KEYS.contains(envKey)) { + overriddenProperties.setProperty(envKey, envEntry.getValue()); + } + } + + return overriddenProperties; + } + + /** + * Creates a new Properties object containing values overridden from the System properties + * + * @param p + * The original set of properties to override + * @return A copy of the original Properties with overridden values + */ + private static Properties overrideDockerPropertiesWithSystemProperties(Properties p, Properties systemProperties) { + Properties overriddenProperties = new Properties(); + overriddenProperties.putAll(p); + + for (String key : CONFIG_KEYS) { + if (systemProperties.containsKey(key)) { + overriddenProperties.setProperty(key, systemProperties.getProperty(key)); + } + } + return overriddenProperties; + } + + public static Builder createDefaultConfigBuilder() { + return createDefaultConfigBuilder(System.getenv(), System.getProperties()); + } + + /** + * Allows you to build the config without system environment interfering for more robust testing + */ + static Builder createDefaultConfigBuilder(Map env, Properties systemProperties) { + Properties properties = loadIncludedDockerProperties(systemProperties); + properties = overrideDockerPropertiesWithSettingsFromUserHome(properties, systemProperties); + properties = overrideDockerPropertiesWithEnv(properties, env); + properties = overrideDockerPropertiesWithSystemProperties(properties, systemProperties); + return new Builder().withProperties(properties); + } + + @Override + public URI getDockerHost() { + return dockerHost; + } + + @Override + public RemoteApiVersion getApiVersion() { + return apiVersion; + } + + @Override + public String getRegistryUsername() { + return registryUsername; + } + + @Override + public String getRegistryPassword() { + return registryPassword; + } + + @Override + public String getRegistryEmail() { + return registryEmail; + } + + @Override + public String getRegistryUrl() { + return registryUrl; + } + + public String getDockerConfig() { + return dockerConfig; + } + + private AuthConfig getAuthConfig() { + AuthConfig authConfig = null; + if (getRegistryUsername() != null && getRegistryPassword() != null && getRegistryEmail() != null + && getRegistryUrl() != null) { + authConfig = new AuthConfig() + .withUsername(getRegistryUsername()) + .withPassword(getRegistryPassword()) + .withEmail(getRegistryEmail()) + .withRegistryAddress(getRegistryUrl()); + } + return authConfig; + } + + @Override + public AuthConfig effectiveAuthConfig(String imageName) { + AuthConfig authConfig = null; + + File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); + + if (dockerCfgFile.exists() && dockerCfgFile.isFile() && imageName != null) { + AuthConfigFile authConfigFile; + try { + authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); + } catch (IOException e) { + throw new DockerClientException("Failed to parse dockerCfgFile", e); + } + ReposTag reposTag = NameParser.parseRepositoryTag(imageName); + HostnameReposName hostnameReposName = NameParser.resolveRepositoryName(reposTag.repos); + + authConfig = authConfigFile.resolveAuthConfig(hostnameReposName.hostname); + } + + AuthConfig otherAuthConfig = getAuthConfig(); + + if (otherAuthConfig != null) { + authConfig = otherAuthConfig; + } + + return authConfig; + } + + @Override + public AuthConfigurations getAuthConfigurations() { + File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); + if (dockerCfgFile.exists() && dockerCfgFile.isFile()) { + AuthConfigFile authConfigFile; + try { + authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); + } catch (IOException e) { + throw new DockerClientException("Failed to parse dockerCfgFile", e); + } + + return authConfigFile.getAuthConfigurations(); + } + + return new AuthConfigurations(); + } + + @Override + public SSLConfig getSSLConfig() { + return sslConfig; + } + + @Override + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public static class Builder { + private URI dockerHost; + + private String apiVersion, registryUsername, registryPassword, registryEmail, registryUrl, dockerConfig, + dockerCertPath; + + private boolean dockerTlsVerify; + + private SSLConfig customSslConfig = null; + + /** + * This will set all fields in the builder to those contained in the Properties object. The Properties object should contain the + * following docker-java configuration keys: DOCKER_HOST, DOCKER_TLS_VERIFY, api.version, registry.username, registry.password, + * registry.email, DOCKER_CERT_PATH, and DOCKER_CONFIG. + */ + public Builder withProperties(Properties p) { + return withDockerHost(p.getProperty(DOCKER_HOST)) + .withDockerTlsVerify(p.getProperty(DOCKER_TLS_VERIFY)) + .withDockerConfig(p.getProperty(DOCKER_CONFIG)) + .withDockerCertPath(p.getProperty(DOCKER_CERT_PATH)) + .withApiVersion(p.getProperty(API_VERSION)) + .withRegistryUsername(p.getProperty(REGISTRY_USERNAME)) + .withRegistryPassword(p.getProperty(REGISTRY_PASSWORD)) + .withRegistryEmail(p.getProperty(REGISTRY_EMAIL)) + .withRegistryUrl(p.getProperty(REGISTRY_URL)); + } + + /** + * configure DOCKER_HOST + */ + public final Builder withDockerHost(String dockerHost) { + checkNotNull(dockerHost, "uri was not specified"); + this.dockerHost = URI.create(dockerHost); + return this; + } + + public final Builder withApiVersion(RemoteApiVersion apiVersion) { + this.apiVersion = apiVersion.getVersion(); + return this; + } + + public final Builder withApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + return this; + } + + public final Builder withRegistryUsername(String registryUsername) { + this.registryUsername = registryUsername; + return this; + } + + public final Builder withRegistryPassword(String registryPassword) { + this.registryPassword = registryPassword; + return this; + } + + public final Builder withRegistryEmail(String registryEmail) { + this.registryEmail = registryEmail; + return this; + } + + public Builder withRegistryUrl(String registryUrl) { + this.registryUrl = registryUrl; + return this; + } + + public final Builder withDockerCertPath(String dockerCertPath) { + this.dockerCertPath = dockerCertPath; + return this; + } + + public final Builder withDockerConfig(String dockerConfig) { + this.dockerConfig = dockerConfig; + return this; + } + + public final Builder withDockerTlsVerify(String dockerTlsVerify) { + if (dockerTlsVerify != null) { + String trimmed = dockerTlsVerify.trim(); + this.dockerTlsVerify = "true".equalsIgnoreCase(trimmed) || "1".equals(trimmed); + } else { + this.dockerTlsVerify = false; + } + return this; + } + + public final Builder withDockerTlsVerify(Boolean dockerTlsVerify) { + this.dockerTlsVerify = dockerTlsVerify; + return this; + } + + /** + * Overrides the default {@link SSLConfig} that is used when calling {@link Builder#withDockerTlsVerify(java.lang.Boolean)} and + * {@link Builder#withDockerCertPath(String)}. This way it is possible to pass a custom {@link SSLConfig} to the resulting + * {@link DockerClientConfig} that may be created by other means than the local file system. + */ + public final Builder withCustomSslConfig(SSLConfig customSslConfig) { + this.customSslConfig = customSslConfig; + return this; + } + + public DefaultDockerClientConfig build() { + + SSLConfig sslConfig = null; + + if (customSslConfig == null) { + if (dockerTlsVerify) { + dockerCertPath = checkDockerCertPath(dockerCertPath); + sslConfig = new LocalDirectorySSLConfig(dockerCertPath); + } + } else { + sslConfig = customSslConfig; + } + + return new DefaultDockerClientConfig(dockerHost, dockerConfig, apiVersion, registryUrl, registryUsername, + registryPassword, registryEmail, sslConfig); + } + + private String checkDockerCertPath(String dockerCertPath) { + if (StringUtils.isEmpty(dockerCertPath)) { + throw new DockerClientException( + "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certifate path (DOCKER_CERT_PATH) is not defined."); + } + + File certPath = new File(dockerCertPath); + + if (!certPath.exists()) { + throw new DockerClientException( + "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + + dockerCertPath + "' doesn't exist."); + } else if (!certPath.isDirectory()) { + throw new DockerClientException( + "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + + dockerCertPath + "' doesn't point to a directory."); + } + + return dockerCertPath; + } + } +} diff --git a/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java b/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java index 6aed6c358..743b8c2ef 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java @@ -2,7 +2,7 @@ import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.DockerCmdExecFactory; -import com.github.dockerjava.core.DockerClientConfig.DockerClientConfigBuilder; +import com.github.dockerjava.core.DefaultDockerClientConfig.Builder; import com.github.dockerjava.jaxrs.DockerCmdExecFactoryImpl; public class DockerClientBuilder { @@ -19,7 +19,7 @@ public static DockerClientBuilder getInstance() { return new DockerClientBuilder(DockerClientImpl.getInstance()); } - public static DockerClientBuilder getInstance(DockerClientConfigBuilder dockerClientConfigBuilder) { + public static DockerClientBuilder getInstance(Builder dockerClientConfigBuilder) { return getInstance(dockerClientConfigBuilder.build()); } diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index 31cfc0c58..532fe6b43 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -1,440 +1,40 @@ +/* + * Created on 08.06.2016 + */ package com.github.dockerjava.core; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; import java.net.URI; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; -import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.AuthConfigurations; -import com.github.dockerjava.core.NameParser.HostnameReposName; -import com.github.dockerjava.core.NameParser.ReposTag; /** - * Respects some of the docker CLI options. See https://docs.docker.com/engine/reference/commandline/cli/#environment-variables + * Interface that describes the docker client configuration. + * + * @author Marcus Linke + * */ -public class DockerClientConfig implements Serializable { - - private static final long serialVersionUID = -4307357472441531489L; - - public static final String DOCKER_HOST = "DOCKER_HOST"; - - public static final String DOCKER_TLS_VERIFY = "DOCKER_TLS_VERIFY"; - - public static final String DOCKER_CONFIG = "DOCKER_CONFIG"; - - public static final String DOCKER_CERT_PATH = "DOCKER_CERT_PATH"; - - public static final String API_VERSION = "api.version"; - - public static final String REGISTRY_USERNAME = "registry.username"; - - public static final String REGISTRY_PASSWORD = "registry.password"; - - public static final String REGISTRY_EMAIL = "registry.email"; - - public static final String REGISTRY_URL = "registry.url"; - - private static final String DOCKER_JAVA_PROPERTIES = "docker-java.properties"; - - private static final String DOCKER_CFG = ".dockercfg"; - - private static final Set CONFIG_KEYS = new HashSet(); - - static { - CONFIG_KEYS.add(DOCKER_HOST); - CONFIG_KEYS.add(DOCKER_TLS_VERIFY); - CONFIG_KEYS.add(DOCKER_CONFIG); - CONFIG_KEYS.add(DOCKER_CERT_PATH); - CONFIG_KEYS.add(API_VERSION); - CONFIG_KEYS.add(REGISTRY_USERNAME); - CONFIG_KEYS.add(REGISTRY_PASSWORD); - CONFIG_KEYS.add(REGISTRY_EMAIL); - CONFIG_KEYS.add(REGISTRY_URL); - } - - private final URI dockerHost; - - private final String registryUsername, registryPassword, registryEmail, registryUrl, dockerConfig, dockerCertPath; +public interface DockerClientConfig { - private final boolean dockerTlsVerify; + URI getDockerHost(); - private final RemoteApiVersion apiVersion; + RemoteApiVersion getApiVersion(); - DockerClientConfig(URI dockerHost, String dockerConfig, String apiVersion, String registryUrl, - String registryUsername, String registryPassword, String registryEmail, String dockerCertPath, - boolean dockerTslVerify) { - this.dockerHost = checkDockerHostScheme(dockerHost); - this.dockerTlsVerify = dockerTslVerify; - this.dockerCertPath = checkDockerCertPath(dockerTslVerify, dockerCertPath); - this.dockerConfig = dockerConfig; - this.apiVersion = RemoteApiVersion.parseConfigWithDefault(apiVersion); - this.registryUsername = registryUsername; - this.registryPassword = registryPassword; - this.registryEmail = registryEmail; - this.registryUrl = registryUrl; - } + String getRegistryUsername(); - private URI checkDockerHostScheme(URI dockerHost) { - if ("tcp".equals(dockerHost.getScheme()) || "unix".equals(dockerHost.getScheme())) { - return dockerHost; - } else { - throw new DockerClientException("Unsupported protocol scheme found: '" + dockerHost - + "'. Only 'tcp://' or 'unix://' supported."); - } - } + String getRegistryPassword(); - private String checkDockerCertPath(boolean dockerTlsVerify, String dockerCertPath) { - if (dockerTlsVerify) { - if (StringUtils.isEmpty(dockerCertPath)) { - throw new DockerClientException( - "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certifate path (DOCKER_CERT_PATH) is not defined."); - } else { - File certPath = new File(dockerCertPath); + String getRegistryEmail(); - if (!certPath.exists()) { - throw new DockerClientException( - "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + dockerCertPath - + "' doesn't exist."); - } + String getRegistryUrl(); - if (certPath.isDirectory()) { - return dockerCertPath; - } else { - throw new DockerClientException( - "Enabled TLS verification (DOCKER_TLS_VERIFY=1) but certificate path (DOCKER_CERT_PATH) '" + dockerCertPath - + "' doesn't point to a directory."); - } - } - } else { - return dockerCertPath; - } - } + AuthConfig effectiveAuthConfig(String imageName); - private static Properties loadIncludedDockerProperties(Properties systemProperties) { - try (InputStream is = DockerClientConfig.class.getResourceAsStream("/" + DOCKER_JAVA_PROPERTIES)) { - Properties p = new Properties(); - p.load(is); - replaceProperties(p, systemProperties); - return p; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static void replaceProperties(Properties properties, Properties replacements) { - for (Object objectKey : properties.keySet()) { - String key = objectKey.toString(); - properties.setProperty(key, replaceProperties(properties.getProperty(key), replacements)); - } - } - - private static String replaceProperties(String s, Properties replacements) { - for (Map.Entry entry : replacements.entrySet()) { - String key = "${" + entry.getKey() + "}"; - while (s.contains(key)) { - s = s.replace(key, String.valueOf(entry.getValue())); - } - } - return s; - } - - /** - * Creates a new Properties object containing values overridden from ${user.home}/.docker.io.properties - * - * @param p - * The original set of properties to override - * @return A copy of the original Properties with overridden values - */ - private static Properties overrideDockerPropertiesWithSettingsFromUserHome(Properties p, Properties systemProperties) { - Properties overriddenProperties = new Properties(); - overriddenProperties.putAll(p); - - final File usersDockerPropertiesFile = new File(systemProperties.getProperty("user.home"), - "." + DOCKER_JAVA_PROPERTIES); - if (usersDockerPropertiesFile.isFile()) { - try (FileInputStream in = new FileInputStream(usersDockerPropertiesFile)) { - overriddenProperties.load(in); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return overriddenProperties; - } - - private static Properties overrideDockerPropertiesWithEnv(Properties properties, Map env) { - Properties overriddenProperties = new Properties(); - overriddenProperties.putAll(properties); - - // special case which is a sensible default - if (env.containsKey(DOCKER_HOST)) { - overriddenProperties.setProperty(DOCKER_HOST, env.get(DOCKER_HOST)); - } - - for (Map.Entry envEntry : env.entrySet()) { - String envKey = envEntry.getKey(); - if (CONFIG_KEYS.contains(envKey)) { - overriddenProperties.setProperty(envKey, envEntry.getValue()); - } - } - - return overriddenProperties; - } + AuthConfigurations getAuthConfigurations(); /** - * Creates a new Properties object containing values overridden from the System properties - * - * @param p - * The original set of properties to override - * @return A copy of the original Properties with overridden values + * Returns an {@link SSLConfig} when secure connection is configured or null if not. */ - private static Properties overrideDockerPropertiesWithSystemProperties(Properties p, Properties systemProperties) { - Properties overriddenProperties = new Properties(); - overriddenProperties.putAll(p); - - for (String key : CONFIG_KEYS) { - if (systemProperties.containsKey(key)) { - overriddenProperties.setProperty(key, systemProperties.getProperty(key)); - } - } - return overriddenProperties; - } - - public static DockerClientConfigBuilder createDefaultConfigBuilder() { - return createDefaultConfigBuilder(System.getenv(), System.getProperties()); - } - - /** - * Allows you to build the config without system environment interfering for more robust testing - */ - static DockerClientConfigBuilder createDefaultConfigBuilder(Map env, Properties systemProperties) { - Properties properties = loadIncludedDockerProperties(systemProperties); - properties = overrideDockerPropertiesWithSettingsFromUserHome(properties, systemProperties); - properties = overrideDockerPropertiesWithEnv(properties, env); - properties = overrideDockerPropertiesWithSystemProperties(properties, systemProperties); - return new DockerClientConfigBuilder().withProperties(properties); - } - - public URI getDockerHost() { - return dockerHost; - } - - public RemoteApiVersion getApiVersion() { - return apiVersion; - } - - public String getRegistryUsername() { - return registryUsername; - } - - public String getRegistryPassword() { - return registryPassword; - } - - public String getRegistryEmail() { - return registryEmail; - } - - public String getRegistryUrl() { - return registryUrl; - } - - public String getDockerConfig() { - return dockerConfig; - } - - public String getDockerCertPath() { - return dockerCertPath; - } - - public boolean getDockerTlsVerify() { - return dockerTlsVerify; - } - - private AuthConfig getAuthConfig() { - AuthConfig authConfig = null; - if (getRegistryUsername() != null && getRegistryPassword() != null && getRegistryEmail() != null - && getRegistryUrl() != null) { - authConfig = new AuthConfig() - .withUsername(getRegistryUsername()) - .withPassword(getRegistryPassword()) - .withEmail(getRegistryEmail()) - .withRegistryAddress(getRegistryUrl()); - } - return authConfig; - } - - public AuthConfig effectiveAuthConfig(String imageName) { - AuthConfig authConfig = null; - - File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); - - if (dockerCfgFile.exists() && dockerCfgFile.isFile() && imageName != null) { - AuthConfigFile authConfigFile; - try { - authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); - } catch (IOException e) { - throw new DockerClientException("Failed to parse dockerCfgFile", e); - } - ReposTag reposTag = NameParser.parseRepositoryTag(imageName); - HostnameReposName hostnameReposName = NameParser.resolveRepositoryName(reposTag.repos); - - authConfig = authConfigFile.resolveAuthConfig(hostnameReposName.hostname); - } - - AuthConfig otherAuthConfig = getAuthConfig(); - - if (otherAuthConfig != null) { - authConfig = otherAuthConfig; - } - - return authConfig; - } - - public AuthConfigurations getAuthConfigurations() { - File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); - if (dockerCfgFile.exists() && dockerCfgFile.isFile()) { - AuthConfigFile authConfigFile; - try { - authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); - } catch (IOException e) { - throw new DockerClientException("Failed to parse dockerCfgFile", e); - } - - return authConfigFile.getAuthConfigurations(); - } - - return new AuthConfigurations(); - } - - // CHECKSTYLE:OFF - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - DockerClientConfig that = (DockerClientConfig) o; - - return EqualsBuilder.reflectionEquals(this, that); - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - - // CHECKSTYLE:ON - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } - - public static class DockerClientConfigBuilder { - private URI dockerHost; - - private String apiVersion, registryUsername, registryPassword, registryEmail, registryUrl, dockerConfig, - dockerCertPath; - - private boolean dockerTlsVerify; - - /** - * This will set all fields in the builder to those contained in the Properties object. The Properties object should contain the - * following docker-java configuration keys: DOCKER_HOST, DOCKER_TLS_VERIFY, api.version, registry.username, registry.password, - * registry.email, DOCKER_CERT_PATH, and DOCKER_CONFIG. - */ - public DockerClientConfigBuilder withProperties(Properties p) { - return withDockerHost(p.getProperty(DOCKER_HOST)).withDockerTlsVerify(p.getProperty(DOCKER_TLS_VERIFY)) - .withDockerConfig(p.getProperty(DOCKER_CONFIG)).withDockerCertPath(p.getProperty(DOCKER_CERT_PATH)) - .withApiVersion(p.getProperty(API_VERSION)).withRegistryUsername(p.getProperty(REGISTRY_USERNAME)) - .withRegistryPassword(p.getProperty(REGISTRY_PASSWORD)) - .withRegistryEmail(p.getProperty(REGISTRY_EMAIL)).withRegistryUrl(p.getProperty(REGISTRY_URL)); - } - - /** - * configure DOCKER_HOST - */ - public final DockerClientConfigBuilder withDockerHost(String dockerHost) { - checkNotNull(dockerHost, "uri was not specified"); - this.dockerHost = URI.create(dockerHost); - return this; - } - - public final DockerClientConfigBuilder withApiVersion(RemoteApiVersion apiVersion) { - this.apiVersion = apiVersion.getVersion(); - return this; - } - - public final DockerClientConfigBuilder withApiVersion(String apiVersion) { - this.apiVersion = apiVersion; - return this; - } - - public final DockerClientConfigBuilder withRegistryUsername(String registryUsername) { - this.registryUsername = registryUsername; - return this; - } - - public final DockerClientConfigBuilder withRegistryPassword(String registryPassword) { - this.registryPassword = registryPassword; - return this; - } - - public final DockerClientConfigBuilder withRegistryEmail(String registryEmail) { - this.registryEmail = registryEmail; - return this; - } - - public DockerClientConfigBuilder withRegistryUrl(String registryUrl) { - this.registryUrl = registryUrl; - return this; - } - - public final DockerClientConfigBuilder withDockerCertPath(String dockerCertPath) { - this.dockerCertPath = dockerCertPath; - return this; - } - - public final DockerClientConfigBuilder withDockerConfig(String dockerConfig) { - this.dockerConfig = dockerConfig; - return this; - } - - public final DockerClientConfigBuilder withDockerTlsVerify(String dockerTlsVerify) { - if (dockerTlsVerify != null) { - String trimmed = dockerTlsVerify.trim(); - this.dockerTlsVerify = "true".equalsIgnoreCase(trimmed) || "1".equals(trimmed); - } else { - this.dockerTlsVerify = false; - } - return this; - } - - public final DockerClientConfigBuilder withDockerTlsVerify(Boolean dockerTlsVerify) { - this.dockerTlsVerify = dockerTlsVerify; - return this; - } + SSLConfig getSSLConfig(); - public DockerClientConfig build() { - return new DockerClientConfig(dockerHost, dockerConfig, apiVersion, registryUrl, registryUsername, - registryPassword, registryEmail, dockerCertPath, dockerTlsVerify); - } - } } diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 765f562bd..e11ca4f30 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -125,7 +125,7 @@ public class DockerClientImpl implements Closeable, DockerClient { private DockerCmdExecFactory dockerCmdExecFactory; private DockerClientImpl() { - this(DockerClientConfig.createDefaultConfigBuilder().build()); + this(DefaultDockerClientConfig.createDefaultConfigBuilder().build()); } private DockerClientImpl(String serverUrl) { @@ -138,7 +138,7 @@ private DockerClientImpl(DockerClientConfig dockerClientConfig) { } private static DockerClientConfig configWithServerUrl(String serverUrl) { - return DockerClientConfig.createDefaultConfigBuilder().withDockerHost(serverUrl).build(); + return DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost(serverUrl).build(); } public static DockerClientImpl getInstance() { diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 5d489bbc5..d71cc33ae 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -18,6 +18,7 @@ import javax.ws.rs.client.WebTarget; import com.github.dockerjava.api.command.UpdateContainerCmd; + import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -83,7 +84,6 @@ import com.github.dockerjava.api.command.RenameContainerCmd; import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.core.LocalDirectorySSLConfig; import com.github.dockerjava.jaxrs.connector.ApacheConnectorProvider; import com.github.dockerjava.jaxrs.filter.JsonClientFilter; import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; @@ -114,8 +114,6 @@ public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { private DockerClientConfig dockerClientConfig; - SSLContext sslContext = null; - @Override public void init(DockerClientConfig dockerClientConfig) { checkNotNull(dockerClientConfig, "config was not specified"); @@ -160,18 +158,16 @@ public void init(DockerClientConfig dockerClientConfig) { String protocol = null; - if (dockerClientConfig.getDockerTlsVerify()) { - protocol = "https"; + SSLContext sslContext = null; - try { - - if (sslContext == null) { - sslContext = new LocalDirectorySSLConfig(dockerClientConfig.getDockerCertPath()).getSSLContext(); - } + try { + sslContext = dockerClientConfig.getSSLConfig().getSSLContext(); + } catch (Exception ex) { + throw new DockerClientException("Error in SSL Configuration", ex); + } - } catch (Exception ex) { - throw new DockerClientException("Error in SSL Configuration", ex); - } + if (sslContext != null) { + protocol = "https"; } else { protocol = "http"; } @@ -529,12 +525,6 @@ public void close() throws IOException { client.close(); } - @Override - public DockerCmdExecFactoryImpl withSSLContext(SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - public DockerCmdExecFactoryImpl withReadTimeout(Integer readTimeout) { this.readTimeout = readTimeout; return this; diff --git a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java index 8f704c7af..1f55c61a8 100644 --- a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java @@ -53,7 +53,7 @@ import com.github.dockerjava.api.command.RenameContainerCmd; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.DockerClientImpl; -import com.github.dockerjava.core.LocalDirectorySSLConfig; +import com.github.dockerjava.core.SSLConfig; import com.github.dockerjava.netty.exec.AttachContainerCmdExec; import com.github.dockerjava.netty.exec.AuthCmdExec; import com.github.dockerjava.netty.exec.BuildImageCmdExec; @@ -123,7 +123,6 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -168,8 +167,6 @@ public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { private NettyInitializer nettyInitializer; - private SSLContext sslContext = null; - private ChannelProvider channelProvider = new ChannelProvider() { @Override public DuplexChannel getChannel() { @@ -270,12 +267,10 @@ public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { DuplexChannel channel = (DuplexChannel) bootstrap.connect(host, port).sync().channel(); - if (dockerClientConfig.getDockerTlsVerify()) { - final SslHandler ssl = initSsl(dockerClientConfig); + final SslHandler ssl = initSsl(dockerClientConfig); - if (ssl != null) { - channel.pipeline().addFirst(ssl); - } + if (ssl != null) { + channel.pipeline().addFirst(ssl); } return channel; @@ -288,18 +283,19 @@ private SslHandler initSsl(DockerClientConfig dockerClientConfig) { String host = dockerClientConfig.getDockerHost().getHost(); int port = dockerClientConfig.getDockerHost().getPort(); - if (sslContext == null) { - sslContext = new LocalDirectorySSLConfig(dockerClientConfig.getDockerCertPath()).getSSLContext(); - } + final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); + + if (sslConfig != null && sslConfig.getSSLContext() != null) { - SSLEngine engine = sslContext.createSSLEngine(host, port); - engine.setUseClientMode(true); - engine.setSSLParameters(enableHostNameVerification(engine.getSSLParameters())); + SSLEngine engine = sslConfig.getSSLContext().createSSLEngine(host, port); + engine.setUseClientMode(true); + engine.setSSLParameters(enableHostNameVerification(engine.getSSLParameters())); - // in the future we may use HostnameVerifier like here: - // https://github.com/AsyncHttpClient/async-http-client/blob/1.8.x/src/main/java/com/ning/http/client/providers/netty/NettyConnectListener.java#L76 + // in the future we may use HostnameVerifier like here: + // https://github.com/AsyncHttpClient/async-http-client/blob/1.8.x/src/main/java/com/ning/http/client/providers/netty/NettyConnectListener.java#L76 - ssl = new SslHandler(engine); + ssl = new SslHandler(engine); + } } catch (Exception e) { throw new RuntimeException(e); @@ -577,12 +573,6 @@ public void close() throws IOException { eventLoopGroup.shutdownGracefully(); } - @Override - public DockerCmdExecFactory withSSLContext(SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - private WebTarget getBaseResource() { return new WebTarget(channelProvider); } diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index 1a52bbd3f..e6cc00ac0 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -29,7 +29,7 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.Volume; import com.github.dockerjava.core.DockerClientBuilder; -import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.core.TestDockerCmdExecFactory; import com.github.dockerjava.core.command.BuildImageResultCallback; import com.github.dockerjava.core.command.LogContainerResultCallback; @@ -68,12 +68,12 @@ public void beforeTest() throws Exception { LOG.info("======================= END OF BEFORETEST =======================\n\n"); } - private DockerClientConfig config() { + private DefaultDockerClientConfig config() { return config(null); } - protected DockerClientConfig config(String password) { - DockerClientConfig.DockerClientConfigBuilder builder = DockerClientConfig.createDefaultConfigBuilder() + protected DefaultDockerClientConfig config(String password) { + DefaultDockerClientConfig.Builder builder = DefaultDockerClientConfig.createDefaultConfigBuilder() .withRegistryUrl("https://index.docker.io/v1/"); if (password != null) { builder = builder.withRegistryPassword(password); diff --git a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java similarity index 54% rename from src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java rename to src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java index ee679a0af..55ec38015 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java @@ -19,16 +19,16 @@ import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.model.AuthConfig; -public class DockerClientConfigTest { +public class DefaultDockerClientConfigTest { - public static final DockerClientConfig EXAMPLE_CONFIG = newExampleConfig(); + public static final DefaultDockerClientConfig EXAMPLE_CONFIG = newExampleConfig(); - private static DockerClientConfig newExampleConfig() { + private static DefaultDockerClientConfig newExampleConfig() { String dockerCertPath = dockerCertPath(); - return new DockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - dockerCertPath, true); + return new DefaultDockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + new LocalDirectorySSLConfig(dockerCertPath)); } private static String homeDir() { @@ -49,7 +49,7 @@ public void environmentDockerHost() throws Exception { // given docker host in env Map env = new HashMap(); - env.put(DockerClientConfig.DOCKER_HOST, "tcp://baz:8768"); + env.put(DefaultDockerClientConfig.DOCKER_HOST, "tcp://baz:8768"); // and it looks to be SSL disabled env.remove("DOCKER_CERT_PATH"); @@ -59,7 +59,7 @@ public void environmentDockerHost() throws Exception { systemProperties.setProperty("user.home", homeDir()); // when you build a config - DockerClientConfig config = buildConfig(env, systemProperties); + DefaultDockerClientConfig config = buildConfig(env, systemProperties); assertEquals(config.getDockerHost(), URI.create("tcp://baz:8768")); } @@ -69,25 +69,25 @@ public void environment() throws Exception { // given a default config in env properties Map env = new HashMap(); - env.put(DockerClientConfig.DOCKER_HOST, "tcp://foo"); - env.put(DockerClientConfig.API_VERSION, "apiVersion"); - env.put(DockerClientConfig.REGISTRY_USERNAME, "registryUsername"); - env.put(DockerClientConfig.REGISTRY_PASSWORD, "registryPassword"); - env.put(DockerClientConfig.REGISTRY_EMAIL, "registryEmail"); - env.put(DockerClientConfig.REGISTRY_URL, "registryUrl"); - env.put(DockerClientConfig.DOCKER_CONFIG, "dockerConfig"); - env.put(DockerClientConfig.DOCKER_CERT_PATH, dockerCertPath()); - env.put(DockerClientConfig.DOCKER_TLS_VERIFY, "1"); + env.put(DefaultDockerClientConfig.DOCKER_HOST, "tcp://foo"); + env.put(DefaultDockerClientConfig.API_VERSION, "apiVersion"); + env.put(DefaultDockerClientConfig.REGISTRY_USERNAME, "registryUsername"); + env.put(DefaultDockerClientConfig.REGISTRY_PASSWORD, "registryPassword"); + env.put(DefaultDockerClientConfig.REGISTRY_EMAIL, "registryEmail"); + env.put(DefaultDockerClientConfig.REGISTRY_URL, "registryUrl"); + env.put(DefaultDockerClientConfig.DOCKER_CONFIG, "dockerConfig"); + env.put(DefaultDockerClientConfig.DOCKER_CERT_PATH, dockerCertPath()); + env.put(DefaultDockerClientConfig.DOCKER_TLS_VERIFY, "1"); // when you build a config - DockerClientConfig config = buildConfig(env, new Properties()); + DefaultDockerClientConfig config = buildConfig(env, new Properties()); // then we get the example object assertEquals(config, EXAMPLE_CONFIG); } - private DockerClientConfig buildConfig(Map env, Properties systemProperties) { - return DockerClientConfig.createDefaultConfigBuilder(env, systemProperties).build(); + private DefaultDockerClientConfig buildConfig(Map env, Properties systemProperties) { + return DefaultDockerClientConfig.createDefaultConfigBuilder(env, systemProperties).build(); } @Test @@ -99,7 +99,7 @@ public void defaults() throws Exception { systemProperties.setProperty("user.home", homeDir()); // when you build config - DockerClientConfig config = buildConfig(Collections. emptyMap(), systemProperties); + DefaultDockerClientConfig config = buildConfig(Collections. emptyMap(), systemProperties); // then the cert path is as expected assertEquals(config.getDockerHost(), URI.create("unix:///var/run/docker.sock")); @@ -107,7 +107,7 @@ public void defaults() throws Exception { assertEquals(config.getRegistryUrl(), AuthConfig.DEFAULT_SERVER_ADDRESS); assertEquals(config.getApiVersion(), RemoteApiVersion.unknown()); assertEquals(config.getDockerConfig(), homeDir() + "/.docker"); - assertNull(config.getDockerCertPath()); + assertNull(config.getSSLConfig()); } @Test @@ -115,18 +115,18 @@ public void systemProperties() throws Exception { // given system properties based on the example Properties systemProperties = new Properties(); - systemProperties.put(DockerClientConfig.DOCKER_HOST, "tcp://foo"); - systemProperties.put(DockerClientConfig.API_VERSION, "apiVersion"); - systemProperties.put(DockerClientConfig.REGISTRY_USERNAME, "registryUsername"); - systemProperties.put(DockerClientConfig.REGISTRY_PASSWORD, "registryPassword"); - systemProperties.put(DockerClientConfig.REGISTRY_EMAIL, "registryEmail"); - systemProperties.put(DockerClientConfig.REGISTRY_URL, "registryUrl"); - systemProperties.put(DockerClientConfig.DOCKER_CONFIG, "dockerConfig"); - systemProperties.put(DockerClientConfig.DOCKER_CERT_PATH, dockerCertPath()); - systemProperties.put(DockerClientConfig.DOCKER_TLS_VERIFY, "1"); + systemProperties.put(DefaultDockerClientConfig.DOCKER_HOST, "tcp://foo"); + systemProperties.put(DefaultDockerClientConfig.API_VERSION, "apiVersion"); + systemProperties.put(DefaultDockerClientConfig.REGISTRY_USERNAME, "registryUsername"); + systemProperties.put(DefaultDockerClientConfig.REGISTRY_PASSWORD, "registryPassword"); + systemProperties.put(DefaultDockerClientConfig.REGISTRY_EMAIL, "registryEmail"); + systemProperties.put(DefaultDockerClientConfig.REGISTRY_URL, "registryUrl"); + systemProperties.put(DefaultDockerClientConfig.DOCKER_CONFIG, "dockerConfig"); + systemProperties.put(DefaultDockerClientConfig.DOCKER_CERT_PATH, dockerCertPath()); + systemProperties.put(DefaultDockerClientConfig.DOCKER_TLS_VERIFY, "1"); // when you build new config - DockerClientConfig config = buildConfig(Collections. emptyMap(), systemProperties); + DefaultDockerClientConfig config = buildConfig(Collections. emptyMap(), systemProperties); // then it is the same as the example assertEquals(config, EXAMPLE_CONFIG); @@ -136,50 +136,46 @@ public void systemProperties() throws Exception { @Test public void serializableTest() { final byte[] serialized = SerializationUtils.serialize(EXAMPLE_CONFIG); - final DockerClientConfig deserialized = (DockerClientConfig) SerializationUtils.deserialize(serialized); + final DefaultDockerClientConfig deserialized = (DefaultDockerClientConfig) SerializationUtils.deserialize(serialized); assertThat("Deserialized object mush match source object", deserialized, equalTo(EXAMPLE_CONFIG)); } - @Test(expectedExceptions = DockerClientException.class) - public void testTlsVerifyAndCertPathNull() throws Exception { - new DockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - null, true); + @Test() + public void testSslContextEmpty() throws Exception { + new DefaultDockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + null); } - @Test(expectedExceptions = DockerClientException.class) - public void testTlsVerifyAndCertPathEmpty() throws Exception { - new DockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - "", true); - } + @Test() public void testTlsVerifyAndCertPath() throws Exception { - new DockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - dockerCertPath(), true); + new DefaultDockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + new LocalDirectorySSLConfig(dockerCertPath())); } @Test(expectedExceptions = DockerClientException.class) public void testWrongHostScheme() throws Exception { - new DockerClientConfig(URI.create("http://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - null, false); + new DefaultDockerClientConfig(URI.create("http://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + null); } @Test() public void testTcpHostScheme() throws Exception { - new DockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - null, false); + new DefaultDockerClientConfig(URI.create("tcp://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + null); } @Test() public void testUnixHostScheme() throws Exception { - new DockerClientConfig(URI.create("unix://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", - null, false); + new DefaultDockerClientConfig(URI.create("unix://foo"), "dockerConfig", "apiVersion", "registryUrl", "registryUsername", "registryPassword", "registryEmail", + null); } @Test public void withDockerTlsVerify() throws Exception { - DockerClientConfig.DockerClientConfigBuilder builder = new DockerClientConfig.DockerClientConfigBuilder(); + DefaultDockerClientConfig.Builder builder = new DefaultDockerClientConfig.Builder(); Field field = builder.getClass().getDeclaredField("dockerTlsVerify"); field.setAccessible(true); diff --git a/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java index 7ea8bace5..1df4636ba 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java @@ -12,7 +12,7 @@ public class DockerClientImplTest { @Test public void configuredInstanceAuthConfig() throws Exception { // given a config with null serverAddress - DockerClientConfig dockerClientConfig = new DockerClientConfig(URI.create("tcp://foo"), null, null, null, "", "", "", null, false); + DefaultDockerClientConfig dockerClientConfig = new DefaultDockerClientConfig(URI.create("tcp://foo"), null, null, null, "", "", "", null); DockerClientImpl dockerClient = DockerClientImpl.getInstance(dockerClientConfig); // when we get the auth config diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index aee8a60a8..48ea1e164 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -58,7 +58,6 @@ import com.github.dockerjava.api.command.WaitContainerCmd; import com.github.dockerjava.api.model.BuildResponseItem; -import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.SecureRandom; import java.util.ArrayList; @@ -431,9 +430,4 @@ public List getVolumeNames() { public List getNetworkIds() { return new ArrayList<>(networkIds); } - - @Override - public DockerCmdExecFactory withSSLContext(SSLContext sslContext) { - return delegate.withSSLContext(sslContext); - } } From 006fd9b061066ba76c7412009292ec2e644417a4 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Mon, 13 Jun 2016 23:00:05 +0200 Subject: [PATCH 073/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f3b7e9b9..ad5885775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Change Log --- All changes +* [#596] (https://github.com/docker-java/docker-java/pull/596) Refactor configuration of SSL to allow override with custom config * [#529] (https://github.com/docker-java/docker-java/pull/529) Refactor CertUtils. Support ECDSA and PrivateKey v3.0.0 From 2f8d317585c0d4b4e9fc45d122a3a02ad31a1d72 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 14 Jun 2016 00:02:15 +0300 Subject: [PATCH 074/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad5885775..10065afad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Change Log All changes * [#596] (https://github.com/docker-java/docker-java/pull/596) Refactor configuration of SSL to allow override with custom config * [#529] (https://github.com/docker-java/docker-java/pull/529) Refactor CertUtils. Support ECDSA and PrivateKey +* [#593] (https://github.com/docker-java/docker-java/pull/593) Added Device.parse() method with simple verification. v3.0.0 --- From efb424523971ddb50488bc3b03a52f32d8bcc5b9 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 15 Jun 2016 23:43:44 +0300 Subject: [PATCH 075/780] Allow null value. boolean <-> Boolean error --- .../github/dockerjava/core/DefaultDockerClientConfig.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java index 4641f9d3c..b21e227ec 100644 --- a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -1,6 +1,7 @@ package com.github.dockerjava.core; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.commons.lang.BooleanUtils.isTrue; import java.io.File; import java.io.FileInputStream; @@ -319,7 +320,7 @@ public static class Builder { private String apiVersion, registryUsername, registryPassword, registryEmail, registryUrl, dockerConfig, dockerCertPath; - private boolean dockerTlsVerify; + private Boolean dockerTlsVerify; private SSLConfig customSslConfig = null; @@ -419,7 +420,7 @@ public DefaultDockerClientConfig build() { SSLConfig sslConfig = null; if (customSslConfig == null) { - if (dockerTlsVerify) { + if (isTrue(dockerTlsVerify)) { dockerCertPath = checkDockerCertPath(dockerCertPath); sslConfig = new LocalDirectorySSLConfig(dockerCertPath); } From 019770cc8dda7fcdcbede13fa7cefcdb072589ed Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 16 Jun 2016 09:53:49 +0300 Subject: [PATCH 076/780] Fix tests --- .../core/DefaultDockerClientConfigTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java index 55ec38015..54e70c511 100644 --- a/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java @@ -180,25 +180,25 @@ public void withDockerTlsVerify() throws Exception { field.setAccessible(true); builder.withDockerTlsVerify(""); - assertThat(field.getBoolean(builder), is(false)); + assertThat((Boolean) field.get(builder), is(false)); builder.withDockerTlsVerify("false"); - assertThat(field.getBoolean(builder), is(false)); + assertThat((Boolean) field.get(builder), is(false)); builder.withDockerTlsVerify("FALSE"); - assertThat(field.getBoolean(builder), is(false)); + assertThat((Boolean) field.get(builder), is(false)); builder.withDockerTlsVerify("true"); - assertThat(field.getBoolean(builder), is(true)); + assertThat((Boolean) field.get(builder), is(true)); builder.withDockerTlsVerify("TRUE"); - assertThat(field.getBoolean(builder), is(true)); + assertThat((Boolean) field.get(builder), is(true)); builder.withDockerTlsVerify("0"); - assertThat(field.getBoolean(builder), is(false)); + assertThat((Boolean) field.get(builder), is(false)); builder.withDockerTlsVerify("1"); - assertThat(field.getBoolean(builder), is(true)); + assertThat((Boolean) field.get(builder), is(true)); } } From 2116ae00f5ca5e5630491bc68a4208adc969b1dc Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sat, 18 Jun 2016 00:12:52 +0300 Subject: [PATCH 077/780] Docker travis for ITs (#606) Fast build - without integration tests. ITs - against different docker versions. --- .travis.yml | 37 ++- get-docker-com.sh | 313 ++++++++++++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 6 +- src/test/resources/travis-logback.xml | 19 ++ travis-after-success.sh | 5 +- travis-before-install.sh | 43 +++ 6 files changed, 418 insertions(+), 5 deletions(-) create mode 100755 get-docker-com.sh create mode 100644 src/test/resources/travis-logback.xml create mode 100755 travis-before-install.sh diff --git a/.travis.yml b/.travis.yml index 1d78b3bb9..4e980294e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,40 @@ +sudo: required +dist: trusty language: java + +services: + - docker + jdk: - oraclejdk7 + +env: + global: + - DOCKER_TLS_VERIFY="" + + matrix: + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" FAST_BUILD=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" + - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" + - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" + - repo="experimental" DOCKER_HOST="tcp://127.0.0.1:2375" + - repo="experimental" DOCKER_HOST="unix:///var/run/docker.sock" + +cache: + directories: + - $HOME/.travis_cache +# - $HOME/.m2 install would pollute it + before_install: - - pip install --user codecov + - pip install --user codecov + - ./travis-before-install.sh + +script: if [ "${FAST_BUILD}" == true ]; then mvn package ; else mvn verify; fi + after_success: - - ./travis-after-success.sh + - ./travis-after-success.sh + +after_script: + - sudo cat /var/log/upstart/docker.log diff --git a/get-docker-com.sh b/get-docker-com.sh new file mode 100755 index 000000000..66ca4aefc --- /dev/null +++ b/get-docker-com.sh @@ -0,0 +1,313 @@ +#!/bin/sh +set -e +# +# This script is meant for quick & easy install via: +# 'curl -sSL https://get.docker.com/ | sh' +# or: +# 'wget -qO- https://get.docker.com/ | sh' +# +# For test builds (ie. release candidates): +# 'curl -fsSL https://test.docker.com/ | sh' +# or: +# 'wget -qO- https://test.docker.com/ | sh' +# +# For experimental builds: +# 'curl -fsSL https://experimental.docker.com/ | sh' +# or: +# 'wget -qO- https://experimental.docker.com/ | sh' +# +# Docker Maintainers: +# To update this script on https://get.docker.com, +# use hack/release.sh during a normal release, +# or the following one-liner for script hotfixes: +# aws s3 cp --acl public-read hack/install.sh s3://get.docker.com/index +# + +url="https://get.docker.com/" +apt_url="https://apt.dockerproject.org" +yum_url="https://yum.dockerproject.org" +gpg_fingerprint="58118E89F3A912897C070ADBF76221572C52609D" + +key_servers=" +ha.pool.sks-keyservers.net +pgp.mit.edu +keyserver.ubuntu.com +" + +command_exists() { + command -v "$@" > /dev/null 2>&1 +} + +semverParse() { + major="${1%%.*}" + minor="${1#$major.}" + minor="${minor%%.*}" + patch="${1#$major.$minor.}" + patch="${patch%%[-.]*}" +} + +do_install() { + case "$(uname -m)" in + *64) + ;; + *) + cat >&2 <<-'EOF' + Error: you are not using a 64bit platform. + Docker currently only supports 64bit platforms. + EOF + exit 1 + ;; + esac + + user="$(id -un 2>/dev/null || true)" + + sh_c='sh -c' + if [ "$user" != 'root' ]; then + if command_exists sudo; then + sh_c='sudo -E sh -c' + elif command_exists su; then + sh_c='su -c' + else + cat >&2 <<-'EOF' + Error: this installer needs the ability to run commands as root. + We are unable to find either "sudo" or "su" available to make this happen. + EOF + exit 1 + fi + fi + + curl='' + if command_exists curl; then + curl='curl -sSL' + elif command_exists wget; then + curl='wget -qO-' + elif command_exists busybox && busybox --list-modules | grep -q wget; then + curl='busybox wget -qO-' + fi + + # check to see which repo they are trying to install from + if [ -z "$repo" ]; then + repo='main' + if [ "https://test.docker.com/" = "$url" ]; then + repo='testing' + elif [ "https://experimental.docker.com/" = "$url" ]; then + repo='experimental' + fi + fi + + # perform some very rudimentary platform detection + lsb_dist='' + dist_version='' + if command_exists lsb_release; then + lsb_dist="$(lsb_release -si)" + fi + if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then + lsb_dist="$(. /etc/lsb-release && echo "$DISTRIB_ID")" + fi + if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then + lsb_dist='debian' + fi + if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then + lsb_dist='fedora' + fi + if [ -z "$lsb_dist" ] && [ -r /etc/oracle-release ]; then + lsb_dist='oracleserver' + fi + if [ -z "$lsb_dist" ]; then + if [ -r /etc/centos-release ] || [ -r /etc/redhat-release ]; then + lsb_dist='centos' + fi + fi + if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then + lsb_dist="$(. /etc/os-release && echo "$ID")" + fi + + lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')" + + case "$lsb_dist" in + + ubuntu) + if command_exists lsb_release; then + dist_version="$(lsb_release --codename | cut -f2)" + fi + if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then + dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")" + fi + ;; + + debian) + dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')" + case "$dist_version" in + 8) + dist_version="jessie" + ;; + 7) + dist_version="wheezy" + ;; + esac + ;; + + oracleserver) + # need to switch lsb_dist to match yum repo URL + lsb_dist="oraclelinux" + dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')" + ;; + + fedora|centos) + dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')" + ;; + + *) + if command_exists lsb_release; then + dist_version="$(lsb_release --codename | cut -f2)" + fi + if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then + dist_version="$(. /etc/os-release && echo "$VERSION_ID")" + fi + ;; + + + esac + + + # Run setup for each distro accordingly + case "$lsb_dist" in + ubuntu|debian) + export DEBIAN_FRONTEND=noninteractive + + did_apt_get_update= + apt_get_update() { + if [ -z "$did_apt_get_update" ]; then + ( set -x; $sh_c 'sleep 3; apt-get update' ) + did_apt_get_update=1 + fi + } + + # aufs is preferred over devicemapper; try to ensure the driver is available. + if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then + if uname -r | grep -q -- '-generic' && dpkg -l 'linux-image-*-generic' | grep -qE '^ii|^hi' 2>/dev/null; then + kern_extras="linux-image-extra-$(uname -r) linux-image-extra-virtual" + + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true + + if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then + echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)' + echo >&2 ' but we still have no AUFS. Docker may not work. Proceeding anyways!' + ( set -x; sleep 10 ) + fi + else + echo >&2 'Warning: current kernel is not supported by the linux-image-extra-virtual' + echo >&2 ' package. We have no AUFS support. Consider installing the packages' + echo >&2 ' linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.' + ( set -x; sleep 10 ) + fi + fi + + # install apparmor utils if they're missing and apparmor is enabled in the kernel + # otherwise Docker will fail to start + if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then + if command -v apparmor_parser >/dev/null 2>&1; then + echo 'apparmor is enabled in the kernel and apparmor utils were already installed' + else + echo 'apparmor is enabled in the kernel, but apparmor_parser missing' + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q apparmor' ) + fi + fi + + if [ ! -e /usr/lib/apt/methods/https ]; then + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https ca-certificates' ) + fi + if [ -z "$curl" ]; then + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q curl ca-certificates' ) + curl='curl -sSL' + fi + ( + set -x + for key_server in $key_servers ; do + $sh_c "apt-key adv --keyserver hkp://${key_server}:80 --recv-keys ${gpg_fingerprint}" && break + done + $sh_c "apt-key adv -k ${gpg_fingerprint} >/dev/null" + $sh_c "mkdir -p /etc/apt/sources.list.d" + $sh_c "echo deb [arch=$(dpkg --print-architecture)] ${apt_url}/repo ${lsb_dist}-${dist_version} ${repo} > /etc/apt/sources.list.d/docker.list" + $sh_c 'sleep 3; apt-get update' + if [ -z "$DOCKER_VERSION" ]; then + $sh_c 'apt-get -o Dpkg::Options::="--force-confnew" install -y -q docker-engine' + else + $sh_c "apt-get -o Dpkg::Options::=\"--force-confnew\" install -y -q docker-engine=$DOCKER_VERSION" + fi + ) + exit 0 + ;; + + fedora|centos|oraclelinux) + $sh_c "cat >/etc/yum.repos.d/docker-${repo}.repo" <<-EOF + [docker-${repo}-repo] + name=Docker ${repo} Repository + baseurl=${yum_url}/repo/${repo}/${lsb_dist}/${dist_version} + enabled=1 + gpgcheck=1 + gpgkey=${yum_url}/gpg + EOF + if [ "$lsb_dist" = "fedora" ] && [ "$dist_version" -ge "22" ]; then + ( + set -x + $sh_c 'sleep 3; dnf -y -q install docker-engine' + ) + else + ( + set -x + $sh_c 'sleep 3; yum -y -q install docker-engine' + ) + fi + exit 0 + ;; + gentoo) + if [ "$url" = "https://test.docker.com/" ]; then + # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output + cat >&2 <<-'EOF' + + You appear to be trying to install the latest nightly build in Gentoo.' + The portage tree should contain the latest stable release of Docker, but' + if you want something more recent, you can always use the live ebuild' + provided in the "docker" overlay available via layman. For more' + instructions, please see the following URL:' + + https://github.com/tianon/docker-overlay#using-this-overlay' + + After adding the "docker" overlay, you should be able to:' + + emerge -av =app-emulation/docker-9999' + + EOF + exit 1 + fi + + ( + set -x + $sh_c 'sleep 3; emerge app-emulation/docker' + ) + exit 0 + ;; + esac + + # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output + cat >&2 <<-'EOF' + + Either your platform is not easily detectable, is not supported by this + installer script (yet - PRs welcome! [hack/install.sh]), or does not yet have + a package for Docker. Please visit the following URL for more detailed + installation instructions: + + https://docs.docker.com/engine/installation/ + + EOF + exit 1 +} + +# wrapped up in a function so that we have some protection against only getting +# half the file during "curl | sh" +do_install \ 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 d71cc33ae..fc74e1fde 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -19,6 +19,7 @@ import com.github.dockerjava.api.command.UpdateContainerCmd; +import com.github.dockerjava.core.SSLConfig; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -161,7 +162,10 @@ public void init(DockerClientConfig dockerClientConfig) { SSLContext sslContext = null; try { - sslContext = dockerClientConfig.getSSLConfig().getSSLContext(); + final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); + if (sslConfig != null) { + sslContext = sslConfig.getSSLContext(); + } } catch (Exception ex) { throw new DockerClientException("Error in SSL Configuration", ex); } diff --git a/src/test/resources/travis-logback.xml b/src/test/resources/travis-logback.xml new file mode 100644 index 000000000..250cbd335 --- /dev/null +++ b/src/test/resources/travis-logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + diff --git a/travis-after-success.sh b/travis-after-success.sh index aeb3c12c7..6d198daf5 100755 --- a/travis-after-success.sh +++ b/travis-after-success.sh @@ -1,9 +1,10 @@ #!/usr/bin/env bash + codecov -if [[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_PULL_REQUEST == "false" ]]; +if [[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_PULL_REQUEST == "false" ]] && [[ $DEPLOY == "true" ]]; then - cat << EOF >> ~/settings.xml + cat <> ~/settings.xml diff --git a/travis-before-install.sh b/travis-before-install.sh new file mode 100755 index 000000000..0253ce6bf --- /dev/null +++ b/travis-before-install.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + + +if [ "$FAST_BUILD" == true ]; then + echo "Fast build, skipping docker installations." + exit 0 +fi + +set -exu + +docker info +docker version + +sudo -E apt-get update +sudo -E apt-get install -q -y wget +sudo -E apt-get -q -y --purge remove docker-engine +sudo -E apt-cache policy docker-engine + +./get-docker-com.sh +#mkdir "${HOME}/.cache" || : +#pushd "${HOME}/.cache" +# wget -N "https://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_${DOCKER_VERSION}_amd64.deb" +# sudo apt-get -f install +# sudo dpkg -i "$(ls *${DOCKER_VERSION}*)" +#popd +#rm -f "src/test/resources/logback.xml" +mv "src/test/resources/travis-logback.xml" "src/test/resources/logback.xml" + +echo 'DOCKER_OPTS="-H=unix:///var/run/docker.sock -H=tcp://127.0.0.1:2375"' | sudo tee -a /etc/default/docker +sudo -E restart docker +sleep 10 +docker version +docker info + +set +u + +cat < "${HOME}/.docker-java.properties" +registry.username=${registry_username} +registry.password=${registry_password} +registry.email=${registry_email} +registry.url=https://index.docker.io/v1/ + +EOF From 2bd837f0187edbb85888f4d2a43c05b487d1858b Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 20 Jun 2016 10:54:50 +0300 Subject: [PATCH 078/780] Coverity (#613) - more badges - coverity verification on master on main (fast/successful) build. --- .travis.yml | 15 ++++++++++++--- README.md | 2 ++ travis-before-install.sh | 5 +++++ travis-script.sh | 22 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100755 travis-script.sh diff --git a/.travis.yml b/.travis.yml index 4e980294e..b99125afc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,14 +8,22 @@ services: jdk: - oraclejdk7 +install: true + env: global: - DOCKER_TLS_VERIFY="" + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + # via the "travis encrypt" command using the project repo's public key + - secure: "GonzmzvnXsTNQV+6sKtBSSPiwbpMZjxumNt5LFp1g77/afLxw9kl2EQOXbUe308vFOwRVqeY7drBvNJa8aJkTUClfMaGRjfZ9DUwm6doMKMUYrdEkYoQTcH7yDX5K5w9MT6m+Izj+BK2gB7nK3yFlYG6COeXCdFbQ4/cf3/xfRc=" + - COVERITY_SCAN_PROJECT_NAME="docker-java/docker-java" + - COVERITY_SCAN_BRANCH_PATTERN="master" + - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" FAST_BUILD=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true FAST_BUILD=true COVERITY=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" @@ -31,7 +39,8 @@ before_install: - pip install --user codecov - ./travis-before-install.sh -script: if [ "${FAST_BUILD}" == true ]; then mvn package ; else mvn verify; fi +script: + - ./travis-script.sh after_success: - ./travis-after-success.sh diff --git a/README.md b/README.md index e47b6e5a4..71fbaa11e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ [![Build Status](https://travis-ci.org/docker-java/docker-java.svg?branch=master)](https://travis-ci.org/docker-java/docker-java) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) +[![codecov.io](http://codecov.io/github/docker-java/docker-java/coverage.svg?branch=master)](http://codecov.io/github/docker-java/docker-java?branch=master) # docker-java diff --git a/travis-before-install.sh b/travis-before-install.sh index 0253ce6bf..13034fc74 100755 --- a/travis-before-install.sh +++ b/travis-before-install.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash +sudo apt-get install -y -q ca-certificates + +echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt + + if [ "$FAST_BUILD" == true ]; then echo "Fast build, skipping docker installations." exit 0 diff --git a/travis-script.sh b/travis-script.sh new file mode 100755 index 000000000..0a5fdd38c --- /dev/null +++ b/travis-script.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -ex + +IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"` + + +if [ "${FAST_BUILD}" == "true" ]; then + if [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + export COVERITY_SCAN_BUILD_COMMAND="mvn package" + curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + else + mvn package + fi +else + if [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + COVERITY_SCAN_BUILD_COMMAND="mvn verify" + curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + else + mvn verify + fi +fi From 197e72c268d3c0a555b78095987864565f23f5c9 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 29 Jun 2016 23:58:33 +0300 Subject: [PATCH 079/780] Versioneye references. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 71fbaa11e..47873ccfe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![Build Status](https://travis-ci.org/docker-java/docker-java.svg?branch=master)](https://travis-ci.org/docker-java/docker-java) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) [![codecov.io](http://codecov.io/github/docker-java/docker-java/coverage.svg?branch=master)](http://codecov.io/github/docker-java/docker-java?branch=master) +[![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat-square)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) # docker-java From 2e79af92672df2d5b722dad5857ed43eebb16b77 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 10:30:51 +0300 Subject: [PATCH 080/780] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 47873ccfe..5fb385387 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) [![codecov.io](http://codecov.io/github/docker-java/docker-java/coverage.svg?branch=master)](http://codecov.io/github/docker-java/docker-java?branch=master) [![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat-square)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) +![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](https://github.com/docker-java/docker-java/blob/master/LICENSE) + # docker-java From 4b2ffe244493639b8fef0622ef2405cd95942cba Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 10:31:26 +0300 Subject: [PATCH 081/780] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fb385387..d50624c0d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) [![codecov.io](http://codecov.io/github/docker-java/docker-java/coverage.svg?branch=master)](http://codecov.io/github/docker-java/docker-java?branch=master) [![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat-square)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) -![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](https://github.com/docker-java/docker-java/blob/master/LICENSE) +[![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](https://github.com/docker-java/docker-java/blob/master/LICENSE) # docker-java From 04fa7e86584ad0d6a8d8bb4d7b8712bd193aa7cd Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 22:04:35 +0300 Subject: [PATCH 082/780] Fix it2 (#621) * Fix hasItem in test * Disable toolbox only tests --- .../core/command/CreateContainerCmdImplTest.java | 12 ++++++++---- .../core/command/UpdateContainerCmdImplTest.java | 8 ++++---- .../netty/exec/CreateContainerCmdExecTest.java | 12 ++++++++---- .../netty/exec/UpdateContainerCmdExecTest.java | 8 ++++---- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index a93e100c6..a9c0acb8c 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -45,6 +45,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItemInArray; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; @@ -191,9 +192,12 @@ public void createContainerWithVolumesFrom() throws DockerException { @Test public void createContainerWithEnv() throws Exception { + final String testVariable = "VARIABLE=success"; - CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE).withEnv("VARIABLE=success") - .withCmd("env").exec(); + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withEnv(testVariable) + .withCmd("env") + .exec(); LOG.info("Created container {}", container.toString()); @@ -201,11 +205,11 @@ public void createContainerWithEnv() throws Exception { InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - assertThat(Arrays.asList(inspectContainerResponse.getConfig().getEnv()), containsInAnyOrder("VARIABLE=success")); + assertThat(Arrays.asList(inspectContainerResponse.getConfig().getEnv()), hasItem(testVariable)); dockerClient.startContainerCmd(container.getId()).exec(); - assertThat(containerLog(container.getId()), containsString("VARIABLE=success")); + assertThat(containerLog(container.getId()), containsString(testVariable)); } @Test diff --git a/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java index c230fbb02..3c7a9fd47 100644 --- a/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java @@ -84,10 +84,10 @@ public void updateContainer() throws DockerException, IOException { // .withKernelMemory(52428800) Can not update kernel memory to a running container, please stop it first. .exec(); - // docker toolbox 1.10.1 - assertThat(updateResponse.getWarnings(), hasSize(1)); - assertThat(updateResponse.getWarnings().get(0), - is("Your kernel does not support Block I/O weight. Weight discarded.")); + // true only on docker toolbox (1.10.1) +// assertThat(updateResponse.getWarnings(), hasSize(1)); +// assertThat(updateResponse.getWarnings().get(0), +// is("Your kernel does not support Block I/O weight. Weight discarded.")); InspectContainerResponse inspectAfter = dockerClient.inspectContainerCmd(containerId).exec(); final HostConfig afterHostConfig = inspectAfter.getHostConfig(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index 3dbe21f16..ec35f930a 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -43,6 +43,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItemInArray; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; @@ -189,9 +190,12 @@ public void createContainerWithVolumesFrom() throws DockerException { @Test public void createContainerWithEnv() throws Exception { + final String testVariable = "VARIABLE=success"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withEnv("VARIABLE=success") - .withCmd("env").exec(); + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withEnv(testVariable) + .withCmd("env") + .exec(); LOG.info("Created container {}", container.toString()); @@ -199,11 +203,11 @@ public void createContainerWithEnv() throws Exception { InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - assertThat(Arrays.asList(inspectContainerResponse.getConfig().getEnv()), containsInAnyOrder("VARIABLE=success")); + assertThat(Arrays.asList(inspectContainerResponse.getConfig().getEnv()), hasItem(testVariable)); dockerClient.startContainerCmd(container.getId()).exec(); - assertThat(containerLog(container.getId()), containsString("VARIABLE=success")); + assertThat(containerLog(container.getId()), containsString(testVariable)); } @Test diff --git a/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java index e2907dc8a..1134afd6d 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java @@ -83,10 +83,10 @@ public void updateContainer() throws DockerException, IOException { // .withKernelMemory(52428800) Can not update kernel memory to a running container, please stop it first. .exec(); - // docker toolbox 1.10.1 - assertThat(updateResponse.getWarnings(), hasSize(1)); - assertThat(updateResponse.getWarnings().get(0), - is("Your kernel does not support Block I/O weight. Weight discarded.")); + // found only on docker toolbox (1.10.1) +// assertThat(updateResponse.getWarnings(), hasSize(1)); +// assertThat(updateResponse.getWarnings().get(0), +// is("Your kernel does not support Block I/O weight. Weight discarded.")); InspectContainerResponse inspectAfter = dockerClient.inspectContainerCmd(containerId).exec(); final HostConfig afterHostConfig = inspectAfter.getHostConfig(); From 0890ec30cdf8d33c639eabc23bd158323fb83966 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 22:09:11 +0300 Subject: [PATCH 083/780] [CID-125822] Fix resource leak --- .../dockerjava/jaxrs/async/AbstractCallbackNotifier.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java index 86f528af6..bd80a2d66 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java +++ b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java @@ -60,9 +60,7 @@ public Void call() throws Exception { return null; } - try { - InputStream inputStream = new WrappedResponseInputStream(response); - + try (InputStream inputStream = new WrappedResponseInputStream(response)) { if (resultCallback != null) { responseStreamProcessor.processResponseStream(inputStream, resultCallback); } From f74fc3dd51d454e561c66c6a0667525ce9d250de Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 22:49:41 +0300 Subject: [PATCH 084/780] Don't upload coverity for PRs --- travis-script.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/travis-script.sh b/travis-script.sh index 0a5fdd38c..e40de7f73 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -6,14 +6,14 @@ IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_ if [ "${FAST_BUILD}" == "true" ]; then - if [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then export COVERITY_SCAN_BUILD_COMMAND="mvn package" curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash else mvn package fi else - if [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then COVERITY_SCAN_BUILD_COMMAND="mvn verify" curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash else From ada726bbdb79bf850d571e8f184be1ad454892db Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 22:54:30 +0300 Subject: [PATCH 085/780] Update badges --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d50624c0d..159108dd8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ +[![Maven Central](https://img.shields.io/maven-central/v/com.github.docker-java/docker-java.svg?maxAge=2592000)]() +[![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) [![Build Status](https://travis-ci.org/docker-java/docker-java.svg?branch=master)](https://travis-ci.org/docker-java/docker-java) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) [![codecov.io](http://codecov.io/github/docker-java/docker-java/coverage.svg?branch=master)](http://codecov.io/github/docker-java/docker-java?branch=master) -[![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat-square)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) -[![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](https://github.com/docker-java/docker-java/blob/master/LICENSE) +[![License](http://img.shields.io/:license-apache-blue.svg?style=flat)](https://github.com/docker-java/docker-java/blob/master/LICENSE) # docker-java From 199e27db662da73fe51c2af8f66ad595bd91b1cc Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 4 Jul 2016 23:32:13 +0300 Subject: [PATCH 086/780] Move scripts to dir. Fix coverity skip. --- .travis.yml | 6 +- .../travis-after-success.sh | 0 .../travis-before-install.sh | 0 travis-script.sh => .travis/travis-script.sh | 6 +- .travis/travisci_build_coverity_scan.sh | 100 ++++++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) rename travis-after-success.sh => .travis/travis-after-success.sh (100%) rename travis-before-install.sh => .travis/travis-before-install.sh (100%) rename travis-script.sh => .travis/travis-script.sh (68%) create mode 100644 .travis/travisci_build_coverity_scan.sh diff --git a/.travis.yml b/.travis.yml index b99125afc..b6e6f953b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,13 +37,13 @@ cache: before_install: - pip install --user codecov - - ./travis-before-install.sh + - ./.travis/travis-before-install.sh script: - - ./travis-script.sh + - ./.travis/travis-script.sh after_success: - - ./travis-after-success.sh + - ./.travis/travis-after-success.sh after_script: - sudo cat /var/log/upstart/docker.log diff --git a/travis-after-success.sh b/.travis/travis-after-success.sh similarity index 100% rename from travis-after-success.sh rename to .travis/travis-after-success.sh diff --git a/travis-before-install.sh b/.travis/travis-before-install.sh similarity index 100% rename from travis-before-install.sh rename to .travis/travis-before-install.sh diff --git a/travis-script.sh b/.travis/travis-script.sh similarity index 68% rename from travis-script.sh rename to .travis/travis-script.sh index e40de7f73..7046940ff 100755 --- a/travis-script.sh +++ b/.travis/travis-script.sh @@ -8,14 +8,16 @@ IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_ if [ "${FAST_BUILD}" == "true" ]; then if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then export COVERITY_SCAN_BUILD_COMMAND="mvn package" - curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + #curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + ./.travis/travisci_build_coverity_scan.sh else mvn package fi else if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then COVERITY_SCAN_BUILD_COMMAND="mvn verify" - curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + #curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash + ./.travis/travisci_build_coverity_scan.sh else mvn verify fi diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh new file mode 100644 index 000000000..2679384b9 --- /dev/null +++ b/.travis/travisci_build_coverity_scan.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +set -e + +# Environment check +echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m" +[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1 +[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 +[ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1 +[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1 +[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 + +PLATFORM=`uname` +TOOL_ARCHIVE=/tmp/cov-analysis-${PLATFORM}.tgz +TOOL_URL=https://scan.coverity.com/download/${PLATFORM} +TOOL_BASE=/tmp/coverity-scan-analysis +UPLOAD_URL="https://scan.coverity.com/builds" +SCAN_URL="https://scan.coverity.com" + +# Do not run on pull requests +if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then + echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m" + exit 0 +fi + +# Verify this branch should run +IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"` +if [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + echo -e "\033[33;1mCoverity Scan configured to run on branch ${TRAVIS_BRANCH}\033[0m" +else + echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${TRAVIS_BRANCH}\033[0m" + exit 1 +fi + +# Verify upload is permitted +AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted` +if [ "$AUTH_RES" = "Access denied" ]; then + echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" + exit 1 +else + AUTH=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']"` + if [ "$AUTH" = "true" ]; then + echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" + else + WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"` + echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m" + + exit 1 + fi +fi + +if [ ! -d $TOOL_BASE ]; then + # Download Coverity Scan Analysis Tool + if [ ! -e $TOOL_ARCHIVE ]; then + echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" + wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" + fi + + # Extract Coverity Scan Analysis Tool + echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m" + mkdir -p $TOOL_BASE + pushd $TOOL_BASE + tar xzf $TOOL_ARCHIVE + popd +fi + +TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'` +export PATH=$TOOL_DIR/bin:$PATH + +# Build +echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m" +COV_BUILD_OPTIONS="" +#COV_BUILD_OPTIONS="--return-emit-failures 8 --parse-error-threshold 85" +RESULTS_DIR="cov-int" +eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}" +COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND +cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1 + +# Upload results +echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m" +RESULTS_ARCHIVE=analysis-results.tgz +tar czf $RESULTS_ARCHIVE $RESULTS_DIR +SHA=`git rev-parse --short HEAD` + +echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m" +response=$(curl \ + --silent --write-out "\n%{http_code}\n" \ + --form project=$COVERITY_SCAN_PROJECT_NAME \ + --form token=$COVERITY_SCAN_TOKEN \ + --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \ + --form file=@$RESULTS_ARCHIVE \ + --form version=$SHA \ + --form description="Travis CI build" \ + $UPLOAD_URL) +status_code=$(echo "$response" | sed -n '$p') +if [ "$status_code" != "201" ]; then + TEXT=$(echo "$response" | sed '$d') + echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m" + exit 1 +fi From a4d5d85d28e6ccb70c33215515b8ef75352c4bb9 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 5 Jul 2016 21:24:07 +0300 Subject: [PATCH 087/780] Fix file perm. --- .travis/travisci_build_coverity_scan.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .travis/travisci_build_coverity_scan.sh diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh old mode 100644 new mode 100755 From 898d6fa3c7dd7367327f21ed3f3088e0f1f9e691 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 5 Jul 2016 21:49:10 +0300 Subject: [PATCH 088/780] require bash? --- .travis/travisci_build_coverity_scan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 2679384b9..13af2c275 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e From fba96397576f2e9f9c56eb0aad7eb5713eefddc0 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 20 Jun 2016 14:55:12 +0300 Subject: [PATCH 089/780] Update deps. Fix IT. - remove custom jersey connector - update all deps - httpclient latest fails, stay on working version --- pom.xml | 77 +- .../jaxrs/DockerCmdExecFactoryImpl.java | 25 +- .../jaxrs/UnixConnectionSocketFactory.java | 5 +- .../jaxrs/async/AbstractCallbackNotifier.java | 1 + .../jaxrs/connector/ApacheConnector.java | 663 ------------------ .../ApacheConnectorClientResponse.java | 48 -- .../connector/ApacheConnectorProvider.java | 146 ---- .../dockerjava/jaxrs/connector/README.txt | 3 - .../command/AttachContainerCmdImplTest.java | 26 +- .../exec/AttachContainerCmdExecTest.java | 8 +- 10 files changed, 101 insertions(+), 901 deletions(-) delete mode 100644 src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnector.java delete mode 100644 src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorClientResponse.java delete mode 100644 src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorProvider.java delete mode 100644 src/main/java/com/github/dockerjava/jaxrs/connector/README.txt diff --git a/pom.xml b/pom.xml index 3f9caa55a..cb43f2897 100644 --- a/pom.xml +++ b/pom.xml @@ -47,35 +47,35 @@ 1.7 1.7 - 2.11 + 2.23.1 2.6.4 - 4.3.1 - 1.5 - 1.8 - 2.3 + 4.5 + 1.12 + 1.10 + 2.5 2.6 - 1.7.5 + 1.7.21 - 1.51 - 2015-01-27T15-02-14 - 18.0 + 1.54 + 2016-04-06T22-21-19 + 19.0 - 1.1.0 - 6.1.1 - 4.1.0.CR3 + 1.1.7 + 6.9.10 + 4.1.1.Final 1.3 - 1.6 + 1.8 2.3.3 1.10.19 - 2.2 - 2.3.1 - 2.3.1 + 3.0.2 + 3.5.1 + 2.5.3 2.19.1 2.19.1 - 1.7 + 1.8 @@ -89,6 +89,11 @@ jersey-apache-connector ${jersey.version} + + org.apache.httpcomponents + httpcore + 4.4.5 + org.apache.httpcomponents httpclient @@ -99,10 +104,20 @@ jersey-client ${jersey.version} + + + + + + + com.kohlschutter.junixsocket + junixsocket-common + 2.0.4 + - de.gesellix - unix-socket-factory - ${unix-socket-factory.version} + com.kohlschutter.junixsocket + junixsocket-native-common + 2.0.4 @@ -133,7 +148,7 @@ org.slf4j jcl-over-slf4j - 1.7.12 + 1.7.21 @@ -206,7 +221,7 @@ com.google.code.findbugs annotations - 3.0.0 + 3.0.1 provided @@ -231,6 +246,12 @@ ${netty.version} linux-x86_64 + + junit + junit + 4.12 + test + @@ -321,7 +342,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.0.1 attach-sources @@ -334,7 +355,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 2.10.4 attach-javadocs @@ -350,7 +371,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.2 + 1.6.7 true ossrh @@ -362,7 +383,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5 + ${maven-release-plugin.version} true false @@ -465,7 +486,7 @@ org.codehaus.mojo findbugs-maven-plugin - 3.0.2 + 3.0.3 Max Low @@ -484,7 +505,7 @@ org.jacoco jacoco-maven-plugin - 0.7.6.201602180812 + 0.7.7.201606060606 diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index fc74e1fde..4800f22ae 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -18,8 +18,8 @@ import javax.ws.rs.client.WebTarget; import com.github.dockerjava.api.command.UpdateContainerCmd; - import com.github.dockerjava.core.SSLConfig; + import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -27,6 +27,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.apache.connector.ApacheClientProperties; +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.slf4j.Logger; @@ -85,7 +86,6 @@ import com.github.dockerjava.api.command.RenameContainerCmd; import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.core.DockerClientConfig; -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; @@ -115,6 +115,8 @@ public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { private DockerClientConfig dockerClientConfig; + private PoolingHttpClientConnectionManager connManager = null; + @Override public void init(DockerClientConfig dockerClientConfig) { checkNotNull(dockerClientConfig, "config was not specified"); @@ -187,8 +189,21 @@ public void init(DockerClientConfig dockerClientConfig) { configureProxy(clientConfig, protocol); } - PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry( - originalUri, sslContext)); + connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry( + originalUri, sslContext)) { + + @Override + public void close() { + super.shutdown(); + } + + @Override + public void shutdown() { + // Disable shutdown of the pool. This will be done later, when this factory is closed + // This is a workaround for finalize method on jerseys ClientRuntime which + // closes the client and shuts down the connection pool when it is garbage collected + } + }; if (maxTotalConnections != null) { connManager.setMaxTotal(maxTotalConnections); @@ -412,7 +427,6 @@ public KillContainerCmd.Exec createKillContainerCmdExec() { return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); } - @Override public UpdateContainerCmd.Exec createUpdateContainerCmdExec() { return new UpdateContainerCmdExec(getBaseResource(), getDockerClientConfig()); @@ -527,6 +541,7 @@ public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() { public void close() throws IOException { checkNotNull(client, "Factory not initialized. You probably forgot to call init()!"); client.close(); + connManager.close(); } public DockerCmdExecFactoryImpl withReadTimeout(Integer readTimeout) { diff --git a/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java b/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java index 870e2fd04..0c5400ecd 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java +++ b/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java @@ -29,7 +29,8 @@ import java.net.URI; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.protocol.HttpContext; @@ -38,7 +39,7 @@ /** * Provides a ConnectionSocketFactory for connecting Apache HTTP clients to Unix sockets. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class UnixConnectionSocketFactory implements ConnectionSocketFactory { private File socketFile; diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java index bd80a2d66..cd7a7f809 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java +++ b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java @@ -61,6 +61,7 @@ public Void call() throws Exception { } try (InputStream inputStream = new WrappedResponseInputStream(response)) { + if (resultCallback != null) { responseStreamProcessor.processResponseStream(inputStream, resultCallback); } diff --git a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnector.java b/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnector.java deleted file mode 100644 index 68b47bfa8..000000000 --- a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnector.java +++ /dev/null @@ -1,663 +0,0 @@ -package com.github.dockerjava.jaxrs.connector; - -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (c) 2010-2014 Oracle and/or its affiliates. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common Development - * and Distribution License("CDDL") (collectively, the "License"). You - * may not use this file except in compliance with the License. You can - * obtain a copy of the License at - * http://glassfish.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific - * language governing permissions and limitations under the License. - * - * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. - * - * GPL Classpath Exception: - * Oracle designates this particular file as subject to the "Classpath" - * exception as provided by Oracle in the GPL Version 2 section of the License - * file that accompanied this code. - * - * Modifications: - * If applicable, add the following below the License Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyright [year] [name of copyright owner]" - * - * Contributor(s): - * If you wish your version of this file to be governed by only the CDDL or - * only the GPL Version 2, indicate your decision by adding "[Contributor] - * elects to include this software in this distribution under the [CDDL or GPL - * Version 2] license." If you don't indicate a single choice of license, a - * recipient has the option to distribute your version of this file under - * either the CDDL, the GPL Version 2 or to extend the choice of license to - * its licensees as provided above. However, if you add GPL Version 2 code - * and therefore, elected the GPL Version 2 license, then the option applies - * only if the new code is made subject to such option by the copyright - * holder. - */ - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.ws.rs.ProcessingException; -import javax.ws.rs.core.Configuration; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; - -import jersey.repackaged.com.google.common.util.concurrent.MoreExecutors; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CookieStore; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.CookieSpecs; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.ManagedHttpClientConnection; -import org.apache.http.conn.routing.HttpRoute; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLContexts; -import org.apache.http.conn.ssl.X509HostnameVerifier; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.BufferedHttpEntity; -import org.apache.http.entity.ContentLengthStrategy; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.BasicAuthCache; -import org.apache.http.impl.client.BasicCookieStore; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.DefaultManagedHttpClientConnection; -import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.impl.io.ChunkedOutputStream; -import org.apache.http.io.SessionOutputBuffer; -import org.apache.http.util.TextUtils; -import org.apache.http.util.VersionInfo; -import org.glassfish.jersey.SslConfigurator; -import org.glassfish.jersey.apache.connector.ApacheClientProperties; -import org.glassfish.jersey.apache.connector.LocalizationMessages; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.ClientRequest; -import org.glassfish.jersey.client.ClientResponse; -import org.glassfish.jersey.client.RequestEntityProcessing; -import org.glassfish.jersey.client.spi.AsyncConnectorCallback; -import org.glassfish.jersey.client.spi.Connector; -import org.glassfish.jersey.internal.util.PropertiesHelper; -import org.glassfish.jersey.message.internal.HeaderUtils; -import org.glassfish.jersey.message.internal.OutboundMessageContext; -import org.glassfish.jersey.message.internal.ReaderWriter; -import org.glassfish.jersey.message.internal.Statuses; - -/** - * A {@link Connector} that utilizes the Apache HTTP Client to send and receive HTTP request and responses. - *

- * The following properties are only supported at construction of this class: - *

    - *
  • {@link ApacheClientProperties#CONNECTION_MANAGER}
  • - *
  • {@link ApacheClientProperties#REQUEST_CONFIG}
  • - *
  • {@link ApacheClientProperties#CREDENTIALS_PROVIDER}
  • - *
  • {@link ApacheClientProperties#DISABLE_COOKIES}
  • - *
  • {@link ClientProperties#PROXY_URI}
  • - *
  • {@link ClientProperties#PROXY_USERNAME}
  • - *
  • {@link ClientProperties#PROXY_PASSWORD}
  • - *
  • {@link ClientProperties#REQUEST_ENTITY_PROCESSING} - default value is {@link RequestEntityProcessing#CHUNKED}
  • - *
  • {@link ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}
  • - *
  • {@link ApacheClientProperties#SSL_CONFIG}
  • - *
- *

- * This connector uses {@link RequestEntityProcessing#CHUNKED chunked encoding} as a default setting. This can be overridden by the - * {@link ClientProperties#REQUEST_ENTITY_PROCESSING}. By default the {@link ClientProperties#CHUNKED_ENCODING_SIZE} property is only - * supported by using default connection manager. If custom connection manager needs to be used then chunked encoding size can be set by - * providing a custom {@link org.apache.http.HttpClientConnection} (via custom - * {@link org.apache.http.impl.conn.ManagedHttpClientConnectionFactory}) and overriding {@code createOutputStream} method. - *

- *

- * Using of authorization is dependent on the chunk encoding setting. If the entity buffering is enabled, the entity is buffered and - * authorization can be performed automatically in response to a 401 by sending the request again. When entity buffering is disabled - * (chunked encoding is used) then the property - * {@link org.glassfish.jersey.apache.connector.ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION} must be set to {@code true}. - *

- *

- * If a {@link org.glassfish.jersey.client.ClientResponse} is obtained and an entity is not read from the response then - * {@link org.glassfish.jersey.client.ClientResponse#close()} MUST be called after processing the response to release connection-based - * resources. - *

- *

- * Client operations are thread safe, the HTTP connection may be shared between different threads. - *

- *

- * If a response entity is obtained that is an instance of {@link Closeable} then the instance MUST be closed after processing the entity to - * release connection-based resources. - *

- *

- * The following methods are currently supported: HEAD, GET, POST, PUT, DELETE, OPTIONS, PATCH and TRACE. - *

- * - * @author jorgeluisw@mac.com - * @author Paul Sandoz (paul.sandoz at oracle.com) - * @author Pavel Bucek (pavel.bucek at oracle.com) - * @author Arul Dhesiaseelan (aruld at acm.org) - * @see ApacheClientProperties#CONNECTION_MANAGER - */ -@SuppressWarnings("deprecation") -class ApacheConnector implements Connector { - - private static final Logger LOGGER = Logger.getLogger(ApacheConnector.class.getName()); - - private static final VersionInfo VERSION_INFO; - - private static final String RELEASE; - - static { - VERSION_INFO = VersionInfo.loadVersionInfo("org.apache.http.client", HttpClientBuilder.class.getClassLoader()); - RELEASE = (VERSION_INFO != null) ? VERSION_INFO.getRelease() : VersionInfo.UNAVAILABLE; - } - - private final CloseableHttpClient client; - - private final CookieStore cookieStore; - - private final boolean preemptiveBasicAuth; - - private final RequestConfig requestConfig; - - /** - * Create the new Apache HTTP Client connector. - * - * @param config - * client configuration. - */ - ApacheConnector(Configuration config) { - Object reqConfig = null; - - if (config != null) { - final Object connectionManager = config.getProperties().get(ApacheClientProperties.CONNECTION_MANAGER); - - if (connectionManager != null && !(connectionManager instanceof HttpClientConnectionManager)) { - LOGGER.log(Level.WARNING, LocalizationMessages.IGNORING_VALUE_OF_PROPERTY( - ApacheClientProperties.CONNECTION_MANAGER, connectionManager.getClass().getName(), - HttpClientConnectionManager.class.getName())); - } - - reqConfig = config.getProperties().get(ApacheClientProperties.REQUEST_CONFIG); - if (reqConfig != null) { - if (!(reqConfig instanceof RequestConfig)) { - LOGGER.log(Level.WARNING, LocalizationMessages.IGNORING_VALUE_OF_PROPERTY( - ApacheClientProperties.REQUEST_CONFIG, reqConfig.getClass().getName(), - RequestConfig.class.getName())); - reqConfig = null; - } - } - } - - final SSLContext sslContext = getSslContext(config); - final HttpClientBuilder clientBuilder = HttpClientBuilder.create(); - - clientBuilder.setConnectionManager(getConnectionManager(config, sslContext)); - clientBuilder.setSslcontext(sslContext); - - final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); - - int connectTimeout = 0; - int socketTimeout = 0; - boolean ignoreCookies = false; - if (config != null) { - connectTimeout = ClientProperties.getValue(config.getProperties(), ClientProperties.CONNECT_TIMEOUT, 0); - socketTimeout = ClientProperties.getValue(config.getProperties(), ClientProperties.READ_TIMEOUT, 0); - ignoreCookies = PropertiesHelper.isProperty(config.getProperties(), ApacheClientProperties.DISABLE_COOKIES); - - final Object credentialsProvider = config.getProperty(ApacheClientProperties.CREDENTIALS_PROVIDER); - if (credentialsProvider != null && (credentialsProvider instanceof CredentialsProvider)) { - clientBuilder.setDefaultCredentialsProvider((CredentialsProvider) credentialsProvider); - } - - Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - final HttpHost proxy = new HttpHost(u.getHost(), u.getPort(), u.getScheme()); - String userName; - userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, - String.class); - if (userName != null) { - String password; - password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, - String.class); - - if (password != null) { - final CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials(new AuthScope(u.getHost(), u.getPort()), - new UsernamePasswordCredentials(userName, password)); - clientBuilder.setDefaultCredentialsProvider(credsProvider); - } - } - clientBuilder.setProxy(proxy); - } - - final Boolean preemptiveBasicAuthProperty = (Boolean) config.getProperties().get( - ApacheClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION); - this.preemptiveBasicAuth = (preemptiveBasicAuthProperty != null) ? preemptiveBasicAuthProperty : false; - } else { - this.preemptiveBasicAuth = false; - } - - if (reqConfig != null) { - RequestConfig.Builder reqConfigBuilder = RequestConfig.copy((RequestConfig) reqConfig); - if (connectTimeout > 0) { - reqConfigBuilder.setConnectTimeout(connectTimeout); - } - if (socketTimeout > 0) { - reqConfigBuilder.setSocketTimeout(socketTimeout); - } - if (ignoreCookies) { - reqConfigBuilder.setCookieSpec(CookieSpecs.IGNORE_COOKIES); - } - requestConfig = reqConfigBuilder.build(); - } else { - requestConfigBuilder.setConnectTimeout(connectTimeout); - requestConfigBuilder.setSocketTimeout(socketTimeout); - if (ignoreCookies) { - requestConfigBuilder.setCookieSpec(CookieSpecs.IGNORE_COOKIES); - } - requestConfig = requestConfigBuilder.build(); - } - - if (requestConfig.getCookieSpec() == null || !requestConfig.getCookieSpec().equals(CookieSpecs.IGNORE_COOKIES)) { - this.cookieStore = new BasicCookieStore(); - clientBuilder.setDefaultCookieStore(cookieStore); - } else { - this.cookieStore = null; - } - clientBuilder.setDefaultRequestConfig(requestConfig); - this.client = clientBuilder.build(); - } - - private SSLContext getSslContext(final Configuration config) { - final SslConfigurator sslConfigurator = ApacheClientProperties.getValue(config.getProperties(), - ApacheClientProperties.SSL_CONFIG, SslConfigurator.class); - - return sslConfigurator != null ? sslConfigurator.createSSLContext() : null; - } - - HttpClientConnectionManager getConnectionManager(final Configuration config, final SSLContext sslContext) { - final Object cmObject = config.getProperties().get(ApacheClientProperties.CONNECTION_MANAGER); - - // Connection manager from configuration. - if (cmObject != null) { - if (cmObject instanceof HttpClientConnectionManager) { - return (HttpClientConnectionManager) cmObject; - } else { - LOGGER.log(Level.WARNING, LocalizationMessages.IGNORING_VALUE_OF_PROPERTY( - ApacheClientProperties.CONNECTION_MANAGER, cmObject.getClass().getName(), - HttpClientConnectionManager.class.getName())); - } - } - - // Create custom connection manager. - return createConnectionManager(config, sslContext, null, false); - } - - private HttpClientConnectionManager createConnectionManager(final Configuration config, - final SSLContext sslContext, X509HostnameVerifier hostnameVerifier, final boolean useSystemProperties) { - - final String[] supportedProtocols = useSystemProperties ? split(System.getProperty("https.protocols")) : null; - final String[] supportedCipherSuites = useSystemProperties ? split(System.getProperty("https.cipherSuites")) - : null; - - if (hostnameVerifier == null) { - hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; - } - - final LayeredConnectionSocketFactory sslSocketFactory; - if (sslContext != null) { - sslSocketFactory = new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, - hostnameVerifier); - } else { - if (useSystemProperties) { - sslSocketFactory = new SSLConnectionSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault(), - supportedProtocols, supportedCipherSuites, hostnameVerifier); - } else { - sslSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), hostnameVerifier); - } - } - - final Registry registry = RegistryBuilder. create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory) - .build(); - - final Integer chunkSize = ClientProperties.getValue(config.getProperties(), - ClientProperties.CHUNKED_ENCODING_SIZE, 4096, Integer.class); - - final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry, - new ConnectionFactory(chunkSize)); - - if (useSystemProperties) { - String s = System.getProperty("http.keepAlive", "true"); - if ("true".equalsIgnoreCase(s)) { - s = System.getProperty("http.maxConnections", "5"); - final int max = Integer.parseInt(s); - connectionManager.setDefaultMaxPerRoute(max); - connectionManager.setMaxTotal(2 * max); - } - } - - return connectionManager; - } - - private static String[] split(final String s) { - if (TextUtils.isBlank(s)) { - return null; - } - return s.split(" *, *"); - } - - /** - * Get the {@link HttpClient}. - * - * @return the {@link HttpClient}. - */ - @SuppressWarnings("UnusedDeclaration") - public HttpClient getHttpClient() { - return client; - } - - /** - * Get the {@link CookieStore}. - * - * @return the {@link CookieStore} instance or {@code null} when {@value ApacheClientProperties#DISABLE_COOKIES} set to {@code true}. - */ - public CookieStore getCookieStore() { - return cookieStore; - } - - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - - @Override - public ClientResponse apply(final ClientRequest clientRequest) throws ProcessingException { - final HttpUriRequest request = getUriHttpRequest(clientRequest); - final Map clientHeadersSnapshot = writeOutBoundHeaders(clientRequest.getHeaders(), request); - - try { - final CloseableHttpResponse response; - final HttpClientContext context = HttpClientContext.create(); - if (preemptiveBasicAuth) { - final AuthCache authCache = new BasicAuthCache(); - final BasicScheme basicScheme = new BasicScheme(); - authCache.put(getHost(request), basicScheme); - context.setAuthCache(authCache); - } - - // context.setRequestConfig(RequestConfig.custom().setConnectionRequestTimeout(10).build()); - - response = client.execute(getHost(request), request, context); - HeaderUtils - .checkHeaderChanges(clientHeadersSnapshot, clientRequest.getHeaders(), this.getClass().getName()); - - final Response.StatusType status = response.getStatusLine().getReasonPhrase() == null ? Statuses - .from(response.getStatusLine().getStatusCode()) : Statuses.from(response.getStatusLine() - .getStatusCode(), response.getStatusLine().getReasonPhrase()); - - final ClientResponse responseContext = new ApacheConnectorClientResponse(status, clientRequest, response); - final List redirectLocations = context.getRedirectLocations(); - if (redirectLocations != null && !redirectLocations.isEmpty()) { - responseContext.setResolvedRequestUri(redirectLocations.get(redirectLocations.size() - 1)); - } - - final Header[] respHeaders = response.getAllHeaders(); - final MultivaluedMap headers = responseContext.getHeaders(); - for (final Header header : respHeaders) { - final String headerName = header.getName(); - List list = headers.get(headerName); - if (list == null) { - list = new ArrayList(); - } - list.add(header.getValue()); - headers.put(headerName, list); - } - - final HttpEntity entity = response.getEntity(); - - if (entity != null) { - if (headers.get(HttpHeaders.CONTENT_LENGTH) == null) { - headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getContentLength())); - } - - final Header contentEncoding = entity.getContentEncoding(); - if (headers.get(HttpHeaders.CONTENT_ENCODING) == null && contentEncoding != null) { - headers.add(HttpHeaders.CONTENT_ENCODING, contentEncoding.getValue()); - } - } - - try { - responseContext.setEntityStream(new HttpClientResponseInputStream(response)); - } catch (final IOException e) { - LOGGER.log(Level.SEVERE, null, e); - } - - return responseContext; - } catch (final Exception e) { - throw new ProcessingException(e); - } - } - - @Override - public Future apply(final ClientRequest request, final AsyncConnectorCallback callback) { - return MoreExecutors.sameThreadExecutor().submit(new Runnable() { - @Override - public void run() { - try { - callback.response(apply(request)); - } catch (final ProcessingException ex) { - callback.failure(ex); - } catch (final Throwable t) { - callback.failure(t); - } - } - }); - } - - @Override - public String getName() { - return "Apache HttpClient " + RELEASE; - } - - @Override - public void close() { - try { - client.close(); - } catch (final IOException e) { - throw new ProcessingException(LocalizationMessages.FAILED_TO_STOP_CLIENT(), e); - } - } - - private HttpHost getHost(final HttpUriRequest request) { - return new HttpHost(request.getURI().getHost(), request.getURI().getPort(), request.getURI().getScheme()); - } - - private HttpUriRequest getUriHttpRequest(final ClientRequest clientRequest) { - final Boolean redirectsEnabled = clientRequest.resolveProperty(ClientProperties.FOLLOW_REDIRECTS, - requestConfig.isRedirectsEnabled()); - final RequestConfig config = RequestConfig.copy(requestConfig).setRedirectsEnabled(redirectsEnabled).build(); - - final Boolean bufferingEnabled = clientRequest.resolveProperty(ClientProperties.REQUEST_ENTITY_PROCESSING, - RequestEntityProcessing.class) == RequestEntityProcessing.BUFFERED; - final HttpEntity entity = getHttpEntity(clientRequest, bufferingEnabled); - - return RequestBuilder.create(clientRequest.getMethod()).setUri(clientRequest.getUri()).setConfig(config) - .setEntity(entity).build(); - } - - private HttpEntity getHttpEntity(final ClientRequest clientRequest, final boolean bufferingEnabled) { - final Object entity = clientRequest.getEntity(); - - if (entity == null) { - return null; - } - - final AbstractHttpEntity httpEntity = new AbstractHttpEntity() { - @Override - public boolean isRepeatable() { - return false; - } - - @Override - public long getContentLength() { - return -1; - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - if (bufferingEnabled) { - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(512); - writeTo(buffer); - return new ByteArrayInputStream(buffer.toByteArray()); - } else { - return null; - } - } - - @Override - public void writeTo(final OutputStream outputStream) throws IOException { - clientRequest.setStreamProvider(new OutboundMessageContext.StreamProvider() { - @Override - public OutputStream getOutputStream(final int contentLength) throws IOException { - return outputStream; - } - }); - clientRequest.writeEntity(); - } - - @Override - public boolean isStreaming() { - return false; - } - }; - - if (bufferingEnabled) { - try { - return new BufferedHttpEntity(httpEntity); - } catch (final IOException e) { - throw new ProcessingException(LocalizationMessages.ERROR_BUFFERING_ENTITY(), e); - } - } else { - return httpEntity; - } - } - - private static Map writeOutBoundHeaders(final MultivaluedMap headers, - final HttpUriRequest request) { - Map stringHeaders = HeaderUtils.asStringHeadersSingleValue(headers); - - for (Map.Entry e : stringHeaders.entrySet()) { - request.addHeader(e.getKey(), e.getValue()); - } - return stringHeaders; - } - - private static final class HttpClientResponseInputStream extends FilterInputStream { - - HttpClientResponseInputStream(final CloseableHttpResponse response) throws IOException { - super(getInputStream(response)); - } - - @Override - public void close() throws IOException { - super.close(); - } - } - - private static InputStream getInputStream(final CloseableHttpResponse response) throws IOException { - - if (response.getEntity() == null) { - return new ByteArrayInputStream(new byte[0]); - } else { - final InputStream i = response.getEntity().getContent(); - if (i.markSupported()) { - return i; - } - return new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE); - } - } - - private static class ConnectionFactory extends ManagedHttpClientConnectionFactory { - - private static final AtomicLong COUNTER = new AtomicLong(); - - private final int chunkSize; - - private ConnectionFactory(final int chunkSize) { - this.chunkSize = chunkSize; - } - - @Override - public ManagedHttpClientConnection create(final HttpRoute route, final ConnectionConfig config) { - final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement()); - - return new HttpClientConnection(id, config.getBufferSize(), chunkSize); - } - } - - private static class HttpClientConnection extends DefaultManagedHttpClientConnection { - - private final int chunkSize; - - private HttpClientConnection(final String id, final int buffersize, final int chunkSize) { - super(id, buffersize); - - this.chunkSize = chunkSize; - } - - @Override - protected OutputStream createOutputStream(final long len, final SessionOutputBuffer outbuffer) { - if (len == ContentLengthStrategy.CHUNKED) { - return new ChunkedOutputStream(chunkSize, outbuffer); - } - return super.createOutputStream(len, outbuffer); - } - } -} diff --git a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorClientResponse.java b/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorClientResponse.java deleted file mode 100644 index fead3575c..000000000 --- a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorClientResponse.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.github.dockerjava.jaxrs.connector; - -import java.io.IOException; - -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.StatusType; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.glassfish.jersey.client.ClientRequest; -import org.glassfish.jersey.client.ClientResponse; - -/** - * Fix for https://github.com/docker-java/docker-java/issues/196 - * - * https://java.net/jira/browse/JERSEY-2852 - * - * @author Marcus Linke - * - */ -public class ApacheConnectorClientResponse extends ClientResponse { - - private CloseableHttpResponse closeableHttpResponse; - - public ApacheConnectorClientResponse(ClientRequest requestContext, Response response) { - super(requestContext, response); - } - - public ApacheConnectorClientResponse(StatusType status, ClientRequest requestContext, - CloseableHttpResponse closeableHttpResponse) { - super(status, requestContext); - this.closeableHttpResponse = closeableHttpResponse; - } - - public ApacheConnectorClientResponse(StatusType status, ClientRequest requestContext) { - super(status, requestContext); - } - - @Override - public void close() { - try { - closeableHttpResponse.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - super.close(); - } - -} diff --git a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorProvider.java b/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorProvider.java deleted file mode 100644 index eafb55c29..000000000 --- a/src/main/java/com/github/dockerjava/jaxrs/connector/ApacheConnectorProvider.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.github.dockerjava.jaxrs.connector; - -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (c) 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common Development - * and Distribution License("CDDL") (collectively, the "License"). You - * may not use this file except in compliance with the License. You can - * obtain a copy of the License at - * http://glassfish.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific - * language governing permissions and limitations under the License. - * - * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. - * - * GPL Classpath Exception: - * Oracle designates this particular file as subject to the "Classpath" - * exception as provided by Oracle in the GPL Version 2 section of the License - * file that accompanied this code. - * - * Modifications: - * If applicable, add the following below the License Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyright [year] [name of copyright owner]" - * - * Contributor(s): - * If you wish your version of this file to be governed by only the CDDL or - * only the GPL Version 2, indicate your decision by adding "[Contributor] - * elects to include this software in this distribution under the [CDDL or GPL - * Version 2] license." If you don't indicate a single choice of license, a - * recipient has the option to distribute your version of this file under - * either the CDDL, the GPL Version 2 or to extend the choice of license to - * its licensees as provided above. However, if you add GPL Version 2 code - * and therefore, elected the GPL Version 2 license, then the option applies - * only if the new code is made subject to such option by the copyright - * holder. - */ -import javax.ws.rs.client.Client; -import javax.ws.rs.core.Configurable; -import javax.ws.rs.core.Configuration; - -import org.apache.http.client.HttpClient; -import org.glassfish.jersey.apache.connector.ApacheClientProperties; -import org.glassfish.jersey.apache.connector.LocalizationMessages; -import org.glassfish.jersey.client.Initializable; -import org.glassfish.jersey.client.spi.Connector; -import org.glassfish.jersey.client.spi.ConnectorProvider; - -/** - * Connector provider for Jersey {@link Connector connectors} that utilize Apache HTTP Client to send and receive HTTP request and - * responses. - *

- * The following connector configuration properties are supported: - *

    - *
  • {@link ApacheClientProperties#CONNECTION_MANAGER}
  • - *
  • {@link ApacheClientProperties#REQUEST_CONFIG}
  • - *
  • {@link ApacheClientProperties#CREDENTIALS_PROVIDER}
  • - *
  • {@link ApacheClientProperties#DISABLE_COOKIES}
  • - *
  • {@link org.glassfish.jersey.client.ClientProperties#PROXY_URI}
  • - *
  • {@link org.glassfish.jersey.client.ClientProperties#PROXY_USERNAME}
  • - *
  • {@link org.glassfish.jersey.client.ClientProperties#PROXY_PASSWORD}
  • - *
  • {@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING} - default value is - * {@link org.glassfish.jersey.client.RequestEntityProcessing#CHUNKED}
  • - *
  • {@link ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}
  • - *
  • {@link ApacheClientProperties#SSL_CONFIG}
  • - *
- *

- *

- * Connector instances created via this connector provider use {@link org.glassfish.jersey.client.RequestEntityProcessing#CHUNKED chunked - * encoding} as a default setting. This can be overridden by the - * {@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING}. By default the - * {@link org.glassfish.jersey.client.ClientProperties#CHUNKED_ENCODING_SIZE} property is only supported when using the default - * {@code org.apache.http.conn.HttpClientConnectionManager} instance. If custom connection manager is used, then chunked encoding size can - * be set by providing a custom {@code org.apache.http.HttpClientConnection} (via custom - * {@code org.apache.http.impl.conn.ManagedHttpClientConnectionFactory}) and overriding it's {@code createOutputStream} method. - *

- *

- * Use of authorization by the AHC-based connectors is dependent on the chunk encoding setting. If the entity buffering is enabled, the - * entity is buffered and authorization can be performed automatically in response to a 401 by sending the request again. When entity - * buffering is disabled (chunked encoding is used) then the property - * {@link org.glassfish.jersey.apache.connector.ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION} must be set to {@code true}. - *

- *

- * If a {@link org.glassfish.jersey.client.ClientResponse} is obtained and an entity is not read from the response then - * {@link org.glassfish.jersey.client.ClientResponse#close()} MUST be called after processing the response to release connection-based - * resources. - *

- *

- * If a response entity is obtained that is an instance of {@link java.io.Closeable} then the instance MUST be closed after processing the - * entity to release connection-based resources. - *

- *

- * The following methods are currently supported: HEAD, GET, POST, PUT, DELETE, OPTIONS, PATCH and TRACE. - *

- * - * @author Pavel Bucek (pavel.bucek at oracle.com) - * @author Arul Dhesiaseelan (aruld at acm.org) - * @author jorgeluisw at mac.com - * @author Marek Potociar (marek.potociar at oracle.com) - * @author Paul Sandoz (paul.sandoz at oracle.com) - * @since 2.5 - */ -public class ApacheConnectorProvider implements ConnectorProvider { - - @Override - public Connector getConnector(Client client, Configuration runtimeConfig) { - return new ApacheConnector(runtimeConfig); - } - - /** - * Retrieve the underlying Apache {@link HttpClient} instance from {@link org.glassfish.jersey.client.JerseyClient} or - * {@link org.glassfish.jersey.client.JerseyWebTarget} configured to use {@code ApacheConnectorProvider}. - * - * @param component - * {@code JerseyClient} or {@code JerseyWebTarget} instance that is configured to use {@code ApacheConnectorProvider}. - * @return underlying Apache {@code HttpClient} instance. - * - * @throws java.lang.IllegalArgumentException - * in case the {@code component} is neither {@code JerseyClient} nor {@code JerseyWebTarget} instance or in case the - * component is not configured to use a {@code ApacheConnectorProvider}. - * @since 2.8 - */ - public static HttpClient getHttpClient(Configurable component) { - if (!(component instanceof Initializable)) { - throw new IllegalArgumentException(LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component - .getClass().getName())); - } - - final Initializable initializable = (Initializable) component; - Connector connector = initializable.getConfiguration().getConnector(); - if (connector == null) { - initializable.preInitialize(); - connector = initializable.getConfiguration().getConnector(); - } - - if (connector instanceof ApacheConnector) { - return ((ApacheConnector) connector).getHttpClient(); - } - - throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED()); - } -} diff --git a/src/main/java/com/github/dockerjava/jaxrs/connector/README.txt b/src/main/java/com/github/dockerjava/jaxrs/connector/README.txt deleted file mode 100644 index c3c1415f1..000000000 --- a/src/main/java/com/github/dockerjava/jaxrs/connector/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This package exists as a workaround to https://java.net/jira/browse/JERSEY-2852. -It introduces ApacheConnectorClientResponse which extends ClientResponse and closes -the underlying CloseableHttpResponse when close() is called. \ No newline at end of file diff --git a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java index 21507e44e..f8bf33fef 100644 --- a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.core.command; +import static org.apache.commons.lang.StringUtils.isEmpty; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.isEmptyString; @@ -11,7 +12,9 @@ import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; +import org.apache.commons.codec.binary.StringUtils; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -74,7 +77,7 @@ public void onNext(Frame frame) { assertThat(callback.toString(), containsString(snippet)); } - @Test + @Test(groups = "badTests", enabled = false) public void attachContainerWithTTY() throws Exception { File baseDir = new File(Thread.currentThread().getContextClassLoader() @@ -97,14 +100,24 @@ public void onNext(Frame frame) { }; }; - dockerClient.attachContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withFollowStream(true) - .exec(callback).awaitCompletion(15, TimeUnit.SECONDS); + dockerClient.attachContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .exec(callback) + .awaitCompletion(); +// .awaitCompletion(15, TimeUnit.SECONDS); callback.close(); + dockerClient.close(); + System.out.println("log: " + callback.toString()); // HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0); - + RuntimeException firstError = callback.getFirstError(); + if (isEmpty(callback.toString())) { + throw new SkipException("com.github.dockerjava.api.exception.InternalServerErrorException: http: Hijack is incompatible with use of CloseNotifier"); + } assertThat(callback.toString(), containsString("stdout\r\nstderr")); } @@ -145,6 +158,11 @@ public void onNext(Frame item) { super.onNext(item); } + @Override + public RuntimeException getFirstError() { + return super.getFirstError(); + } + @Override public String toString() { return log.toString(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index 7f8e66609..ba3d5a9ca 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -134,8 +134,12 @@ public void onNext(Frame frame) { }; }; - dockerClient.attachContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withFollowStream(true) - .exec(callback).awaitCompletion(10, TimeUnit.SECONDS); + dockerClient.attachContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) + .exec(callback) + .awaitCompletion(10, TimeUnit.SECONDS); callback.close(); // HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0); From 52ff6d82952a4b1ff2426a24e239547e32f38314 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 00:31:26 +0300 Subject: [PATCH 090/780] revert dep and test --- pom.xml | 18 ++++-------------- .../command/AttachContainerCmdImplTest.java | 11 ++--------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index cb43f2897..a13ac1fc0 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ 1.7.21 1.54 - 2016-04-06T22-21-19 + 2015-01-27T15-02-14 19.0 @@ -104,20 +104,10 @@ jersey-client ${jersey.version} - - - - - - com.kohlschutter.junixsocket - junixsocket-common - 2.0.4 - - - com.kohlschutter.junixsocket - junixsocket-native-common - 2.0.4 + de.gesellix + unix-socket-factory + ${unix-socket-factory.version} diff --git a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java index f8bf33fef..ef69984f3 100644 --- a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java @@ -77,7 +77,7 @@ public void onNext(Frame frame) { assertThat(callback.toString(), containsString(snippet)); } - @Test(groups = "badTests", enabled = false) + @Test public void attachContainerWithTTY() throws Exception { File baseDir = new File(Thread.currentThread().getContextClassLoader() @@ -105,19 +105,12 @@ public void onNext(Frame frame) { .withStdOut(true) .withFollowStream(true) .exec(callback) - .awaitCompletion(); -// .awaitCompletion(15, TimeUnit.SECONDS); + .awaitCompletion(15, TimeUnit.SECONDS); callback.close(); - dockerClient.close(); - System.out.println("log: " + callback.toString()); // HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0); - RuntimeException firstError = callback.getFirstError(); - if (isEmpty(callback.toString())) { - throw new SkipException("com.github.dockerjava.api.exception.InternalServerErrorException: http: Hijack is incompatible with use of CloseNotifier"); - } assertThat(callback.toString(), containsString("stdout\r\nstderr")); } From 19d5f84c0bfe9494d558f991e073680195989371 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 00:44:37 +0300 Subject: [PATCH 091/780] Fix version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3f9caa55a..bee178a6d 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.0-kostyasha-3 + 3.0.1-SNAPSHOT docker-java https://github.com/docker-java/docker-java From 1a148f2e51ac908cfa9a23e0f847a07b2c155797 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 01:14:28 +0300 Subject: [PATCH 092/780] Skip auth tests --- pom.xml | 3 ++- .../github/dockerjava/core/command/PushImageCmdImplTest.java | 2 +- .../com/github/dockerjava/netty/exec/PushImageCmdExecTest.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a13ac1fc0..2437baa22 100644 --- a/pom.xml +++ b/pom.xml @@ -388,6 +388,7 @@ ${maven-surefire-plugin.version} integration + integration-auth @@ -403,7 +404,7 @@ integration - + integration-auth **/*Test.java diff --git a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java index e89a071b8..a48750bd1 100644 --- a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java @@ -19,7 +19,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; -@Test(groups = "integration") +@Test(groups = "integration-auth") public class PushImageCmdImplTest extends AbstractDockerClientTest { public static final Logger LOG = LoggerFactory.getLogger(PushImageCmdImplTest.class); diff --git a/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java index 777cc8eed..5e77a6765 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java @@ -21,7 +21,7 @@ import com.github.dockerjava.core.command.PushImageResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; -@Test(groups = "integration") +@Test(groups = "integration-auth") public class PushImageCmdExecTest extends AbstractNettyDockerClientTest { public static final Logger LOG = LoggerFactory.getLogger(PushImageCmdExecTest.class); From 3a782a9834449f78368c54356d5dd3412ae89917 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 01:26:19 +0300 Subject: [PATCH 093/780] Enable cache --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6e6f953b..4491de529 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ env: cache: directories: - $HOME/.travis_cache -# - $HOME/.m2 install would pollute it + - $HOME/.m2 # install will pollute it before_install: - pip install --user codecov From 31d5627be8dad851941f126a5af0aa5385e002b4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 01:45:09 +0300 Subject: [PATCH 094/780] Disable experimental/testing --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4491de529..9c96c5abd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,10 +25,10 @@ env: - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" - - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" - - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" - - repo="experimental" DOCKER_HOST="tcp://127.0.0.1:2375" - - repo="experimental" DOCKER_HOST="unix:///var/run/docker.sock" +# - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" +# - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" +# - repo="experimental" DOCKER_HOST="tcp://127.0.0.1:2375" +# - repo="experimental" DOCKER_HOST="unix:///var/run/docker.sock" cache: directories: From 007f66899f9a84bde102f4740631816973e2fb9a Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 02:12:48 +0300 Subject: [PATCH 095/780] run codecov only on one run --- .travis.yml | 3 +-- .travis/travis-after-success.sh | 4 +++- .travis/travis-before-install.sh | 3 +-- .../github/dockerjava/core/command/PushImageCmdImplTest.java | 2 +- .../github/dockerjava/netty/exec/PushImageCmdExecTest.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9c96c5abd..bb559fd93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,7 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true FAST_BUILD=true COVERITY=true - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" # - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" diff --git a/.travis/travis-after-success.sh b/.travis/travis-after-success.sh index 6d198daf5..695358122 100755 --- a/.travis/travis-after-success.sh +++ b/.travis/travis-after-success.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash +if [[ $CODECOV == "true" ]]; then + codecov +fi -codecov if [[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_PULL_REQUEST == "false" ]] && [[ $DEPLOY == "true" ]]; then cat <> ~/settings.xml diff --git a/.travis/travis-before-install.sh b/.travis/travis-before-install.sh index 13034fc74..970425f63 100755 --- a/.travis/travis-before-install.sh +++ b/.travis/travis-before-install.sh @@ -28,8 +28,7 @@ sudo -E apt-cache policy docker-engine # sudo apt-get -f install # sudo dpkg -i "$(ls *${DOCKER_VERSION}*)" #popd -#rm -f "src/test/resources/logback.xml" -mv "src/test/resources/travis-logback.xml" "src/test/resources/logback.xml" + echo 'DOCKER_OPTS="-H=unix:///var/run/docker.sock -H=tcp://127.0.0.1:2375"' | sudo tee -a /etc/default/docker sudo -E restart docker diff --git a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java index a48750bd1..0fb32c311 100644 --- a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java @@ -19,7 +19,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; -@Test(groups = "integration-auth") +@Test(groups = {"integration-auth", "integration"}) public class PushImageCmdImplTest extends AbstractDockerClientTest { public static final Logger LOG = LoggerFactory.getLogger(PushImageCmdImplTest.class); diff --git a/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java index 5e77a6765..73e99af6d 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/PushImageCmdExecTest.java @@ -21,7 +21,7 @@ import com.github.dockerjava.core.command.PushImageResultCallback; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; -@Test(groups = "integration-auth") +@Test(groups = {"integration", "integration-auth"}) public class PushImageCmdExecTest extends AbstractNettyDockerClientTest { public static final Logger LOG = LoggerFactory.getLogger(PushImageCmdExecTest.class); From 3854e2efd477ae4cba4e0d1c85302ccc2d085c41 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 02:15:44 +0300 Subject: [PATCH 096/780] revert typo --- .travis/travis-before-install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis/travis-before-install.sh b/.travis/travis-before-install.sh index 970425f63..13034fc74 100755 --- a/.travis/travis-before-install.sh +++ b/.travis/travis-before-install.sh @@ -28,7 +28,8 @@ sudo -E apt-cache policy docker-engine # sudo apt-get -f install # sudo dpkg -i "$(ls *${DOCKER_VERSION}*)" #popd - +#rm -f "src/test/resources/logback.xml" +mv "src/test/resources/travis-logback.xml" "src/test/resources/logback.xml" echo 'DOCKER_OPTS="-H=unix:///var/run/docker.sock -H=tcp://127.0.0.1:2375"' | sudo tee -a /etc/default/docker sudo -E restart docker From 24d3a15001da56083a5c83f47a1f5076e1468195 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 02:31:08 +0300 Subject: [PATCH 097/780] tune timeout --- .../dockerjava/netty/exec/AttachContainerCmdExecTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index ba3d5a9ca..675c11177 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -105,7 +105,9 @@ public void onNext(Frame frame) { InputStream stdin = new ByteArrayInputStream((snippet + "\n").getBytes()); dockerClient.attachContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withFollowStream(true) - .withStdIn(stdin).exec(callback).awaitCompletion(2, TimeUnit.SECONDS); + .withStdIn(stdin) + .exec(callback) + .awaitCompletion(5, TimeUnit.SECONDS); callback.close(); assertThat(callback.toString(), containsString(snippet)); From 8837ac38a9a6b820ea292a8afc82a658cb24d883 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 8 Jul 2016 10:50:27 +0300 Subject: [PATCH 098/780] Fix shell scripting --- .travis/travis-script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis-script.sh b/.travis/travis-script.sh index 7046940ff..aeae555ef 100755 --- a/.travis/travis-script.sh +++ b/.travis/travis-script.sh @@ -15,7 +15,7 @@ if [ "${FAST_BUILD}" == "true" ]; then fi else if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then - COVERITY_SCAN_BUILD_COMMAND="mvn verify" + export COVERITY_SCAN_BUILD_COMMAND="mvn verify" #curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash ./.travis/travisci_build_coverity_scan.sh else From 1c14bc3cf04f22a0768e47431a0124425f53e787 Mon Sep 17 00:00:00 2001 From: tejksat Date: Sat, 9 Jul 2016 11:19:43 +0300 Subject: [PATCH 099/780] Fix for #625 (#630) * Fix for #625 * Checkstyle errors fixed --- .../github/dockerjava/netty/WebTarget.java | 63 +++++++++++++++---- .../dockerjava/netty/WebTargetTest.java | 39 ++++++++++++ 2 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 src/test/java/com/github/dockerjava/netty/WebTargetTest.java diff --git a/src/main/java/com/github/dockerjava/netty/WebTarget.java b/src/main/java/com/github/dockerjava/netty/WebTarget.java index 090fea67c..ef1510f5c 100644 --- a/src/main/java/com/github/dockerjava/netty/WebTarget.java +++ b/src/main/java/com/github/dockerjava/netty/WebTarget.java @@ -2,12 +2,14 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + /** * This class is basically a replacement of javax.ws.rs.client.WebTarget to allow simpler migration of JAX-RS code to a netty based * implementation. @@ -16,32 +18,40 @@ */ public class WebTarget { - private ChannelProvider channelProvider; + private final ChannelProvider channelProvider; - private List path = new ArrayList(); + private final ImmutableList path; - private Map queryParams = new HashMap(); + private final ImmutableMap queryParams; private static final String PATH_SEPARATOR = "/"; public WebTarget(ChannelProvider channelProvider) { + this(channelProvider, ImmutableList.of(), ImmutableMap.of()); + } + + private WebTarget(ChannelProvider channelProvider, + ImmutableList path, + ImmutableMap queryParams) { this.channelProvider = channelProvider; + this.path = path; + this.queryParams = queryParams; } public WebTarget path(String... components) { + ImmutableList.Builder newPath = ImmutableList.builder().addAll(this.path); for (String component : components) { - - path.addAll(Arrays.asList(StringUtils.split(component, PATH_SEPARATOR))); + newPath.addAll(Arrays.asList(StringUtils.split(component, PATH_SEPARATOR))); } - return this; + return new WebTarget(channelProvider, newPath.build(), queryParams); } public InvocationBuilder request() { String resource = PATH_SEPARATOR + StringUtils.join(path, PATH_SEPARATOR); - List params = new ArrayList(); + List params = new ArrayList<>(); for (Map.Entry entry : queryParams.entrySet()) { params.add(entry.getKey() + "=" + entry.getValue()); } @@ -54,20 +64,47 @@ public InvocationBuilder request() { } public WebTarget resolveTemplate(String name, Object value) { - List newPath = new ArrayList(); + ImmutableList.Builder newPath = ImmutableList.builder(); for (String component : path) { component = component.replaceAll("\\{" + name + "\\}", value.toString()); newPath.add(component); } - path = newPath; - return this; + return new WebTarget(channelProvider, newPath.build(), queryParams); } public WebTarget queryParam(String name, Object value) { + ImmutableMap.Builder builder = ImmutableMap.builder().putAll(queryParams); if (value != null) { - queryParams.put(name, value.toString()); + builder.put(name, value.toString()); } - return this; + return new WebTarget(channelProvider, path, builder.build()); } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + WebTarget webTarget = (WebTarget) o; + + if (channelProvider != null ? !channelProvider.equals(webTarget.channelProvider) : webTarget.channelProvider != null) { + return false; + } + if (path != null ? !path.equals(webTarget.path) : webTarget.path != null) { + return false; + } + return queryParams != null ? queryParams.equals(webTarget.queryParams) : webTarget.queryParams == null; + } + + @Override + public int hashCode() { + int result = channelProvider != null ? channelProvider.hashCode() : 0; + result = 31 * result + (path != null ? path.hashCode() : 0); + result = 31 * result + (queryParams != null ? queryParams.hashCode() : 0); + return result; + } } diff --git a/src/test/java/com/github/dockerjava/netty/WebTargetTest.java b/src/test/java/com/github/dockerjava/netty/WebTargetTest.java new file mode 100644 index 000000000..a462eb8b5 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/WebTargetTest.java @@ -0,0 +1,39 @@ +package com.github.dockerjava.netty; + +import static org.testng.Assert.assertEquals; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Alexander Koshevoy + */ +public class WebTargetTest { + @Mock private ChannelProvider channelProvider; + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void verifyImmutability() throws Exception { + WebTarget emptyWebTarget = new WebTarget(channelProvider); + + WebTarget initWebTarget = emptyWebTarget.path("/containers/{id}/attach").resolveTemplate("id", "d03da378b592") + .queryParam("logs", "true"); + + WebTarget anotherWebTarget = emptyWebTarget.path("/containers/{id}/attach") + .resolveTemplate("id", "2cfada4e3c07").queryParam("stdin", "true"); + + assertEquals(new WebTarget(channelProvider), emptyWebTarget); + + assertEquals(new WebTarget(channelProvider).path("/containers/d03da378b592/attach") + .queryParam("logs", "true"), initWebTarget); + + assertEquals(new WebTarget(channelProvider).path("/containers/2cfada4e3c07/attach") + .queryParam("stdin", "true"), anotherWebTarget); + } +} From 1923e7e5866374dc4cb771ef9d7d3317aba2704b Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Sat, 9 Jul 2016 10:22:03 +0200 Subject: [PATCH 100/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10065afad..e1f16ec14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Change Log --- All changes +* [#630 ] (https://github.com/docker-java/docker-java/pull/630) Fix: Second execution of a docker command in Netty implementation always fails * [#596] (https://github.com/docker-java/docker-java/pull/596) Refactor configuration of SSL to allow override with custom config * [#529] (https://github.com/docker-java/docker-java/pull/529) Refactor CertUtils. Support ECDSA and PrivateKey * [#593] (https://github.com/docker-java/docker-java/pull/593) Added Device.parse() method with simple verification. From 5f9e2bfe2f840467394152cb18695002302e0767 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 12 Jul 2016 11:28:35 +0300 Subject: [PATCH 101/780] Change serial until we didn't ship release --- .../com/github/dockerjava/core/DefaultDockerClientConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java index b21e227ec..a9a15bb36 100644 --- a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -31,7 +31,7 @@ */ public class DefaultDockerClientConfig implements Serializable, DockerClientConfig { - private static final long serialVersionUID = -4307357472441531489L; + private static final long serialVersionUID = 1L; public static final String DOCKER_HOST = "DOCKER_HOST"; From 2f50240329e336d097239b7813949d1ba29d607e Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 12 Jul 2016 11:29:28 +0300 Subject: [PATCH 102/780] Test also on 1.10 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index bb559fd93..31a062e79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ env: matrix: - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" # - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" # - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" From d803c4692efc51bf0e8c138ca3a396947274391d Mon Sep 17 00:00:00 2001 From: Leonid Rudenko Date: Thu, 14 Jul 2016 23:42:54 +0400 Subject: [PATCH 103/780] Implement POST /images/load endpoint (#627) --- .../github/dockerjava/api/DockerClient.java | 13 +++ .../api/command/DockerCmdExecFactory.java | 2 + .../dockerjava/api/command/LoadImageCmd.java | 21 +++++ .../dockerjava/core/DockerClientImpl.java | 7 ++ .../dockerjava/core/RemoteApiVersion.java | 5 ++ .../core/command/LoadImageCmdImpl.java | 39 +++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 6 ++ .../dockerjava/jaxrs/LoadImageCmdExec.java | 31 +++++++ .../netty/DockerCmdExecFactoryImpl.java | 7 ++ .../netty/exec/LoadImageCmdExec.java | 29 +++++++ .../core/TestDockerCmdExecFactory.java | 12 +++ .../core/command/LoadImageCmdImplTest.java | 76 ++++++++++++++++++ .../netty/exec/LoadImageCmdExecTest.java | 76 ++++++++++++++++++ .../dockerjava/utils/TestResources.java | 14 ++++ src/test/resources/api/images/load/image.tar | Bin 0 -> 11264 bytes 15 files changed, 338 insertions(+) create mode 100644 src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java create mode 100644 src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java create mode 100644 src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java create mode 100644 src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java create mode 100644 src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java create mode 100644 src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java create mode 100644 src/test/java/com/github/dockerjava/utils/TestResources.java create mode 100644 src/test/resources/api/images/load/image.tar diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 4c0e2ed56..491c11ac8 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -35,6 +35,7 @@ import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.ListNetworksCmd; import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.api.command.LogContainerCmd; import com.github.dockerjava.api.command.PauseContainerCmd; import com.github.dockerjava.api.command.PingCmd; @@ -90,6 +91,18 @@ public interface DockerClient extends Closeable { CreateImageCmd createImageCmd(@Nonnull String repository, @Nonnull InputStream imageStream); + /** + * Loads a tarball with a set of images and tags into a Docker repository. + * + * Corresponds to POST /images/load API endpoint. + * + * @param imageStream + * stream of the tarball file + * @return created command + * @since {@link RemoteApiVersion#VERSION_1_7} + */ + LoadImageCmd loadImageCmd(@Nonnull InputStream imageStream); + SearchImagesCmd searchImagesCmd(@Nonnull String term); RemoveImageCmd removeImageCmd(@Nonnull String imageId); 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 0de3afe38..671c0d535 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -28,6 +28,8 @@ public interface DockerCmdExecFactory extends Closeable { CreateImageCmd.Exec createCreateImageCmdExec(); + LoadImageCmd.Exec createLoadImageCmdExec(); + SearchImagesCmd.Exec createSearchImagesCmdExec(); RemoveImageCmd.Exec createRemoveImageCmdExec(); diff --git a/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java b/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java new file mode 100644 index 000000000..184b7ef33 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/LoadImageCmd.java @@ -0,0 +1,21 @@ +package com.github.dockerjava.api.command; + +import java.io.InputStream; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +public interface LoadImageCmd extends SyncDockerCmd { + + @CheckForNull + InputStream getImageStream(); + + /** + * @param imageStream + * the InputStream of the tar file + */ + LoadImageCmd withImageStream(@Nonnull InputStream imageStream); + + 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 e11ca4f30..2d0b5caab 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -37,6 +37,7 @@ import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.ListNetworksCmd; import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.api.command.LogContainerCmd; import com.github.dockerjava.api.command.PauseContainerCmd; import com.github.dockerjava.api.command.PingCmd; @@ -89,6 +90,7 @@ import com.github.dockerjava.core.command.ListImagesCmdImpl; import com.github.dockerjava.core.command.ListNetworksCmdImpl; import com.github.dockerjava.core.command.ListVolumesCmdImpl; +import com.github.dockerjava.core.command.LoadImageCmdImpl; import com.github.dockerjava.core.command.LogContainerCmdImpl; import com.github.dockerjava.core.command.PauseContainerCmdImpl; import com.github.dockerjava.core.command.PingCmdImpl; @@ -249,6 +251,11 @@ public CreateImageCmd createImageCmd(String repository, InputStream imageStream) return new CreateImageCmdImpl(getDockerCmdExecFactory().createCreateImageCmdExec(), repository, imageStream); } + @Override + public LoadImageCmd loadImageCmd(@Nonnull InputStream imageStream) { + return new LoadImageCmdImpl(getDockerCmdExecFactory().createLoadImageCmdExec(), imageStream); + } + @Override public SearchImagesCmd searchImagesCmd(String term) { return new SearchImagesCmdImpl(getDockerCmdExecFactory().createSearchImagesCmdExec(), term); diff --git a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java index 992125414..954ed9971 100644 --- a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java +++ b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java @@ -22,6 +22,11 @@ public class RemoteApiVersion implements Serializable { private static final Pattern VERSION_REGEX = Pattern.compile("v?(\\d+)\\.(\\d+)"); + /** + * Online documentation is not available anymore. + */ + public static final RemoteApiVersion VERSION_1_7 = RemoteApiVersion.create(1, 7); + /** * @see Docker API 1.16 */ diff --git a/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java new file mode 100644 index 000000000..496ea3176 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/LoadImageCmdImpl.java @@ -0,0 +1,39 @@ +package com.github.dockerjava.core.command; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.InputStream; + +import com.github.dockerjava.api.command.LoadImageCmd; + +import javax.annotation.Nonnull; + +public class LoadImageCmdImpl extends AbstrDockerCmd implements LoadImageCmd { + + private InputStream imageStream; + + /** + * @param imageStream + * the InputStream of the tar file + */ + public LoadImageCmdImpl(LoadImageCmd.Exec exec, InputStream imageStream) { + super(exec); + withImageStream(imageStream); + } + + @Override + public InputStream getImageStream() { + return imageStream; + } + + /** + * @param imageStream + * the InputStream of the tar file + */ + @Override + public LoadImageCmdImpl withImageStream(@Nonnull InputStream imageStream) { + checkNotNull(imageStream, "imageStream was not specified"); + this.imageStream = imageStream; + return this; + } +} diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 4800f22ae..7e573a123 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -63,6 +63,7 @@ import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.ListNetworksCmd; import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.api.command.LogContainerCmd; import com.github.dockerjava.api.command.PauseContainerCmd; import com.github.dockerjava.api.command.PingCmd; @@ -322,6 +323,11 @@ public CreateImageCmd.Exec createCreateImageCmdExec() { return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public LoadImageCmd.Exec createLoadImageCmdExec() { + return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public SearchImagesCmd.Exec createSearchImagesCmdExec() { return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); diff --git a/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java new file mode 100644 index 000000000..23d6c493a --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/LoadImageCmdExec.java @@ -0,0 +1,31 @@ +package com.github.dockerjava.jaxrs; + +import static javax.ws.rs.client.Entity.entity; + +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.dockerjava.api.command.LoadImageCmd; +import com.github.dockerjava.core.DockerClientConfig; + +public class LoadImageCmdExec extends AbstrSyncDockerCmdExec implements LoadImageCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(LoadImageCmdExec.class); + + public LoadImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected Void execute(LoadImageCmd command) { + WebTarget webTarget = getBaseResource().path("/images/load"); + + LOGGER.trace("POST: {}", webTarget); + webTarget.request().post(entity(command.getImageStream(), MediaType.APPLICATION_OCTET_STREAM)); + + return null; + } +} diff --git a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java index 1f55c61a8..dff69a228 100644 --- a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java @@ -29,6 +29,7 @@ import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.ListNetworksCmd; import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.api.command.LogContainerCmd; import com.github.dockerjava.api.command.PauseContainerCmd; import com.github.dockerjava.api.command.PingCmd; @@ -82,6 +83,7 @@ import com.github.dockerjava.netty.exec.ListImagesCmdExec; import com.github.dockerjava.netty.exec.ListNetworksCmdExec; import com.github.dockerjava.netty.exec.ListVolumesCmdExec; +import com.github.dockerjava.netty.exec.LoadImageCmdExec; import com.github.dockerjava.netty.exec.LogContainerCmdExec; import com.github.dockerjava.netty.exec.PauseContainerCmdExec; import com.github.dockerjava.netty.exec.PingCmdExec; @@ -366,6 +368,11 @@ public CreateImageCmd.Exec createCreateImageCmdExec() { return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public LoadImageCmd.Exec createLoadImageCmdExec() { + return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public SearchImagesCmd.Exec createSearchImagesCmdExec() { return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); diff --git a/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java new file mode 100644 index 000000000..23581119f --- /dev/null +++ b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java @@ -0,0 +1,29 @@ +package com.github.dockerjava.netty.exec; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.github.dockerjava.api.command.LoadImageCmd; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.netty.WebTarget; + +public class LoadImageCmdExec extends AbstrSyncDockerCmdExec implements + LoadImageCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(LoadImageCmdExec.class); + + public LoadImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected Void execute(LoadImageCmd command) { + WebTarget webResource = getBaseResource().path("/images/load"); + + LOGGER.trace("POST: {}", webResource); + return webResource.request() + .post(new TypeReference() { + }, command.getImageStream()); + } +} diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index 48ea1e164..46d6d4dcc 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -34,6 +34,7 @@ import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.ListNetworksCmd; import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.api.command.LogContainerCmd; import com.github.dockerjava.api.command.PauseContainerCmd; import com.github.dockerjava.api.command.PingCmd; @@ -131,6 +132,17 @@ public CreateImageResponse exec(CreateImageCmd command) { }; } + @Override + public LoadImageCmd.Exec createLoadImageCmdExec() { + return new LoadImageCmd.Exec() { + @Override + public Void exec(LoadImageCmd command) { + delegate.createLoadImageCmdExec().exec(command); + return null; + } + }; + } + @Override public RemoveImageCmd.Exec createRemoveImageCmdExec() { return new RemoveImageCmd.Exec() { diff --git a/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java new file mode 100644 index 000000000..7cecf7334 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/LoadImageCmdImplTest.java @@ -0,0 +1,76 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.model.Image; +import com.github.dockerjava.client.AbstractDockerClientTest; + +import com.github.dockerjava.utils.TestResources; +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 java.io.InputStream; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.util.List; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsEqual.equalTo; + +@Test(groups = "integration") +public class LoadImageCmdImplTest extends AbstractDockerClientTest { + + private String expectedImageId; + + @BeforeTest + public void beforeTest() throws Exception { + super.beforeTest(); + } + + @AfterTest + public void afterTest() { + super.afterTest(); + } + + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + expectedImageId = "sha256:56031f66eb0cef2e2e5cb2d1dabafaa0ebcd0a18a507d313b5bdb8c0472c5eba"; + if (findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec()) != null) { + dockerClient.removeImageCmd(expectedImageId).exec(); + } + } + + @AfterMethod + public void afterMethod(ITestResult result) { + dockerClient.removeImageCmd(expectedImageId).exec(); + super.afterMethod(result); + } + + @Test + public void loadImageFromTar() throws Exception { + try (InputStream uploadStream = Files.newInputStream(TestResources.getApiImagesLoadTestTarball())) { + dockerClient.loadImageCmd(uploadStream).exec(); + } + + final Image image = findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec()); + + assertThat("Can't find expected image after loading from a tar archive!", image, notNullValue()); + assertThat("Image after loading from a tar archive has wrong tags!", + asList(image.getRepoTags()), equalTo(singletonList("docker-java/load:1.0"))); + } + + private Image findImageWithId(final String id, final List images) { + for (Image image : images) { + if (id.equals(image.getId())) { + return image; + } + } + return null; + } +} diff --git a/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java new file mode 100644 index 000000000..d978f5662 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/exec/LoadImageCmdExecTest.java @@ -0,0 +1,76 @@ +package com.github.dockerjava.netty.exec; + +import com.github.dockerjava.api.model.Image; + +import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +import com.github.dockerjava.utils.TestResources; +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 java.io.InputStream; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.util.List; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsEqual.equalTo; + +@Test(groups = "integration") +public class LoadImageCmdExecTest extends AbstractNettyDockerClientTest { + + private String expectedImageId; + + @BeforeTest + public void beforeTest() throws Exception { + super.beforeTest(); + } + + @AfterTest + public void afterTest() { + super.afterTest(); + } + + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + expectedImageId = "sha256:56031f66eb0cef2e2e5cb2d1dabafaa0ebcd0a18a507d313b5bdb8c0472c5eba"; + if (findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec()) != null) { + dockerClient.removeImageCmd(expectedImageId).exec(); + } + } + + @AfterMethod + public void afterMethod(ITestResult result) { + dockerClient.removeImageCmd(expectedImageId).exec(); + super.afterMethod(result); + } + + @Test + public void loadImageFromTar() throws Exception { + try (InputStream uploadStream = Files.newInputStream(TestResources.getApiImagesLoadTestTarball())) { + dockerClient.loadImageCmd(uploadStream).exec(); + } + + final Image image = findImageWithId(expectedImageId, dockerClient.listImagesCmd().exec()); + + assertThat("Can't find expected image after loading from a tar archive!", image, notNullValue()); + assertThat("Image after loading from a tar archive has wrong tags!", + asList(image.getRepoTags()), equalTo(singletonList("docker-java/load:1.0"))); + } + + private Image findImageWithId(final String id, final List images) { + for (Image image : images) { + if (id.equals(image.getId())) { + return image; + } + } + return null; + } +} diff --git a/src/test/java/com/github/dockerjava/utils/TestResources.java b/src/test/java/com/github/dockerjava/utils/TestResources.java new file mode 100644 index 000000000..35ece680f --- /dev/null +++ b/src/test/java/com/github/dockerjava/utils/TestResources.java @@ -0,0 +1,14 @@ +package com.github.dockerjava.utils; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class TestResources { + + private TestResources() { + } + + public static Path getApiImagesLoadTestTarball() { + return Paths.get("src/test/resources/api/images/load/image.tar"); + } +} diff --git a/src/test/resources/api/images/load/image.tar b/src/test/resources/api/images/load/image.tar new file mode 100644 index 0000000000000000000000000000000000000000..6f2f08f9e945811249c0027eec3a0de531ead521 GIT binary patch literal 11264 zcmeHNU2oeq6!r6dg~7dSfMfHUl7KyQX@C|e=Az9ybU_eM{7BTwQXt7e1H=D)SGJQl zZc`_<5_AalV2kACC3%i6DISUw%9s-|cByxSTE>L%Owu^wR>{~?N(lB&lGIZk5$z(u zm`oMJ80$#kQE&T&F~>@X9#mJE6eGJe5nab(LwazFe zau2ILEDs4!h)gIO#)?WQW5)h%P0OOuS>Y-$_Hi0x?&FvlDJ&;mOD!~IX+#+Dm@DpL ztWzs36A|a|mLRZnOgax4g3xt$C*as;rzn}BS7qH4dg3-(0PC0K1lnGeLHh4{(GR$L z(KOney>Dz*pv3FEc58X%wD~&IRWO8=u*JQ{(FCa z{PtttXSqv+RVtq}P++db5s*Ov94w|m0d@BaiQsj&Xv3227} zi|M>Wf8TPog@2%*-tbQ;?Ef)gBJlq$EW6IrzjW;}_zMUG1Ofs9f&T*nLSoovOX*T< zoTrXDVNz;|)v5Mc!?A#|Sd&N#tSloe6{$@l1N(AngiH0X1O12NP5p-`9M=CQd3J?Ynf@b+ ziE~gB*Hoqfs>-tQAUn-ab9vrsQ45iw1~JNJ-k)R^%8pQdrm2vLW1M;d$Jf#*2WQj~ z7cm7T*~Lz!B-TVyr5#Cyj%}<(Y?x&auat%)u&@9O40>-di@NZa=R zjFPppVE8_O!1^EbpC5($LG@sA*k2u*pibTeAxPi3^YT!iE`oG9Kka?e7a9&Yv`yf^ zxjj92)5?Ymi|!Oih~(oSXFQ1hUIkp$87vf;s~=YL{?^;#pYZE%g4(ZW+W40u#Q*&P m-obLVI&Hg&(018vgS3M~;rTp-;||<}ssVw3KtSLz5%>?llNJ&H literal 0 HcmV?d00001 From 8be5180513b65be8da2444a71de62f7dba5106c3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 14 Jul 2016 22:44:12 +0300 Subject: [PATCH 104/780] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1f16ec14..4d28a9319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ Change Log --- All changes -* [#630 ] (https://github.com/docker-java/docker-java/pull/630) Fix: Second execution of a docker command in Netty implementation always fails +* [#627] (https://github.com/docker-java/docker-java/pull/627) Implementation of POST /images/load endpoint +* [#630] (https://github.com/docker-java/docker-java/pull/630) Fix: Second execution of a docker command in Netty implementation always fails * [#596] (https://github.com/docker-java/docker-java/pull/596) Refactor configuration of SSL to allow override with custom config * [#529] (https://github.com/docker-java/docker-java/pull/529) Refactor CertUtils. Support ECDSA and PrivateKey * [#593] (https://github.com/docker-java/docker-java/pull/593) Added Device.parse() method with simple verification. From 369a12e410cd4c1fe7d58dde8b5a49920330c4e4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 15 Jul 2016 14:27:25 +0300 Subject: [PATCH 105/780] Try cache coverity (#636) --- .travis.yml | 1 + .travis/travisci_build_coverity_scan.sh | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 31a062e79..bb93f49b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ env: cache: directories: - $HOME/.travis_cache + - /tmp/coverity-cache - $HOME/.m2 # install will pollute it before_install: diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 13af2c275..160945f40 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -11,7 +11,7 @@ echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are [ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 PLATFORM=`uname` -TOOL_ARCHIVE=/tmp/cov-analysis-${PLATFORM}.tgz +TOOL_ARCHIVE=/tmp/coverity-cache/cov-analysis-${PLATFORM}.tgz TOOL_URL=https://scan.coverity.com/download/${PLATFORM} TOOL_BASE=/tmp/coverity-scan-analysis UPLOAD_URL="https://scan.coverity.com/builds" @@ -49,18 +49,20 @@ else fi fi +mkdir -p /tmp/coverity-cache || : + if [ ! -d $TOOL_BASE ]; then # Download Coverity Scan Analysis Tool if [ ! -e $TOOL_ARCHIVE ]; then echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" - wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" + wget -nvN -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" fi # Extract Coverity Scan Analysis Tool echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m" mkdir -p $TOOL_BASE pushd $TOOL_BASE - tar xzf $TOOL_ARCHIVE + tar -xf $TOOL_ARCHIVE popd fi From a87b7894272ff3cb9ffecadd6848fdb45ad777a7 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 15 Jul 2016 14:34:19 +0300 Subject: [PATCH 106/780] Update travisci_build_coverity_scan.sh --- .travis/travisci_build_coverity_scan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 160945f40..a4d978e22 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -55,7 +55,7 @@ if [ ! -d $TOOL_BASE ]; then # Download Coverity Scan Analysis Tool if [ ! -e $TOOL_ARCHIVE ]; then echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" - wget -nvN -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" + wget -nv -N -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" fi # Extract Coverity Scan Analysis Tool From 7bcf6fbe2f561e51d45727b4dac9773f4d162f2f Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 15 Jul 2016 14:52:36 +0300 Subject: [PATCH 107/780] Update travisci_build_coverity_scan.sh --- .travis/travisci_build_coverity_scan.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index a4d978e22..8d0fff04b 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -62,6 +62,9 @@ if [ ! -d $TOOL_BASE ]; then echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m" mkdir -p $TOOL_BASE pushd $TOOL_BASE + du -sh $TOOL_ARCHIVE + file $TOOL_ARCHIVE + ls -la $TOOL_ARCHIVE tar -xf $TOOL_ARCHIVE popd fi From a57fec6f7fa10645589b3b5b9d5e5ea7d2590254 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 15 Jul 2016 17:25:34 +0300 Subject: [PATCH 108/780] Add second run that should be successfull @coverity fails without any clear reason. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index bb93f49b5..a8cbe29e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" From 236e1be53547f86bf279fbbc4ec8daef6e8cf83e Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 00:56:00 +0300 Subject: [PATCH 109/780] Try debug bad travis download --- .travis/travisci_build_coverity_scan.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 8d0fff04b..6bf9a9b1f 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -64,6 +64,7 @@ if [ ! -d $TOOL_BASE ]; then pushd $TOOL_BASE du -sh $TOOL_ARCHIVE file $TOOL_ARCHIVE + file $TOOL_ARCHIVE | grep HTML && cat $TOOL_ARCHIVE || : ls -la $TOOL_ARCHIVE tar -xf $TOOL_ARCHIVE popd From 5dbde940d32b02c57b6c55e87be455846d511eac Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 00:59:46 +0300 Subject: [PATCH 110/780] Fix IT run when it shouldn't CSV and not list. --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5842ac320..130977ba3 100644 --- a/pom.xml +++ b/pom.xml @@ -387,8 +387,7 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - integration - integration-auth + integration,integration-auth From 4db9bee87c58e564479ed55a4929f3e1fa4662a1 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 02:08:13 +0300 Subject: [PATCH 111/780] fix concurrency issue --- .../exec/AttachContainerCmdExecTest.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index 675c11177..7daa59b25 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.netty.exec; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.isEmptyString; @@ -70,7 +71,7 @@ public void onNext(Frame frame) { }; dockerClient.attachContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withFollowStream(true) - .withLogs(true).exec(callback).awaitCompletion(10, TimeUnit.SECONDS); + .withLogs(true).exec(callback).awaitCompletion(10, SECONDS); callback.close(); assertThat(callback.toString(), containsString(snippet)); @@ -81,33 +82,40 @@ public void attachContainerWithStdin() throws Exception { String snippet = "hello world"; - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("/bin/sh", "-c", "read line && echo $line") - .withTty(false).withStdinOpen(true).exec(); + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("/bin/sh", "-c", "sleep 1 && read line && echo $line") + .withTty(false) + .withStdinOpen(true) + .exec(); LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainerCmd(container.getId()).exec(); + Thread.sleep(SECONDS.toMillis(3)); //wait bash initialisation + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); assertTrue(inspectContainerResponse.getState().getRunning()); AttachContainerTestCallback callback = new AttachContainerTestCallback() { - @Override public void onNext(Frame frame) { assertEquals(frame.getStreamType(), StreamType.STDOUT); super.onNext(frame); - }; + } }; InputStream stdin = new ByteArrayInputStream((snippet + "\n").getBytes()); - dockerClient.attachContainerCmd(container.getId()).withStdErr(true).withStdOut(true).withFollowStream(true) + dockerClient.attachContainerCmd(container.getId()) + .withStdErr(true) + .withStdOut(true) + .withFollowStream(true) .withStdIn(stdin) .exec(callback) - .awaitCompletion(5, TimeUnit.SECONDS); + .awaitCompletion(15, SECONDS); callback.close(); assertThat(callback.toString(), containsString(snippet)); @@ -141,7 +149,7 @@ public void onNext(Frame frame) { .withStdOut(true) .withFollowStream(true) .exec(callback) - .awaitCompletion(10, TimeUnit.SECONDS); + .awaitCompletion(10, SECONDS); callback.close(); // HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0); From 582331a85ad9bc529b4d8a37d1d80d286bd57b25 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 02:48:09 +0300 Subject: [PATCH 112/780] Verify coverity before not downloading it --- .travis/travisci_build_coverity_scan.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 6bf9a9b1f..a73c66536 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -52,6 +52,13 @@ fi mkdir -p /tmp/coverity-cache || : if [ ! -d $TOOL_BASE ]; then + + # verify that binary is right + if file $TOOL_ARCHIVE | grep HTML ; then + echo "Removing $TOOL_ARCHIVE" + rm -f $TOOL_ARCHIVE + fi + # Download Coverity Scan Analysis Tool if [ ! -e $TOOL_ARCHIVE ]; then echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" From eacea85d70e689e03407572ff982983ecea0c640 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 03:23:56 +0300 Subject: [PATCH 113/780] Don't spam with warnings @coverity using bsd tar?? --- .travis/travisci_build_coverity_scan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index a73c66536..7f30638e1 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -73,7 +73,7 @@ if [ ! -d $TOOL_BASE ]; then file $TOOL_ARCHIVE file $TOOL_ARCHIVE | grep HTML && cat $TOOL_ARCHIVE || : ls -la $TOOL_ARCHIVE - tar -xf $TOOL_ARCHIVE + tar -xf $TOOL_ARCHIVE | grep -v "Ignoring unknown extended header keyword" popd fi From 59db6da8f40f7559c9e33968f5ba5a8283df3673 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 03:26:10 +0300 Subject: [PATCH 114/780] Try limit threadCount Default is parallel test, when there are many tests they become slow and fails. --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 130977ba3..7f51e9d99 100644 --- a/pom.xml +++ b/pom.xml @@ -402,6 +402,9 @@ verify + true + true + 1 integration integration-auth From 51fe92d8400541afb7fdeb170b55bfa91538920e Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 03:54:24 +0300 Subject: [PATCH 115/780] Update travisci_build_coverity_scan.sh --- .travis/travisci_build_coverity_scan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 7f30638e1..933ddae37 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -73,7 +73,7 @@ if [ ! -d $TOOL_BASE ]; then file $TOOL_ARCHIVE file $TOOL_ARCHIVE | grep HTML && cat $TOOL_ARCHIVE || : ls -la $TOOL_ARCHIVE - tar -xf $TOOL_ARCHIVE | grep -v "Ignoring unknown extended header keyword" + tar -xf $TOOL_ARCHIVE |& grep -v "Ignoring unknown extended header keyword" popd fi From 9578981d860478f0c8bda9d1da5b481bdd960c5d Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 03:57:44 +0300 Subject: [PATCH 116/780] Update netty Try fix #632 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f51e9d99..1d4328f9b 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ 1.1.7 6.9.10 - 4.1.1.Final + 4.1.3.Final 1.3 1.8 2.3.3 From 22fe7a6794c91f6a73988099eaf7e2f3e91bf25b Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 04:18:14 +0300 Subject: [PATCH 117/780] Update travisci_build_coverity_scan.sh --- .travis/travisci_build_coverity_scan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travisci_build_coverity_scan.sh b/.travis/travisci_build_coverity_scan.sh index 933ddae37..074d0a46f 100755 --- a/.travis/travisci_build_coverity_scan.sh +++ b/.travis/travisci_build_coverity_scan.sh @@ -73,7 +73,7 @@ if [ ! -d $TOOL_BASE ]; then file $TOOL_ARCHIVE file $TOOL_ARCHIVE | grep HTML && cat $TOOL_ARCHIVE || : ls -la $TOOL_ARCHIVE - tar -xf $TOOL_ARCHIVE |& grep -v "Ignoring unknown extended header keyword" + tar -xf $TOOL_ARCHIVE #|& grep -v "Ignoring unknown extended header keyword" popd fi From 83ac192b85614c0263aebfcb5ef298d9a9cf0b52 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 22 Jul 2016 11:10:09 +0300 Subject: [PATCH 118/780] Name classes normally (#639) * Name classes normally --- .../dockerjava/core/DockerClientBuilder.java | 4 +- .../jaxrs/DockerCmdExecFactoryImpl.java | 586 +----------------- .../jaxrs/JerseyDockerCmdExecFactory.java | 583 +++++++++++++++++ .../netty/DockerCmdExecFactoryImpl.java | 585 +---------------- .../netty/NettyDockerCmdExecFactory.java | 586 ++++++++++++++++++ .../netty/AbstractNettyDockerClientTest.java | 2 +- 6 files changed, 1182 insertions(+), 1164 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java create mode 100644 src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java diff --git a/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java b/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java index 743b8c2ef..991bdbb86 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java @@ -3,7 +3,7 @@ import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.DockerCmdExecFactory; import com.github.dockerjava.core.DefaultDockerClientConfig.Builder; -import com.github.dockerjava.jaxrs.DockerCmdExecFactoryImpl; +import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory; public class DockerClientBuilder { @@ -32,7 +32,7 @@ public static DockerClientBuilder getInstance(String serverUrl) { } public static DockerCmdExecFactory getDefaultDockerCmdExecFactory() { - return new DockerCmdExecFactoryImpl(); + return new JerseyDockerCmdExecFactory(); } public DockerClientBuilder withDockerCmdExecFactory(DockerCmdExecFactory dockerCmdExecFactory) { diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 7e573a123..1d407e233 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -1,583 +1,9 @@ package com.github.dockerjava.jaxrs; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.ProxySelector; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; - -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 com.github.dockerjava.api.command.UpdateContainerCmd; -import com.github.dockerjava.core.SSLConfig; - -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.apache.connector.ApacheConnectorProvider; -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.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.ConnectToNetworkCmd; -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.CreateNetworkCmd; -import com.github.dockerjava.api.command.CreateVolumeCmd; -import com.github.dockerjava.api.command.DisconnectFromNetworkCmd; -import com.github.dockerjava.api.command.DockerCmdExecFactory; -import com.github.dockerjava.api.command.EventsCmd; -import com.github.dockerjava.api.command.ExecCreateCmd; -import com.github.dockerjava.api.command.ExecStartCmd; -import com.github.dockerjava.api.command.InfoCmd; -import com.github.dockerjava.api.command.InspectContainerCmd; -import com.github.dockerjava.api.command.InspectExecCmd; -import com.github.dockerjava.api.command.InspectImageCmd; -import com.github.dockerjava.api.command.InspectNetworkCmd; -import com.github.dockerjava.api.command.InspectVolumeCmd; -import com.github.dockerjava.api.command.KillContainerCmd; -import com.github.dockerjava.api.command.ListContainersCmd; -import com.github.dockerjava.api.command.ListImagesCmd; -import com.github.dockerjava.api.command.ListNetworksCmd; -import com.github.dockerjava.api.command.ListVolumesCmd; -import com.github.dockerjava.api.command.LoadImageCmd; -import com.github.dockerjava.api.command.LogContainerCmd; -import com.github.dockerjava.api.command.PauseContainerCmd; -import com.github.dockerjava.api.command.PingCmd; -import com.github.dockerjava.api.command.PullImageCmd; -import com.github.dockerjava.api.command.PushImageCmd; -import com.github.dockerjava.api.command.RemoveContainerCmd; -import com.github.dockerjava.api.command.RemoveImageCmd; -import com.github.dockerjava.api.command.RemoveNetworkCmd; -import com.github.dockerjava.api.command.RemoveVolumeCmd; -import com.github.dockerjava.api.command.RestartContainerCmd; -import com.github.dockerjava.api.command.SaveImageCmd; -import com.github.dockerjava.api.command.SearchImagesCmd; -import com.github.dockerjava.api.command.StartContainerCmd; -import com.github.dockerjava.api.command.StatsCmd; -import com.github.dockerjava.api.command.StopContainerCmd; -import com.github.dockerjava.api.command.TagImageCmd; -import com.github.dockerjava.api.command.TopContainerCmd; -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.command.RenameContainerCmd; -import com.github.dockerjava.api.exception.DockerClientException; -import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.jaxrs.filter.JsonClientFilter; -import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; -import com.github.dockerjava.jaxrs.filter.SelectiveLoggingFilter; - -//import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; -// see https://github.com/docker-java/docker-java/issues/196 - -public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(DockerCmdExecFactoryImpl.class.getName()); - - private Client client; - - private WebTarget baseResource; - - private Integer readTimeout = null; - - private Integer connectTimeout = null; - - private Integer maxTotalConnections = null; - - private Integer maxPerRouteConnections = null; - - private ClientRequestFilter[] clientRequestFilters = null; - - private ClientResponseFilter[] clientResponseFilters = null; - - private DockerClientConfig dockerClientConfig; - - private PoolingHttpClientConnectionManager connManager = null; - - @Override - public void init(DockerClientConfig dockerClientConfig) { - checkNotNull(dockerClientConfig, "config was not specified"); - this.dockerClientConfig = dockerClientConfig; - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.connectorProvider(new ApacheConnectorProvider()); - clientConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); - - clientConfig.register(ResponseStatusExceptionFilter.class); - clientConfig.register(JsonClientFilter.class); - clientConfig.register(JacksonJsonProvider.class); - - // logging may disabled via log level - clientConfig.register(new SelectiveLoggingFilter(LOGGER, true)); - - if (readTimeout != null) { - clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout); - } - - if (connectTimeout != null) { - clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout); - } - - if (clientResponseFilters != null) { - for (ClientResponseFilter clientResponseFilter : clientResponseFilters) { - if (clientResponseFilter != null) { - clientConfig.register(clientResponseFilter); - } - } - } - - if (clientRequestFilters != null) { - for (ClientRequestFilter clientRequestFilter : clientRequestFilters) { - if (clientRequestFilter != null) { - clientConfig.register(clientRequestFilter); - } - } - } - - URI originalUri = dockerClientConfig.getDockerHost(); - - String protocol = null; - - SSLContext sslContext = null; - - try { - final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); - if (sslConfig != null) { - sslContext = sslConfig.getSSLContext(); - } - } catch (Exception ex) { - throw new DockerClientException("Error in SSL Configuration", ex); - } - - if (sslContext != null) { - protocol = "https"; - } else { - protocol = "http"; - } - - if (!originalUri.getScheme().equals("unix")) { - - try { - originalUri = new URI(originalUri.toString().replaceFirst("tcp", protocol)); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - - configureProxy(clientConfig, protocol); - } - - connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry( - originalUri, sslContext)) { - - @Override - public void close() { - super.shutdown(); - } - - @Override - public void shutdown() { - // Disable shutdown of the pool. This will be done later, when this factory is closed - // This is a workaround for finalize method on jerseys ClientRuntime which - // closes the client and shuts down the connection pool when it is garbage collected - } - }; - - if (maxTotalConnections != null) { - connManager.setMaxTotal(maxTotalConnections); - } - if (maxPerRouteConnections != null) { - connManager.setDefaultMaxPerRoute(maxPerRouteConnections); - } - - clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connManager); - - // Configure connection pool timeout - // clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, RequestConfig.custom() - // .setConnectionRequestTimeout(1000).build()); - - ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); - - if (sslContext != null) { - clientBuilder.sslContext(sslContext); - } - - client = clientBuilder.build(); - - baseResource = client.target(sanitizeUrl(originalUri).toString()).path(dockerClientConfig.getApiVersion().asWebPathPart()); - } - - private URI sanitizeUrl(URI originalUri) { - if (originalUri.getScheme().equals("unix")) { - return UnixConnectionSocketFactory.sanitizeUri(originalUri); - } - return originalUri; - } - - private void configureProxy(ClientConfig clientConfig, String protocol) { - - List proxies = ProxySelector.getDefault().select(dockerClientConfig.getDockerHost()); - - for (Proxy proxy : proxies) { - InetSocketAddress address = (InetSocketAddress) proxy.address(); - if (address != null) { - String hostname = address.getHostName(); - int port = address.getPort(); - - clientConfig.property(ClientProperties.PROXY_URI, "http://" + hostname + ":" + port); - - String httpProxyUser = System.getProperty(protocol + ".proxyUser"); - if (httpProxyUser != null) { - clientConfig.property(ClientProperties.PROXY_USERNAME, httpProxyUser); - String httpProxyPassword = System.getProperty(protocol + ".proxyPassword"); - if (httpProxyPassword != null) { - clientConfig.property(ClientProperties.PROXY_PASSWORD, httpProxyPassword); - } - } - } - } - } - - private org.apache.http.config.Registry getSchemeRegistry(final URI originalUri, - SSLContext sslContext) { - RegistryBuilder registryBuilder = RegistryBuilder.create(); - registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory()); - if (sslContext != null) { - registryBuilder.register("https", new SSLConnectionSocketFactory(sslContext)); - } - registryBuilder.register("unix", new UnixConnectionSocketFactory(originalUri)); - return registryBuilder.build(); - } - - protected WebTarget getBaseResource() { - checkNotNull(baseResource, "Factory not initialized, baseResource not set. You probably forgot to call init()!"); - return baseResource; - } - - protected DockerClientConfig getDockerClientConfig() { - checkNotNull(dockerClientConfig, - "Factor not initialized, dockerClientConfig not set. You probably forgot to call init()!"); - return dockerClientConfig; - } - - @Override - public AuthCmd.Exec createAuthCmdExec() { - return new AuthCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InfoCmd.Exec createInfoCmdExec() { - return new InfoCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PingCmd.Exec createPingCmdExec() { - return new PingCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public VersionCmd.Exec createVersionCmdExec() { - return new VersionCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PullImageCmd.Exec createPullImageCmdExec() { - return new PullImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PushImageCmd.Exec createPushImageCmdExec() { - return new PushImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public SaveImageCmd.Exec createSaveImageCmdExec() { - return new SaveImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateImageCmd.Exec createCreateImageCmdExec() { - return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public LoadImageCmd.Exec createLoadImageCmdExec() { - return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public SearchImagesCmd.Exec createSearchImagesCmdExec() { - return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveImageCmd.Exec createRemoveImageCmdExec() { - return new RemoveImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListImagesCmd.Exec createListImagesCmdExec() { - return new ListImagesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectImageCmd.Exec createInspectImageCmdExec() { - return new InspectImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListContainersCmd.Exec createListContainersCmdExec() { - return new ListContainersCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateContainerCmd.Exec createCreateContainerCmdExec() { - return new CreateContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public StartContainerCmd.Exec createStartContainerCmdExec() { - return new StartContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectContainerCmd.Exec createInspectContainerCmdExec() { - return new InspectContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ExecCreateCmd.Exec createExecCmdExec() { - return new ExecCreateCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveContainerCmd.Exec createRemoveContainerCmdExec() { - return new RemoveContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public WaitContainerCmd.Exec createWaitContainerCmdExec() { - return new WaitContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public AttachContainerCmd.Exec createAttachContainerCmdExec() { - return new AttachContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ExecStartCmd.Exec createExecStartCmdExec() { - return new ExecStartCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectExecCmd.Exec createInspectExecCmdExec() { - return new InspectExecCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public LogContainerCmd.Exec createLogContainerCmdExec() { - return new LogContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - 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()); - } - - @Override - public StopContainerCmd.Exec createStopContainerCmdExec() { - return new StopContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ContainerDiffCmd.Exec createContainerDiffCmdExec() { - return new ContainerDiffCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public KillContainerCmd.Exec createKillContainerCmdExec() { - return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public UpdateContainerCmd.Exec createUpdateContainerCmdExec() { - return new UpdateContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RenameContainerCmd.Exec createRenameContainerCmdExec() { - return new RenameContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RestartContainerCmd.Exec createRestartContainerCmdExec() { - return new RestartContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CommitCmd.Exec createCommitCmdExec() { - return new CommitCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public BuildImageCmd.Exec createBuildImageCmdExec() { - return new BuildImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public TopContainerCmd.Exec createTopContainerCmdExec() { - return new TopContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public TagImageCmd.Exec createTagImageCmdExec() { - return new TagImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PauseContainerCmd.Exec createPauseContainerCmdExec() { - return new PauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public UnpauseContainerCmd.Exec createUnpauseContainerCmdExec() { - return new UnpauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public EventsCmd.Exec createEventsCmdExec() { - return new EventsCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public StatsCmd.Exec createStatsCmdExec() { - return new StatsCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateVolumeCmd.Exec createCreateVolumeCmdExec() { - return new CreateVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectVolumeCmd.Exec createInspectVolumeCmdExec() { - return new InspectVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveVolumeCmd.Exec createRemoveVolumeCmdExec() { - return new RemoveVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListVolumesCmd.Exec createListVolumesCmdExec() { - return new ListVolumesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListNetworksCmd.Exec createListNetworksCmdExec() { - return new ListNetworksCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectNetworkCmd.Exec createInspectNetworkCmdExec() { - - return new InspectNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateNetworkCmd.Exec createCreateNetworkCmdExec() { - - return new CreateNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveNetworkCmd.Exec createRemoveNetworkCmdExec() { - - return new RemoveNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ConnectToNetworkCmd.Exec createConnectToNetworkCmdExec() { - - return new ConnectToNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() { - - return new DisconnectFromNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public void close() throws IOException { - checkNotNull(client, "Factory not initialized. You probably forgot to call init()!"); - client.close(); - connManager.close(); - } - - public DockerCmdExecFactoryImpl withReadTimeout(Integer readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - public DockerCmdExecFactoryImpl withConnectTimeout(Integer connectTimeout) { - this.connectTimeout = connectTimeout; - return this; - } - - public DockerCmdExecFactoryImpl withMaxTotalConnections(Integer maxTotalConnections) { - this.maxTotalConnections = maxTotalConnections; - return this; - } - - public DockerCmdExecFactoryImpl withMaxPerRouteConnections(Integer maxPerRouteConnections) { - this.maxPerRouteConnections = maxPerRouteConnections; - return this; - } - - public DockerCmdExecFactoryImpl withClientResponseFilters(ClientResponseFilter... clientResponseFilter) { - this.clientResponseFilters = clientResponseFilter; - return this; - } - - public DockerCmdExecFactoryImpl withClientRequestFilters(ClientRequestFilter... clientRequestFilters) { - this.clientRequestFilters = clientRequestFilters; - return this; - } - +/** + * @author Kanstantsin Shautsou + * @deprecated clashes with netty impl. + */ +@Deprecated +public class DockerCmdExecFactoryImpl extends JerseyDockerCmdExecFactory { } diff --git a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java new file mode 100644 index 000000000..3339a2696 --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java @@ -0,0 +1,583 @@ +package com.github.dockerjava.jaxrs; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +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 com.github.dockerjava.api.command.UpdateContainerCmd; +import com.github.dockerjava.core.SSLConfig; + +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.apache.connector.ApacheConnectorProvider; +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.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.ConnectToNetworkCmd; +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.CreateNetworkCmd; +import com.github.dockerjava.api.command.CreateVolumeCmd; +import com.github.dockerjava.api.command.DisconnectFromNetworkCmd; +import com.github.dockerjava.api.command.DockerCmdExecFactory; +import com.github.dockerjava.api.command.EventsCmd; +import com.github.dockerjava.api.command.ExecCreateCmd; +import com.github.dockerjava.api.command.ExecStartCmd; +import com.github.dockerjava.api.command.InfoCmd; +import com.github.dockerjava.api.command.InspectContainerCmd; +import com.github.dockerjava.api.command.InspectExecCmd; +import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.InspectNetworkCmd; +import com.github.dockerjava.api.command.InspectVolumeCmd; +import com.github.dockerjava.api.command.KillContainerCmd; +import com.github.dockerjava.api.command.ListContainersCmd; +import com.github.dockerjava.api.command.ListImagesCmd; +import com.github.dockerjava.api.command.ListNetworksCmd; +import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; +import com.github.dockerjava.api.command.LogContainerCmd; +import com.github.dockerjava.api.command.PauseContainerCmd; +import com.github.dockerjava.api.command.PingCmd; +import com.github.dockerjava.api.command.PullImageCmd; +import com.github.dockerjava.api.command.PushImageCmd; +import com.github.dockerjava.api.command.RemoveContainerCmd; +import com.github.dockerjava.api.command.RemoveImageCmd; +import com.github.dockerjava.api.command.RemoveNetworkCmd; +import com.github.dockerjava.api.command.RemoveVolumeCmd; +import com.github.dockerjava.api.command.RestartContainerCmd; +import com.github.dockerjava.api.command.SaveImageCmd; +import com.github.dockerjava.api.command.SearchImagesCmd; +import com.github.dockerjava.api.command.StartContainerCmd; +import com.github.dockerjava.api.command.StatsCmd; +import com.github.dockerjava.api.command.StopContainerCmd; +import com.github.dockerjava.api.command.TagImageCmd; +import com.github.dockerjava.api.command.TopContainerCmd; +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.command.RenameContainerCmd; +import com.github.dockerjava.api.exception.DockerClientException; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.jaxrs.filter.JsonClientFilter; +import com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter; +import com.github.dockerjava.jaxrs.filter.SelectiveLoggingFilter; + +//import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +// see https://github.com/docker-java/docker-java/issues/196 + +public class JerseyDockerCmdExecFactory implements DockerCmdExecFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(JerseyDockerCmdExecFactory.class.getName()); + + private Client client; + + private WebTarget baseResource; + + private Integer readTimeout = null; + + private Integer connectTimeout = null; + + private Integer maxTotalConnections = null; + + private Integer maxPerRouteConnections = null; + + private ClientRequestFilter[] clientRequestFilters = null; + + private ClientResponseFilter[] clientResponseFilters = null; + + private DockerClientConfig dockerClientConfig; + + private PoolingHttpClientConnectionManager connManager = null; + + @Override + public void init(DockerClientConfig dockerClientConfig) { + checkNotNull(dockerClientConfig, "config was not specified"); + this.dockerClientConfig = dockerClientConfig; + + ClientConfig clientConfig = new ClientConfig(); + clientConfig.connectorProvider(new ApacheConnectorProvider()); + clientConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); + + clientConfig.register(ResponseStatusExceptionFilter.class); + clientConfig.register(JsonClientFilter.class); + clientConfig.register(JacksonJsonProvider.class); + + // logging may disabled via log level + clientConfig.register(new SelectiveLoggingFilter(LOGGER, true)); + + if (readTimeout != null) { + clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout); + } + + if (connectTimeout != null) { + clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout); + } + + if (clientResponseFilters != null) { + for (ClientResponseFilter clientResponseFilter : clientResponseFilters) { + if (clientResponseFilter != null) { + clientConfig.register(clientResponseFilter); + } + } + } + + if (clientRequestFilters != null) { + for (ClientRequestFilter clientRequestFilter : clientRequestFilters) { + if (clientRequestFilter != null) { + clientConfig.register(clientRequestFilter); + } + } + } + + URI originalUri = dockerClientConfig.getDockerHost(); + + String protocol = null; + + SSLContext sslContext = null; + + try { + final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); + if (sslConfig != null) { + sslContext = sslConfig.getSSLContext(); + } + } catch (Exception ex) { + throw new DockerClientException("Error in SSL Configuration", ex); + } + + if (sslContext != null) { + protocol = "https"; + } else { + protocol = "http"; + } + + if (!originalUri.getScheme().equals("unix")) { + + try { + originalUri = new URI(originalUri.toString().replaceFirst("tcp", protocol)); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + + configureProxy(clientConfig, protocol); + } + + connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry( + originalUri, sslContext)) { + + @Override + public void close() { + super.shutdown(); + } + + @Override + public void shutdown() { + // Disable shutdown of the pool. This will be done later, when this factory is closed + // This is a workaround for finalize method on jerseys ClientRuntime which + // closes the client and shuts down the connection pool when it is garbage collected + } + }; + + if (maxTotalConnections != null) { + connManager.setMaxTotal(maxTotalConnections); + } + if (maxPerRouteConnections != null) { + connManager.setDefaultMaxPerRoute(maxPerRouteConnections); + } + + clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connManager); + + // Configure connection pool timeout + // clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, RequestConfig.custom() + // .setConnectionRequestTimeout(1000).build()); + + ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); + + if (sslContext != null) { + clientBuilder.sslContext(sslContext); + } + + client = clientBuilder.build(); + + baseResource = client.target(sanitizeUrl(originalUri).toString()).path(dockerClientConfig.getApiVersion().asWebPathPart()); + } + + private URI sanitizeUrl(URI originalUri) { + if (originalUri.getScheme().equals("unix")) { + return UnixConnectionSocketFactory.sanitizeUri(originalUri); + } + return originalUri; + } + + private void configureProxy(ClientConfig clientConfig, String protocol) { + + List proxies = ProxySelector.getDefault().select(dockerClientConfig.getDockerHost()); + + for (Proxy proxy : proxies) { + InetSocketAddress address = (InetSocketAddress) proxy.address(); + if (address != null) { + String hostname = address.getHostName(); + int port = address.getPort(); + + clientConfig.property(ClientProperties.PROXY_URI, "http://" + hostname + ":" + port); + + String httpProxyUser = System.getProperty(protocol + ".proxyUser"); + if (httpProxyUser != null) { + clientConfig.property(ClientProperties.PROXY_USERNAME, httpProxyUser); + String httpProxyPassword = System.getProperty(protocol + ".proxyPassword"); + if (httpProxyPassword != null) { + clientConfig.property(ClientProperties.PROXY_PASSWORD, httpProxyPassword); + } + } + } + } + } + + private org.apache.http.config.Registry getSchemeRegistry(final URI originalUri, + SSLContext sslContext) { + RegistryBuilder registryBuilder = RegistryBuilder.create(); + registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory()); + if (sslContext != null) { + registryBuilder.register("https", new SSLConnectionSocketFactory(sslContext)); + } + registryBuilder.register("unix", new UnixConnectionSocketFactory(originalUri)); + return registryBuilder.build(); + } + + protected WebTarget getBaseResource() { + checkNotNull(baseResource, "Factory not initialized, baseResource not set. You probably forgot to call init()!"); + return baseResource; + } + + protected DockerClientConfig getDockerClientConfig() { + checkNotNull(dockerClientConfig, + "Factor not initialized, dockerClientConfig not set. You probably forgot to call init()!"); + return dockerClientConfig; + } + + @Override + public AuthCmd.Exec createAuthCmdExec() { + return new AuthCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InfoCmd.Exec createInfoCmdExec() { + return new InfoCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PingCmd.Exec createPingCmdExec() { + return new PingCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public VersionCmd.Exec createVersionCmdExec() { + return new VersionCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PullImageCmd.Exec createPullImageCmdExec() { + return new PullImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PushImageCmd.Exec createPushImageCmdExec() { + return new PushImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public SaveImageCmd.Exec createSaveImageCmdExec() { + return new SaveImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateImageCmd.Exec createCreateImageCmdExec() { + return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public LoadImageCmd.Exec createLoadImageCmdExec() { + return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public SearchImagesCmd.Exec createSearchImagesCmdExec() { + return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveImageCmd.Exec createRemoveImageCmdExec() { + return new RemoveImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListImagesCmd.Exec createListImagesCmdExec() { + return new ListImagesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectImageCmd.Exec createInspectImageCmdExec() { + return new InspectImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListContainersCmd.Exec createListContainersCmdExec() { + return new ListContainersCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateContainerCmd.Exec createCreateContainerCmdExec() { + return new CreateContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public StartContainerCmd.Exec createStartContainerCmdExec() { + return new StartContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectContainerCmd.Exec createInspectContainerCmdExec() { + return new InspectContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ExecCreateCmd.Exec createExecCmdExec() { + return new ExecCreateCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveContainerCmd.Exec createRemoveContainerCmdExec() { + return new RemoveContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public WaitContainerCmd.Exec createWaitContainerCmdExec() { + return new WaitContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public AttachContainerCmd.Exec createAttachContainerCmdExec() { + return new AttachContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ExecStartCmd.Exec createExecStartCmdExec() { + return new ExecStartCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectExecCmd.Exec createInspectExecCmdExec() { + return new InspectExecCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public LogContainerCmd.Exec createLogContainerCmdExec() { + return new LogContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + 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()); + } + + @Override + public StopContainerCmd.Exec createStopContainerCmdExec() { + return new StopContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ContainerDiffCmd.Exec createContainerDiffCmdExec() { + return new ContainerDiffCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public KillContainerCmd.Exec createKillContainerCmdExec() { + return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public UpdateContainerCmd.Exec createUpdateContainerCmdExec() { + return new UpdateContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RenameContainerCmd.Exec createRenameContainerCmdExec() { + return new RenameContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RestartContainerCmd.Exec createRestartContainerCmdExec() { + return new RestartContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CommitCmd.Exec createCommitCmdExec() { + return new CommitCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public BuildImageCmd.Exec createBuildImageCmdExec() { + return new BuildImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public TopContainerCmd.Exec createTopContainerCmdExec() { + return new TopContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public TagImageCmd.Exec createTagImageCmdExec() { + return new TagImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PauseContainerCmd.Exec createPauseContainerCmdExec() { + return new PauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public UnpauseContainerCmd.Exec createUnpauseContainerCmdExec() { + return new UnpauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public EventsCmd.Exec createEventsCmdExec() { + return new EventsCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public StatsCmd.Exec createStatsCmdExec() { + return new StatsCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateVolumeCmd.Exec createCreateVolumeCmdExec() { + return new CreateVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectVolumeCmd.Exec createInspectVolumeCmdExec() { + return new InspectVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveVolumeCmd.Exec createRemoveVolumeCmdExec() { + return new RemoveVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListVolumesCmd.Exec createListVolumesCmdExec() { + return new ListVolumesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListNetworksCmd.Exec createListNetworksCmdExec() { + return new ListNetworksCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectNetworkCmd.Exec createInspectNetworkCmdExec() { + + return new InspectNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateNetworkCmd.Exec createCreateNetworkCmdExec() { + + return new CreateNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveNetworkCmd.Exec createRemoveNetworkCmdExec() { + + return new RemoveNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ConnectToNetworkCmd.Exec createConnectToNetworkCmdExec() { + + return new ConnectToNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() { + + return new DisconnectFromNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public void close() throws IOException { + checkNotNull(client, "Factory not initialized. You probably forgot to call init()!"); + client.close(); + connManager.close(); + } + + public JerseyDockerCmdExecFactory withReadTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + public JerseyDockerCmdExecFactory withConnectTimeout(Integer connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + public JerseyDockerCmdExecFactory withMaxTotalConnections(Integer maxTotalConnections) { + this.maxTotalConnections = maxTotalConnections; + return this; + } + + public JerseyDockerCmdExecFactory withMaxPerRouteConnections(Integer maxPerRouteConnections) { + this.maxPerRouteConnections = maxPerRouteConnections; + return this; + } + + public JerseyDockerCmdExecFactory withClientResponseFilters(ClientResponseFilter... clientResponseFilter) { + this.clientResponseFilters = clientResponseFilter; + return this; + } + + public JerseyDockerCmdExecFactory withClientRequestFilters(ClientRequestFilter... clientRequestFilters) { + this.clientRequestFilters = clientRequestFilters; + return this; + } + +} diff --git a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java index dff69a228..25825d169 100644 --- a/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/netty/DockerCmdExecFactoryImpl.java @@ -1,586 +1,9 @@ package com.github.dockerjava.netty; -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.ConnectToNetworkCmd; -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.CreateNetworkCmd; -import com.github.dockerjava.api.command.CreateVolumeCmd; -import com.github.dockerjava.api.command.DisconnectFromNetworkCmd; -import com.github.dockerjava.api.command.DockerCmdExecFactory; -import com.github.dockerjava.api.command.EventsCmd; -import com.github.dockerjava.api.command.ExecCreateCmd; -import com.github.dockerjava.api.command.ExecStartCmd; -import com.github.dockerjava.api.command.InfoCmd; -import com.github.dockerjava.api.command.InspectContainerCmd; -import com.github.dockerjava.api.command.InspectExecCmd; -import com.github.dockerjava.api.command.InspectImageCmd; -import com.github.dockerjava.api.command.InspectNetworkCmd; -import com.github.dockerjava.api.command.InspectVolumeCmd; -import com.github.dockerjava.api.command.KillContainerCmd; -import com.github.dockerjava.api.command.ListContainersCmd; -import com.github.dockerjava.api.command.ListImagesCmd; -import com.github.dockerjava.api.command.ListNetworksCmd; -import com.github.dockerjava.api.command.ListVolumesCmd; -import com.github.dockerjava.api.command.LoadImageCmd; -import com.github.dockerjava.api.command.LogContainerCmd; -import com.github.dockerjava.api.command.PauseContainerCmd; -import com.github.dockerjava.api.command.PingCmd; -import com.github.dockerjava.api.command.PullImageCmd; -import com.github.dockerjava.api.command.PushImageCmd; -import com.github.dockerjava.api.command.RemoveContainerCmd; -import com.github.dockerjava.api.command.RemoveImageCmd; -import com.github.dockerjava.api.command.RemoveNetworkCmd; -import com.github.dockerjava.api.command.RemoveVolumeCmd; -import com.github.dockerjava.api.command.RestartContainerCmd; -import com.github.dockerjava.api.command.SaveImageCmd; -import com.github.dockerjava.api.command.SearchImagesCmd; -import com.github.dockerjava.api.command.StartContainerCmd; -import com.github.dockerjava.api.command.StatsCmd; -import com.github.dockerjava.api.command.StopContainerCmd; -import com.github.dockerjava.api.command.TagImageCmd; -import com.github.dockerjava.api.command.TopContainerCmd; -import com.github.dockerjava.api.command.UnpauseContainerCmd; -import com.github.dockerjava.api.command.UpdateContainerCmd; -import com.github.dockerjava.api.command.VersionCmd; -import com.github.dockerjava.api.command.WaitContainerCmd; -import com.github.dockerjava.api.command.RenameContainerCmd; -import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.core.DockerClientImpl; -import com.github.dockerjava.core.SSLConfig; -import com.github.dockerjava.netty.exec.AttachContainerCmdExec; -import com.github.dockerjava.netty.exec.AuthCmdExec; -import com.github.dockerjava.netty.exec.BuildImageCmdExec; -import com.github.dockerjava.netty.exec.CommitCmdExec; -import com.github.dockerjava.netty.exec.ConnectToNetworkCmdExec; -import com.github.dockerjava.netty.exec.ContainerDiffCmdExec; -import com.github.dockerjava.netty.exec.CopyArchiveFromContainerCmdExec; -import com.github.dockerjava.netty.exec.CopyArchiveToContainerCmdExec; -import com.github.dockerjava.netty.exec.CopyFileFromContainerCmdExec; -import com.github.dockerjava.netty.exec.CreateContainerCmdExec; -import com.github.dockerjava.netty.exec.CreateImageCmdExec; -import com.github.dockerjava.netty.exec.CreateNetworkCmdExec; -import com.github.dockerjava.netty.exec.CreateVolumeCmdExec; -import com.github.dockerjava.netty.exec.DisconnectFromNetworkCmdExec; -import com.github.dockerjava.netty.exec.EventsCmdExec; -import com.github.dockerjava.netty.exec.ExecCreateCmdExec; -import com.github.dockerjava.netty.exec.ExecStartCmdExec; -import com.github.dockerjava.netty.exec.InfoCmdExec; -import com.github.dockerjava.netty.exec.InspectContainerCmdExec; -import com.github.dockerjava.netty.exec.InspectExecCmdExec; -import com.github.dockerjava.netty.exec.InspectImageCmdExec; -import com.github.dockerjava.netty.exec.InspectNetworkCmdExec; -import com.github.dockerjava.netty.exec.InspectVolumeCmdExec; -import com.github.dockerjava.netty.exec.KillContainerCmdExec; -import com.github.dockerjava.netty.exec.ListContainersCmdExec; -import com.github.dockerjava.netty.exec.ListImagesCmdExec; -import com.github.dockerjava.netty.exec.ListNetworksCmdExec; -import com.github.dockerjava.netty.exec.ListVolumesCmdExec; -import com.github.dockerjava.netty.exec.LoadImageCmdExec; -import com.github.dockerjava.netty.exec.LogContainerCmdExec; -import com.github.dockerjava.netty.exec.PauseContainerCmdExec; -import com.github.dockerjava.netty.exec.PingCmdExec; -import com.github.dockerjava.netty.exec.PullImageCmdExec; -import com.github.dockerjava.netty.exec.PushImageCmdExec; -import com.github.dockerjava.netty.exec.RemoveContainerCmdExec; -import com.github.dockerjava.netty.exec.RemoveImageCmdExec; -import com.github.dockerjava.netty.exec.RemoveNetworkCmdExec; -import com.github.dockerjava.netty.exec.RemoveVolumeCmdExec; -import com.github.dockerjava.netty.exec.RestartContainerCmdExec; -import com.github.dockerjava.netty.exec.SaveImageCmdExec; -import com.github.dockerjava.netty.exec.SearchImagesCmdExec; -import com.github.dockerjava.netty.exec.StartContainerCmdExec; -import com.github.dockerjava.netty.exec.StatsCmdExec; -import com.github.dockerjava.netty.exec.StopContainerCmdExec; -import com.github.dockerjava.netty.exec.TagImageCmdExec; -import com.github.dockerjava.netty.exec.TopContainerCmdExec; -import com.github.dockerjava.netty.exec.UnpauseContainerCmdExec; -import com.github.dockerjava.netty.exec.UpdateContainerCmdExec; -import com.github.dockerjava.netty.exec.VersionCmdExec; -import com.github.dockerjava.netty.exec.WaitContainerCmdExec; -import com.github.dockerjava.netty.exec.RenameContainerCmdExec; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.epoll.EpollDomainSocketChannel; -import io.netty.channel.epoll.EpollEventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.DuplexChannel; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.channel.unix.DomainSocketAddress; -import io.netty.channel.unix.UnixChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.logging.LoggingHandler; -import io.netty.handler.ssl.SslHandler; -import io.netty.util.concurrent.DefaultThreadFactory; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.security.Security; - -import static com.google.common.base.Preconditions.checkNotNull; - /** - * Experimental implementation of {@link DockerCmdExecFactory} that supports http connection hijacking that is needed to pass STDIN to the - * container. - * - * To use it just pass an instance via {@link DockerClientImpl#withDockerCmdExecFactory(DockerCmdExecFactory)} - * - * @see https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/#attach-to-a-container - * @see https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/#exec-start - * - * - * @author Marcus Linke + * @author Kanstantsin Shautsou + * @deprecated old clashing name */ -public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { - - private static String threadPrefix = "dockerjava-netty"; - - /* - * useful links: - * - * http://stackoverflow.com/questions/33296749/netty-connect-to-unix-domain-socket-failed - * http://netty.io/wiki/native-transports.html - * https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java - * https://github.com/slandelle/netty-request-chunking/blob/master/src/test/java/slandelle/ChunkingTest.java - */ - - private DockerClientConfig dockerClientConfig; - - private Bootstrap bootstrap; - - private EventLoopGroup eventLoopGroup; - - private NettyInitializer nettyInitializer; - - private ChannelProvider channelProvider = new ChannelProvider() { - @Override - public DuplexChannel getChannel() { - DuplexChannel channel = connect(); - channel.pipeline().addLast(new LoggingHandler(getClass())); - return channel; - } - }; - - @Override - public void init(DockerClientConfig dockerClientConfig) { - checkNotNull(dockerClientConfig, "config was not specified"); - this.dockerClientConfig = dockerClientConfig; - - bootstrap = new Bootstrap(); - - String scheme = dockerClientConfig.getDockerHost().getScheme(); - - if ("unix".equals(scheme)) { - nettyInitializer = new UnixDomainSocketInitializer(); - } else if ("tcp".equals(scheme)) { - nettyInitializer = new InetSocketInitializer(); - } - - eventLoopGroup = nettyInitializer.init(bootstrap, dockerClientConfig); - } - - private DuplexChannel connect() { - try { - return connect(bootstrap); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - private DuplexChannel connect(final Bootstrap bootstrap) throws InterruptedException { - return nettyInitializer.connect(bootstrap); - } - - private interface NettyInitializer { - EventLoopGroup init(final Bootstrap bootstrap, DockerClientConfig dockerClientConfig); - - DuplexChannel connect(final Bootstrap bootstrap) throws InterruptedException; - } - - private class UnixDomainSocketInitializer implements NettyInitializer { - @Override - public EventLoopGroup init(Bootstrap bootstrap, DockerClientConfig dockerClientConfig) { - EventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); - bootstrap.group(epollEventLoopGroup).channel(EpollDomainSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(final UnixChannel channel) throws Exception { - channel.pipeline().addLast(new HttpClientCodec()); - } - }); - return epollEventLoopGroup; - } - - @Override - public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { - return (DuplexChannel) bootstrap.connect(new DomainSocketAddress("/var/run/docker.sock")).sync().channel(); - } - } - - private class InetSocketInitializer implements NettyInitializer { - @Override - public EventLoopGroup init(Bootstrap bootstrap, final DockerClientConfig dockerClientConfig) { - EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); - - InetAddress addr = InetAddress.getLoopbackAddress(); - - final SocketAddress proxyAddress = new InetSocketAddress(addr, 8008); - - Security.addProvider(new BouncyCastleProvider()); - - bootstrap.group(nioEventLoopGroup).channel(NioSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(final SocketChannel channel) throws Exception { - // channel.pipeline().addLast(new - // HttpProxyHandler(proxyAddress)); - channel.pipeline().addLast(new HttpClientCodec()); - } - }); - - return nioEventLoopGroup; - } - - @Override - public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { - String host = dockerClientConfig.getDockerHost().getHost(); - int port = dockerClientConfig.getDockerHost().getPort(); - - if (port == -1) { - throw new RuntimeException("no port configured for " + host); - } - - DuplexChannel channel = (DuplexChannel) bootstrap.connect(host, port).sync().channel(); - - final SslHandler ssl = initSsl(dockerClientConfig); - - if (ssl != null) { - channel.pipeline().addFirst(ssl); - } - - return channel; - } - - private SslHandler initSsl(DockerClientConfig dockerClientConfig) { - SslHandler ssl = null; - - try { - String host = dockerClientConfig.getDockerHost().getHost(); - int port = dockerClientConfig.getDockerHost().getPort(); - - final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); - - if (sslConfig != null && sslConfig.getSSLContext() != null) { - - SSLEngine engine = sslConfig.getSSLContext().createSSLEngine(host, port); - engine.setUseClientMode(true); - engine.setSSLParameters(enableHostNameVerification(engine.getSSLParameters())); - - // in the future we may use HostnameVerifier like here: - // https://github.com/AsyncHttpClient/async-http-client/blob/1.8.x/src/main/java/com/ning/http/client/providers/netty/NettyConnectListener.java#L76 - - ssl = new SslHandler(engine); - } - - } catch (Exception e) { - throw new RuntimeException(e); - } - - return ssl; - } - } - - protected DockerClientConfig getDockerClientConfig() { - checkNotNull(dockerClientConfig, - "Factor not initialized, dockerClientConfig not set. You probably forgot to call init()!"); - return dockerClientConfig; - } - - public SSLParameters enableHostNameVerification(SSLParameters sslParameters) { - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); - return sslParameters; - } - - @Override - public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() { - return new CopyArchiveFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() { - return new CopyArchiveToContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public AuthCmd.Exec createAuthCmdExec() { - return new AuthCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InfoCmd.Exec createInfoCmdExec() { - return new InfoCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PingCmd.Exec createPingCmdExec() { - return new PingCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public VersionCmd.Exec createVersionCmdExec() { - return new VersionCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PullImageCmd.Exec createPullImageCmdExec() { - return new PullImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PushImageCmd.Exec createPushImageCmdExec() { - return new PushImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public SaveImageCmd.Exec createSaveImageCmdExec() { - return new SaveImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateImageCmd.Exec createCreateImageCmdExec() { - return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public LoadImageCmd.Exec createLoadImageCmdExec() { - return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public SearchImagesCmd.Exec createSearchImagesCmdExec() { - return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveImageCmd.Exec createRemoveImageCmdExec() { - return new RemoveImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListImagesCmd.Exec createListImagesCmdExec() { - return new ListImagesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectImageCmd.Exec createInspectImageCmdExec() { - return new InspectImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListContainersCmd.Exec createListContainersCmdExec() { - return new ListContainersCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateContainerCmd.Exec createCreateContainerCmdExec() { - return new CreateContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public StartContainerCmd.Exec createStartContainerCmdExec() { - return new StartContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectContainerCmd.Exec createInspectContainerCmdExec() { - return new InspectContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ExecCreateCmd.Exec createExecCmdExec() { - return new ExecCreateCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveContainerCmd.Exec createRemoveContainerCmdExec() { - return new RemoveContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public WaitContainerCmd.Exec createWaitContainerCmdExec() { - return new WaitContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public AttachContainerCmd.Exec createAttachContainerCmdExec() { - return new AttachContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ExecStartCmd.Exec createExecStartCmdExec() { - return new ExecStartCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectExecCmd.Exec createInspectExecCmdExec() { - return new InspectExecCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public LogContainerCmd.Exec createLogContainerCmdExec() { - return new LogContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { - return new CopyFileFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public StopContainerCmd.Exec createStopContainerCmdExec() { - return new StopContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ContainerDiffCmd.Exec createContainerDiffCmdExec() { - return new ContainerDiffCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public KillContainerCmd.Exec createKillContainerCmdExec() { - return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public UpdateContainerCmd.Exec createUpdateContainerCmdExec() { - return new UpdateContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RenameContainerCmd.Exec createRenameContainerCmdExec() { - return new RenameContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RestartContainerCmd.Exec createRestartContainerCmdExec() { - return new RestartContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CommitCmd.Exec createCommitCmdExec() { - return new CommitCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public BuildImageCmd.Exec createBuildImageCmdExec() { - return new BuildImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public TopContainerCmd.Exec createTopContainerCmdExec() { - return new TopContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public TagImageCmd.Exec createTagImageCmdExec() { - return new TagImageCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public PauseContainerCmd.Exec createPauseContainerCmdExec() { - return new PauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public UnpauseContainerCmd.Exec createUnpauseContainerCmdExec() { - return new UnpauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public EventsCmd.Exec createEventsCmdExec() { - return new EventsCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public StatsCmd.Exec createStatsCmdExec() { - return new StatsCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateVolumeCmd.Exec createCreateVolumeCmdExec() { - return new CreateVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectVolumeCmd.Exec createInspectVolumeCmdExec() { - return new InspectVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveVolumeCmd.Exec createRemoveVolumeCmdExec() { - return new RemoveVolumeCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListVolumesCmd.Exec createListVolumesCmdExec() { - return new ListVolumesCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ListNetworksCmd.Exec createListNetworksCmdExec() { - return new ListNetworksCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public InspectNetworkCmd.Exec createInspectNetworkCmdExec() { - return new InspectNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public CreateNetworkCmd.Exec createCreateNetworkCmdExec() { - return new CreateNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public RemoveNetworkCmd.Exec createRemoveNetworkCmdExec() { - return new RemoveNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public ConnectToNetworkCmd.Exec createConnectToNetworkCmdExec() { - return new ConnectToNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() { - return new DisconnectFromNetworkCmdExec(getBaseResource(), getDockerClientConfig()); - } - - @Override - public void close() throws IOException { - checkNotNull(eventLoopGroup, "Factory not initialized. You probably forgot to call init()!"); - - eventLoopGroup.shutdownGracefully(); - } - - private WebTarget getBaseResource() { - return new WebTarget(channelProvider); - } +@Deprecated +public class DockerCmdExecFactoryImpl extends NettyDockerCmdExecFactory { } diff --git a/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java new file mode 100644 index 000000000..cead92e92 --- /dev/null +++ b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java @@ -0,0 +1,586 @@ +package com.github.dockerjava.netty; + +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.ConnectToNetworkCmd; +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.CreateNetworkCmd; +import com.github.dockerjava.api.command.CreateVolumeCmd; +import com.github.dockerjava.api.command.DisconnectFromNetworkCmd; +import com.github.dockerjava.api.command.DockerCmdExecFactory; +import com.github.dockerjava.api.command.EventsCmd; +import com.github.dockerjava.api.command.ExecCreateCmd; +import com.github.dockerjava.api.command.ExecStartCmd; +import com.github.dockerjava.api.command.InfoCmd; +import com.github.dockerjava.api.command.InspectContainerCmd; +import com.github.dockerjava.api.command.InspectExecCmd; +import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.InspectNetworkCmd; +import com.github.dockerjava.api.command.InspectVolumeCmd; +import com.github.dockerjava.api.command.KillContainerCmd; +import com.github.dockerjava.api.command.ListContainersCmd; +import com.github.dockerjava.api.command.ListImagesCmd; +import com.github.dockerjava.api.command.ListNetworksCmd; +import com.github.dockerjava.api.command.ListVolumesCmd; +import com.github.dockerjava.api.command.LoadImageCmd; +import com.github.dockerjava.api.command.LogContainerCmd; +import com.github.dockerjava.api.command.PauseContainerCmd; +import com.github.dockerjava.api.command.PingCmd; +import com.github.dockerjava.api.command.PullImageCmd; +import com.github.dockerjava.api.command.PushImageCmd; +import com.github.dockerjava.api.command.RemoveContainerCmd; +import com.github.dockerjava.api.command.RemoveImageCmd; +import com.github.dockerjava.api.command.RemoveNetworkCmd; +import com.github.dockerjava.api.command.RemoveVolumeCmd; +import com.github.dockerjava.api.command.RestartContainerCmd; +import com.github.dockerjava.api.command.SaveImageCmd; +import com.github.dockerjava.api.command.SearchImagesCmd; +import com.github.dockerjava.api.command.StartContainerCmd; +import com.github.dockerjava.api.command.StatsCmd; +import com.github.dockerjava.api.command.StopContainerCmd; +import com.github.dockerjava.api.command.TagImageCmd; +import com.github.dockerjava.api.command.TopContainerCmd; +import com.github.dockerjava.api.command.UnpauseContainerCmd; +import com.github.dockerjava.api.command.UpdateContainerCmd; +import com.github.dockerjava.api.command.VersionCmd; +import com.github.dockerjava.api.command.WaitContainerCmd; +import com.github.dockerjava.api.command.RenameContainerCmd; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.DockerClientImpl; +import com.github.dockerjava.core.SSLConfig; +import com.github.dockerjava.netty.exec.AttachContainerCmdExec; +import com.github.dockerjava.netty.exec.AuthCmdExec; +import com.github.dockerjava.netty.exec.BuildImageCmdExec; +import com.github.dockerjava.netty.exec.CommitCmdExec; +import com.github.dockerjava.netty.exec.ConnectToNetworkCmdExec; +import com.github.dockerjava.netty.exec.ContainerDiffCmdExec; +import com.github.dockerjava.netty.exec.CopyArchiveFromContainerCmdExec; +import com.github.dockerjava.netty.exec.CopyArchiveToContainerCmdExec; +import com.github.dockerjava.netty.exec.CopyFileFromContainerCmdExec; +import com.github.dockerjava.netty.exec.CreateContainerCmdExec; +import com.github.dockerjava.netty.exec.CreateImageCmdExec; +import com.github.dockerjava.netty.exec.CreateNetworkCmdExec; +import com.github.dockerjava.netty.exec.CreateVolumeCmdExec; +import com.github.dockerjava.netty.exec.DisconnectFromNetworkCmdExec; +import com.github.dockerjava.netty.exec.EventsCmdExec; +import com.github.dockerjava.netty.exec.ExecCreateCmdExec; +import com.github.dockerjava.netty.exec.ExecStartCmdExec; +import com.github.dockerjava.netty.exec.InfoCmdExec; +import com.github.dockerjava.netty.exec.InspectContainerCmdExec; +import com.github.dockerjava.netty.exec.InspectExecCmdExec; +import com.github.dockerjava.netty.exec.InspectImageCmdExec; +import com.github.dockerjava.netty.exec.InspectNetworkCmdExec; +import com.github.dockerjava.netty.exec.InspectVolumeCmdExec; +import com.github.dockerjava.netty.exec.KillContainerCmdExec; +import com.github.dockerjava.netty.exec.ListContainersCmdExec; +import com.github.dockerjava.netty.exec.ListImagesCmdExec; +import com.github.dockerjava.netty.exec.ListNetworksCmdExec; +import com.github.dockerjava.netty.exec.ListVolumesCmdExec; +import com.github.dockerjava.netty.exec.LoadImageCmdExec; +import com.github.dockerjava.netty.exec.LogContainerCmdExec; +import com.github.dockerjava.netty.exec.PauseContainerCmdExec; +import com.github.dockerjava.netty.exec.PingCmdExec; +import com.github.dockerjava.netty.exec.PullImageCmdExec; +import com.github.dockerjava.netty.exec.PushImageCmdExec; +import com.github.dockerjava.netty.exec.RemoveContainerCmdExec; +import com.github.dockerjava.netty.exec.RemoveImageCmdExec; +import com.github.dockerjava.netty.exec.RemoveNetworkCmdExec; +import com.github.dockerjava.netty.exec.RemoveVolumeCmdExec; +import com.github.dockerjava.netty.exec.RestartContainerCmdExec; +import com.github.dockerjava.netty.exec.SaveImageCmdExec; +import com.github.dockerjava.netty.exec.SearchImagesCmdExec; +import com.github.dockerjava.netty.exec.StartContainerCmdExec; +import com.github.dockerjava.netty.exec.StatsCmdExec; +import com.github.dockerjava.netty.exec.StopContainerCmdExec; +import com.github.dockerjava.netty.exec.TagImageCmdExec; +import com.github.dockerjava.netty.exec.TopContainerCmdExec; +import com.github.dockerjava.netty.exec.UnpauseContainerCmdExec; +import com.github.dockerjava.netty.exec.UpdateContainerCmdExec; +import com.github.dockerjava.netty.exec.VersionCmdExec; +import com.github.dockerjava.netty.exec.WaitContainerCmdExec; +import com.github.dockerjava.netty.exec.RenameContainerCmdExec; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollDomainSocketChannel; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.DuplexChannel; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.channel.unix.DomainSocketAddress; +import io.netty.channel.unix.UnixChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslHandler; +import io.netty.util.concurrent.DefaultThreadFactory; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.security.Security; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Experimental implementation of {@link DockerCmdExecFactory} that supports http connection hijacking that is needed to pass STDIN to the + * container. + * + * To use it just pass an instance via {@link DockerClientImpl#withDockerCmdExecFactory(DockerCmdExecFactory)} + * + * @see https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/#attach-to-a-container + * @see https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/#exec-start + * + * + * @author Marcus Linke + */ +public class NettyDockerCmdExecFactory implements DockerCmdExecFactory { + + private static String threadPrefix = "dockerjava-netty"; + + /* + * useful links: + * + * http://stackoverflow.com/questions/33296749/netty-connect-to-unix-domain-socket-failed + * http://netty.io/wiki/native-transports.html + * https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java + * https://github.com/slandelle/netty-request-chunking/blob/master/src/test/java/slandelle/ChunkingTest.java + */ + + private DockerClientConfig dockerClientConfig; + + private Bootstrap bootstrap; + + private EventLoopGroup eventLoopGroup; + + private NettyInitializer nettyInitializer; + + private ChannelProvider channelProvider = new ChannelProvider() { + @Override + public DuplexChannel getChannel() { + DuplexChannel channel = connect(); + channel.pipeline().addLast(new LoggingHandler(getClass())); + return channel; + } + }; + + @Override + public void init(DockerClientConfig dockerClientConfig) { + checkNotNull(dockerClientConfig, "config was not specified"); + this.dockerClientConfig = dockerClientConfig; + + bootstrap = new Bootstrap(); + + String scheme = dockerClientConfig.getDockerHost().getScheme(); + + if ("unix".equals(scheme)) { + nettyInitializer = new UnixDomainSocketInitializer(); + } else if ("tcp".equals(scheme)) { + nettyInitializer = new InetSocketInitializer(); + } + + eventLoopGroup = nettyInitializer.init(bootstrap, dockerClientConfig); + } + + private DuplexChannel connect() { + try { + return connect(bootstrap); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + private DuplexChannel connect(final Bootstrap bootstrap) throws InterruptedException { + return nettyInitializer.connect(bootstrap); + } + + private interface NettyInitializer { + EventLoopGroup init(final Bootstrap bootstrap, DockerClientConfig dockerClientConfig); + + DuplexChannel connect(final Bootstrap bootstrap) throws InterruptedException; + } + + private class UnixDomainSocketInitializer implements NettyInitializer { + @Override + public EventLoopGroup init(Bootstrap bootstrap, DockerClientConfig dockerClientConfig) { + EventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); + bootstrap.group(epollEventLoopGroup).channel(EpollDomainSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(final UnixChannel channel) throws Exception { + channel.pipeline().addLast(new HttpClientCodec()); + } + }); + return epollEventLoopGroup; + } + + @Override + public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { + return (DuplexChannel) bootstrap.connect(new DomainSocketAddress("/var/run/docker.sock")).sync().channel(); + } + } + + private class InetSocketInitializer implements NettyInitializer { + @Override + public EventLoopGroup init(Bootstrap bootstrap, final DockerClientConfig dockerClientConfig) { + EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); + + InetAddress addr = InetAddress.getLoopbackAddress(); + + final SocketAddress proxyAddress = new InetSocketAddress(addr, 8008); + + Security.addProvider(new BouncyCastleProvider()); + + bootstrap.group(nioEventLoopGroup).channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(final SocketChannel channel) throws Exception { + // channel.pipeline().addLast(new + // HttpProxyHandler(proxyAddress)); + channel.pipeline().addLast(new HttpClientCodec()); + } + }); + + return nioEventLoopGroup; + } + + @Override + public DuplexChannel connect(Bootstrap bootstrap) throws InterruptedException { + String host = dockerClientConfig.getDockerHost().getHost(); + int port = dockerClientConfig.getDockerHost().getPort(); + + if (port == -1) { + throw new RuntimeException("no port configured for " + host); + } + + DuplexChannel channel = (DuplexChannel) bootstrap.connect(host, port).sync().channel(); + + final SslHandler ssl = initSsl(dockerClientConfig); + + if (ssl != null) { + channel.pipeline().addFirst(ssl); + } + + return channel; + } + + private SslHandler initSsl(DockerClientConfig dockerClientConfig) { + SslHandler ssl = null; + + try { + String host = dockerClientConfig.getDockerHost().getHost(); + int port = dockerClientConfig.getDockerHost().getPort(); + + final SSLConfig sslConfig = dockerClientConfig.getSSLConfig(); + + if (sslConfig != null && sslConfig.getSSLContext() != null) { + + SSLEngine engine = sslConfig.getSSLContext().createSSLEngine(host, port); + engine.setUseClientMode(true); + engine.setSSLParameters(enableHostNameVerification(engine.getSSLParameters())); + + // in the future we may use HostnameVerifier like here: + // https://github.com/AsyncHttpClient/async-http-client/blob/1.8.x/src/main/java/com/ning/http/client/providers/netty/NettyConnectListener.java#L76 + + ssl = new SslHandler(engine); + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + + return ssl; + } + } + + protected DockerClientConfig getDockerClientConfig() { + checkNotNull(dockerClientConfig, + "Factor not initialized, dockerClientConfig not set. You probably forgot to call init()!"); + return dockerClientConfig; + } + + public SSLParameters enableHostNameVerification(SSLParameters sslParameters) { + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + return sslParameters; + } + + @Override + public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() { + return new CopyArchiveFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() { + return new CopyArchiveToContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public AuthCmd.Exec createAuthCmdExec() { + return new AuthCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InfoCmd.Exec createInfoCmdExec() { + return new InfoCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PingCmd.Exec createPingCmdExec() { + return new PingCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public VersionCmd.Exec createVersionCmdExec() { + return new VersionCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PullImageCmd.Exec createPullImageCmdExec() { + return new PullImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PushImageCmd.Exec createPushImageCmdExec() { + return new PushImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public SaveImageCmd.Exec createSaveImageCmdExec() { + return new SaveImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateImageCmd.Exec createCreateImageCmdExec() { + return new CreateImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public LoadImageCmd.Exec createLoadImageCmdExec() { + return new LoadImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public SearchImagesCmd.Exec createSearchImagesCmdExec() { + return new SearchImagesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveImageCmd.Exec createRemoveImageCmdExec() { + return new RemoveImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListImagesCmd.Exec createListImagesCmdExec() { + return new ListImagesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectImageCmd.Exec createInspectImageCmdExec() { + return new InspectImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListContainersCmd.Exec createListContainersCmdExec() { + return new ListContainersCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateContainerCmd.Exec createCreateContainerCmdExec() { + return new CreateContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public StartContainerCmd.Exec createStartContainerCmdExec() { + return new StartContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectContainerCmd.Exec createInspectContainerCmdExec() { + return new InspectContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ExecCreateCmd.Exec createExecCmdExec() { + return new ExecCreateCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveContainerCmd.Exec createRemoveContainerCmdExec() { + return new RemoveContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public WaitContainerCmd.Exec createWaitContainerCmdExec() { + return new WaitContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public AttachContainerCmd.Exec createAttachContainerCmdExec() { + return new AttachContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ExecStartCmd.Exec createExecStartCmdExec() { + return new ExecStartCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectExecCmd.Exec createInspectExecCmdExec() { + return new InspectExecCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public LogContainerCmd.Exec createLogContainerCmdExec() { + return new LogContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() { + return new CopyFileFromContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public StopContainerCmd.Exec createStopContainerCmdExec() { + return new StopContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ContainerDiffCmd.Exec createContainerDiffCmdExec() { + return new ContainerDiffCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public KillContainerCmd.Exec createKillContainerCmdExec() { + return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public UpdateContainerCmd.Exec createUpdateContainerCmdExec() { + return new UpdateContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RenameContainerCmd.Exec createRenameContainerCmdExec() { + return new RenameContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RestartContainerCmd.Exec createRestartContainerCmdExec() { + return new RestartContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CommitCmd.Exec createCommitCmdExec() { + return new CommitCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public BuildImageCmd.Exec createBuildImageCmdExec() { + return new BuildImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public TopContainerCmd.Exec createTopContainerCmdExec() { + return new TopContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public TagImageCmd.Exec createTagImageCmdExec() { + return new TagImageCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public PauseContainerCmd.Exec createPauseContainerCmdExec() { + return new PauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public UnpauseContainerCmd.Exec createUnpauseContainerCmdExec() { + return new UnpauseContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public EventsCmd.Exec createEventsCmdExec() { + return new EventsCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public StatsCmd.Exec createStatsCmdExec() { + return new StatsCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateVolumeCmd.Exec createCreateVolumeCmdExec() { + return new CreateVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectVolumeCmd.Exec createInspectVolumeCmdExec() { + return new InspectVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveVolumeCmd.Exec createRemoveVolumeCmdExec() { + return new RemoveVolumeCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListVolumesCmd.Exec createListVolumesCmdExec() { + return new ListVolumesCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ListNetworksCmd.Exec createListNetworksCmdExec() { + return new ListNetworksCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public InspectNetworkCmd.Exec createInspectNetworkCmdExec() { + return new InspectNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public CreateNetworkCmd.Exec createCreateNetworkCmdExec() { + return new CreateNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public RemoveNetworkCmd.Exec createRemoveNetworkCmdExec() { + return new RemoveNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public ConnectToNetworkCmd.Exec createConnectToNetworkCmdExec() { + return new ConnectToNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() { + return new DisconnectFromNetworkCmdExec(getBaseResource(), getDockerClientConfig()); + } + + @Override + public void close() throws IOException { + checkNotNull(eventLoopGroup, "Factory not initialized. You probably forgot to call init()!"); + + eventLoopGroup.shutdownGracefully(); + } + + private WebTarget getBaseResource() { + return new WebTarget(channelProvider); + } +} diff --git a/src/test/java/com/github/dockerjava/netty/AbstractNettyDockerClientTest.java b/src/test/java/com/github/dockerjava/netty/AbstractNettyDockerClientTest.java index 44a541808..57f7aa421 100644 --- a/src/test/java/com/github/dockerjava/netty/AbstractNettyDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/netty/AbstractNettyDockerClientTest.java @@ -12,6 +12,6 @@ public abstract class AbstractNettyDockerClientTest extends AbstractDockerClient @Override protected TestDockerCmdExecFactory initTestDockerCmdExecFactory() { - return new TestDockerCmdExecFactory(new DockerCmdExecFactoryImpl()); + return new TestDockerCmdExecFactory(new NettyDockerCmdExecFactory()); } } From e8b8519bbfb32cc1c5f3b6533b8b32fe7950103a Mon Sep 17 00:00:00 2001 From: tjlee Date: Fri, 29 Jul 2016 17:11:02 +0300 Subject: [PATCH 119/780] [tests] Added integration tests for pause / unpause commands (#647) * [tests] Added integration tests for pause / unpause commands * [tests] added missing netty tests; fixed javadoc text; fixed annotations; --- .../core/command/PauseCmdImplTest.java | 103 +++++++++++++++ .../core/command/UnpauseCmdImplTest.java | 118 ++++++++++++++++++ .../netty/exec/PauseCmdImplTest.java | 103 +++++++++++++++ .../netty/exec/UnpauseCmdImplTest.java | 118 ++++++++++++++++++ .../dockerjava/utils/ContainerUtils.java | 70 +++++++++++ 5 files changed, 512 insertions(+) create mode 100644 src/test/java/com/github/dockerjava/core/command/PauseCmdImplTest.java create mode 100644 src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java create mode 100644 src/test/java/com/github/dockerjava/netty/exec/PauseCmdImplTest.java create mode 100644 src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java create mode 100644 src/test/java/com/github/dockerjava/utils/ContainerUtils.java diff --git a/src/test/java/com/github/dockerjava/core/command/PauseCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PauseCmdImplTest.java new file mode 100644 index 000000000..f100c4f89 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/PauseCmdImplTest.java @@ -0,0 +1,103 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.exception.InternalServerErrorException; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.utils.ContainerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +@Test(groups = {"integration", "ignoreInCircleCi"}) +public class PauseCmdImplTest extends AbstractDockerClientTest { + + public static final Logger LOG = LoggerFactory.getLogger(PauseCmdImplTest.class); + + @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 pauseRunningContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + } + + @Test(expectedExceptions = NotFoundException.class) + public void pauseNonExistingContainer() { + + dockerClient.pauseContainerCmd("non-existing").exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pauseStoppedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.stopContainer(dockerClient, container); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pausePausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pauseCreatedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } +} diff --git a/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java new file mode 100644 index 000000000..f640c4182 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java @@ -0,0 +1,118 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.exception.InternalServerErrorException; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.utils.ContainerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +@Test(groups = {"integration", "ignoreInCircleCi"}) +public class UnpauseCmdImplTest extends AbstractDockerClientTest { + + public static final Logger LOG = LoggerFactory.getLogger(UnpauseCmdImplTest.class); + + @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 unpausePausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + ContainerUtils.unpaseContainer(dockerClient, container); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseRunningContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseStoppedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.stopContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = NotFoundException.class) + public void unpauseNonExistingContainer() { + + dockerClient.unpauseContainerCmd("non-existing").exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseCreatedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseUnpausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } +} diff --git a/src/test/java/com/github/dockerjava/netty/exec/PauseCmdImplTest.java b/src/test/java/com/github/dockerjava/netty/exec/PauseCmdImplTest.java new file mode 100644 index 000000000..612c3efd2 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/exec/PauseCmdImplTest.java @@ -0,0 +1,103 @@ +package com.github.dockerjava.netty.exec; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.exception.InternalServerErrorException; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +import com.github.dockerjava.utils.ContainerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +@Test(groups = {"integration", "ignoreInCircleCi"}) +public class PauseCmdImplTest extends AbstractNettyDockerClientTest { + + public static final Logger LOG = LoggerFactory.getLogger(PauseCmdImplTest.class); + + @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 pauseRunningContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + } + + @Test(expectedExceptions = NotFoundException.class) + public void pauseNonExistingContainer() { + + dockerClient.pauseContainerCmd("non-existing").exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pauseStoppedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.stopContainer(dockerClient, container); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pausePausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void pauseCreatedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.pauseContainerCmd(container.getId()).exec(); + } +} diff --git a/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java b/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java new file mode 100644 index 000000000..db91bc9f9 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java @@ -0,0 +1,118 @@ +package com.github.dockerjava.netty.exec; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.exception.InternalServerErrorException; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +import com.github.dockerjava.utils.ContainerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +@Test(groups = {"integration", "ignoreInCircleCi"}) +public class UnpauseCmdImplTest extends AbstractNettyDockerClientTest { + + public static final Logger LOG = LoggerFactory.getLogger(UnpauseCmdImplTest.class); + + @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 unpausePausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + ContainerUtils.unpaseContainer(dockerClient, container); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseRunningContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseStoppedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.stopContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = NotFoundException.class) + public void unpauseNonExistingContainer() { + + dockerClient.unpauseContainerCmd("non-existing").exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseCreatedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } + + @Test(expectedExceptions = InternalServerErrorException.class) + public void unpauseUnpausedContainer() { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + ContainerUtils.startContainer(dockerClient, container); + + ContainerUtils.pauseContainer(dockerClient, container); + + dockerClient.unpauseContainerCmd(container.getId()).exec(); + dockerClient.unpauseContainerCmd(container.getId()).exec(); + } +} diff --git a/src/test/java/com/github/dockerjava/utils/ContainerUtils.java b/src/test/java/com/github/dockerjava/utils/ContainerUtils.java new file mode 100644 index 000000000..75be6c4d9 --- /dev/null +++ b/src/test/java/com/github/dockerjava/utils/ContainerUtils.java @@ -0,0 +1,70 @@ +package com.github.dockerjava.utils; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Container cmd utils + */ +public class ContainerUtils { + + private ContainerUtils() { + } + + /** + * Starts container and ensures that it running + * + * @param dockerClient docker client + * @param container container + */ + public static void startContainer(DockerClient dockerClient, CreateContainerResponse container) { + dockerClient.startContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + assertThat(inspectContainerResponse.getState().getRunning(), is(true)); + } + + /** + * Pauses container and ensures that it paused + * + * @param dockerClient docker client + * @param container container + */ + public static void pauseContainer(DockerClient dockerClient, CreateContainerResponse container) { + dockerClient.pauseContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + assertThat(inspectContainerResponse.getState().getPaused(), is(true)); + } + + /** + * Stops container and ensures that it stopped + * + * @param dockerClient docker client + * @param container container + */ + public static void stopContainer(DockerClient dockerClient, CreateContainerResponse container) { + dockerClient.stopContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + assertThat(inspectContainerResponse.getState().getRunning(), is(false)); + } + + /** + * Unpauses container and ensures that it unpaused (running) + * + * @param dockerClient docker client + * @param container container + */ + public static void unpaseContainer(DockerClient dockerClient, CreateContainerResponse container) { + dockerClient.unpauseContainerCmd(container.getId()).exec(); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + assertThat(inspectContainerResponse.getState().getPaused(), is(false)); + assertThat(inspectContainerResponse.getState().getRunning(), is(true)); + } +} From d78a1cfb3a1c3a198389c0f86c9d92caa37db8de Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 29 Jul 2016 19:58:13 +0300 Subject: [PATCH 120/780] Add 1.12.0 for tests --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a8cbe29e2..a9e93162a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,8 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.0-0~trusty" + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.0-0~trusty" - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" From 4c663e18bf1685600d4aa032a7517ab3f0f6042f Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 16:57:52 +0300 Subject: [PATCH 121/780] Fix test for different API behaviour. (#642) --- .../github/dockerjava/core/RemoteApiVersion.java | 10 ++++++++++ .../netty/exec/ExecStartCmdExecTest.java | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java index 954ed9971..f40b5b4d5 100644 --- a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java +++ b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java @@ -62,6 +62,16 @@ public class RemoteApiVersion implements Serializable { */ public static final RemoteApiVersion VERSION_1_22 = RemoteApiVersion.create(1, 22); + /** + * @see Docker API 1.22 + */ + public static final RemoteApiVersion VERSION_1_23 = RemoteApiVersion.create(1, 23); + + /** + * @see Docker API 1.22 + */ + public static final RemoteApiVersion VERSION_1_24 = RemoteApiVersion.create(1, 24); + /** * Unknown, docker doesn't reflect reality. I.e. we implemented method, but for javadoc it not clear when it was added. */ diff --git a/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java index e87c56d74..52db7fe44 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java @@ -1,5 +1,8 @@ package com.github.dockerjava.netty.exec; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_22; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_23; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; @@ -12,6 +15,7 @@ import java.security.SecureRandom; import java.util.concurrent.TimeUnit; +import com.github.dockerjava.core.RemoteApiVersion; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -193,7 +197,8 @@ public void execStartNotAttachedStdin() throws Exception { ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) .withAttachStdout(true) .withAttachStdin(false) - .withCmd("/bin/sh").exec(); + .withCmd("/bin/sh") + .exec(); boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId()) .withDetach(false) @@ -201,8 +206,13 @@ public void execStartNotAttachedStdin() throws Exception { .exec(new ExecStartResultCallback(stdout, System.err)) .awaitCompletion(5, TimeUnit.SECONDS); - // with v1.22 of the remote api the server closed the connection when no stdin was attached while exec create, so completed was true - assertFalse(completed, "The process was not finished."); assertEquals(stdout.toString(), ""); + + if (getVersion(dockerClient).isGreaterOrEqual(VERSION_1_23)) { + assertFalse(completed, "The process was not finished."); + } else { + assertTrue(completed, "with v1.22 of the remote api the server closed the connection when no stdin " + + "was attached while exec create, so completed was true"); + } } } From 6195eb888f34293217d463bb205041d51b2602dc Mon Sep 17 00:00:00 2001 From: tjlee Date: Mon, 1 Aug 2016 20:43:25 +0300 Subject: [PATCH 122/780] [tests] use expectedExceptions (#649) --- .../core/command/AuthCmdImplTest.java | 9 ++------- .../core/command/CommitCmdImplTest.java | 10 +++------- .../command/ContainerDiffCmdImplTest.java | 10 +++------- .../CopyArchiveFromContainerCmdImplTest.java | 9 +++------ .../CopyArchiveToContainerCmdImplTest.java | 10 +++------- .../CopyFileFromContainerCmdImplTest.java | 9 +++------ .../command/CreateContainerCmdImplTest.java | 8 ++------ .../command/KillContainerCmdImplTest.java | 8 ++------ .../command/RemoveContainerCmdImplTest.java | 9 +++------ .../core/command/RemoveImageCmdImplTest.java | 8 ++------ .../command/RemoveNetworkCmdImplTest.java | 9 +++------ .../core/command/RemoveVolumeCmdImplTest.java | 9 ++------- .../command/RestartContainerCmdImplTest.java | 9 ++------- .../command/StartContainerCmdImplTest.java | 17 ++++------------- .../command/StopContainerCmdImplTest.java | 8 ++------ .../core/command/TagImageCmdImplTest.java | 10 +++------- .../netty/exec/CommitCmdExecTest.java | 9 +++------ .../netty/exec/ContainerDiffCmdExecTest.java | 9 +++------ .../CopyArchiveFromContainerCmdExecTest.java | 9 +++------ .../CopyArchiveToContainerCmdExecTest.java | 10 +++------- .../CopyFileFromContainerCmdExecTest.java | 9 +++------ .../netty/exec/KillContainerCmdExecTest.java | 8 ++------ .../exec/RemoveContainerCmdExecTest.java | 9 +++------ .../netty/exec/RemoveImageCmdExecTest.java | 8 ++------ .../netty/exec/RemoveNetworkCmdExecTest.java | 9 +++------ .../netty/exec/RemoveVolumeCmdExecTest.java | 9 ++------- .../exec/RestartContainerCmdExecTest.java | 8 ++------ .../netty/exec/StartContainerCmdExecTest.java | 19 +++++-------------- .../netty/exec/StopContainerCmdExecTest.java | 8 ++------ .../netty/exec/TagImageCmdExecTest.java | 10 +++------- 30 files changed, 81 insertions(+), 205 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java index c01c8b8cd..887c99130 100644 --- a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java @@ -45,14 +45,9 @@ public void testAuth() throws Exception { } // Disabled because of 500/InternalServerException - @Test(enabled = false) + @Test(enabled = false, expectedExceptions = UnauthorizedException.class, expectedExceptionsMessageRegExp = "Wrong login/password, please try again") public void testAuthInvalid() throws Exception { - try { - DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); - fail("Expected a UnauthorizedException caused by a bad password."); - } catch (UnauthorizedException e) { - assertEquals(e.getMessage(), "Wrong login/password, please try again\n"); - } + DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java index b8758d332..64e1d7ddf 100644 --- a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java @@ -68,13 +68,9 @@ public void commit() throws DockerException { assertThat(inspectImageResponse.getParent(), equalTo(busyboxImg.getId())); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void commitNonExistingContainer() throws DockerException { - try { - dockerClient.commitCmd("non-existent").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } - } + dockerClient.commitCmd("non-existent").exec(); + } } diff --git a/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java index 62c7b2ec0..e51db21f4 100644 --- a/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java @@ -67,13 +67,9 @@ public void testContainerDiff() throws DockerException { assertThat(testChangeLog, hasField("kind", equalTo(1))); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testContainerDiffWithNonExistingContainer() throws DockerException { - try { - dockerClient.containerDiffCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } - } + dockerClient.containerDiffCmd("non-existing").exec(); + } } diff --git a/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java index 9b30dd891..59c459382 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveFromContainerCmdImplTest.java @@ -70,13 +70,10 @@ public void copyFromContainer() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyFromNonExistingContainer() throws Exception { - try { - dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); } @Test 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 a1006277c..658c1f090 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyArchiveToContainerCmdImplTest.java @@ -83,14 +83,10 @@ private void assertFileCopied(CreateContainerResponse container) throws IOExcept } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyToNonExistingContainer() throws Exception { - try { - dockerClient.copyArchiveToContainerCmd("non-existing").withHostResource("src/test/resources/testReadFile") - .exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyArchiveToContainerCmd("non-existing").withHostResource("src/test/resources/testReadFile").exec(); } @Test 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 3e4e88612..8bd2c44fe 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java @@ -62,12 +62,9 @@ public void copyFromContainer() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyFromNonExistingContainer() throws Exception { - try { - dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index a9c0acb8c..214bb2f4a 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -231,7 +231,7 @@ public void createContainerWithHostname() throws Exception { assertThat(containerLog(container.getId()), containsString("HOSTNAME=docker-java")); } - @Test + @Test(expectedExceptions = ConflictException.class) public void createContainerWithName() throws DockerException { CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE).withName("container") @@ -245,12 +245,8 @@ public void createContainerWithName() throws DockerException { assertThat(inspectContainerResponse.getName(), equalTo("/container")); - try { - dockerClient.createContainerCmd(BUSYBOX_IMAGE).withName("container").withCmd("env").exec(); - fail("Expected ConflictException"); - } catch (ConflictException e) { - } + dockerClient.createContainerCmd(BUSYBOX_IMAGE).withName("container").withCmd("env").exec(); } @Test diff --git a/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java index 3ba85928e..c8589271e 100644 --- a/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java @@ -67,14 +67,10 @@ public void killContainer() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void killNonExistingContainer() throws DockerException { - try { - dockerClient.killContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.killContainerCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java index 87ace71df..26c8e0e19 100644 --- a/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java @@ -68,13 +68,10 @@ public void removeContainer() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingContainer() throws DockerException { - try { - dockerClient.removeContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.removeContainerCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java index 90be81c7f..4427da997 100644 --- a/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java @@ -74,14 +74,10 @@ public void removeImage() throws DockerException, InterruptedException { assertThat(containers, matcher); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingImage() throws DockerException, InterruptedException { - try { - dockerClient.removeImageCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.removeImageCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveNetworkCmdImplTest.java index e1e4e45fe..228e48c4d 100644 --- a/src/test/java/com/github/dockerjava/core/command/RemoveNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RemoveNetworkCmdImplTest.java @@ -64,13 +64,10 @@ public void removeNetwork() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingContainer() throws DockerException { - try { - dockerClient.removeNetworkCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.removeNetworkCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveVolumeCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveVolumeCmdImplTest.java index 249bf8493..9ed690b65 100644 --- a/src/test/java/com/github/dockerjava/core/command/RemoveVolumeCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RemoveVolumeCmdImplTest.java @@ -41,7 +41,7 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeVolume() throws DockerException { String volumeName = "volume1"; @@ -55,11 +55,6 @@ public void removeVolume() throws DockerException { dockerClient.removeVolumeCmd(volumeName).exec(); - try { - dockerClient.inspectVolumeCmd(volumeName).exec(); - fail("Expected NotFoundException"); - } catch (NotFoundException e) { - // just ignore - } + dockerClient.inspectVolumeCmd(volumeName).exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java index 4920ac087..84916f082 100644 --- a/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java @@ -71,14 +71,9 @@ public void restartContainer() throws DockerException { dockerClient.killContainerCmd(container.getId()).exec(); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void restartNonExistingContainer() throws DockerException, InterruptedException { - try { - dockerClient.restartContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.restartContainerCmd("non-existing").exec(); } - } diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java index 2b32e00c5..4bb8f2b99 100644 --- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java @@ -251,7 +251,7 @@ public void startContainerWithRandomPortBindings() throws DockerException { } - @Test + @Test(expectedExceptions = InternalServerErrorException.class) public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp22 = ExposedPort.tcp(22); @@ -268,13 +268,7 @@ public void startContainerWithConflictingPortBindings() throws DockerException { assertThat(container.getId(), not(isEmptyString())); - try { - dockerClient.startContainerCmd(container.getId()).exec(); - fail("expected InternalServerErrorException"); - } catch (InternalServerErrorException e) { - - } - + dockerClient.startContainerCmd(container.getId()).exec(); } @Test @@ -412,13 +406,10 @@ public void startContainer() throws DockerException { } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testStartNonExistingContainer() throws DockerException { - try { + dockerClient.startContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } } /** diff --git a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java index 913ed9474..382e5b29c 100644 --- a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java @@ -76,14 +76,10 @@ public void testStopContainer() throws DockerException { } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testStopNonExistingContainer() throws DockerException { - try { - dockerClient.stopContainerCmd("non-existing").withTimeout(2).exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.stopContainerCmd("non-existing").withTimeout(2).exec(); } } diff --git a/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java index 94d4291d0..3bf033212 100644 --- a/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java @@ -49,15 +49,11 @@ public void tagImage() throws Exception { dockerClient.removeImageCmd("docker-java/busybox:" + tag).exec(); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void tagNonExistingImage() throws Exception { - String tag = "" + RandomUtils.nextInt(Integer.MAX_VALUE); - try { - dockerClient.tagImageCmd("non-existing", "docker-java/busybox", tag).exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + String tag = "" + RandomUtils.nextInt(Integer.MAX_VALUE); + dockerClient.tagImageCmd("non-existing", "docker-java/busybox", tag).exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java index 0186f4233..3d1a66333 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java @@ -68,13 +68,10 @@ public void commit() throws DockerException { assertThat(inspectImageResponse.getParent(), equalTo(busyboxImg.getId())); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void commitNonExistingContainer() throws DockerException { - try { - dockerClient.commitCmd("non-existent").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.commitCmd("non-existent").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/ContainerDiffCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ContainerDiffCmdExecTest.java index 57c4b46a0..c21c426b5 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/ContainerDiffCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/ContainerDiffCmdExecTest.java @@ -68,13 +68,10 @@ public void testContainerDiff() throws DockerException { assertThat(testChangeLog, hasField("kind", equalTo(1))); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testContainerDiffWithNonExistingContainer() throws DockerException { - try { - dockerClient.containerDiffCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.containerDiffCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveFromContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveFromContainerCmdExecTest.java index caec336a2..02b56156d 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveFromContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveFromContainerCmdExecTest.java @@ -70,13 +70,10 @@ public void copyFromContainer() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyFromNonExistingContainer() throws Exception { - try { - dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyArchiveFromContainerCmd("non-existing", "/test").exec(); } @Test diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java index eb43b54de..d75d36ea8 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyArchiveToContainerCmdExecTest.java @@ -84,14 +84,10 @@ private void assertFileCopied(CreateContainerResponse container) throws IOExcept } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyToNonExistingContainer() throws Exception { - try { - dockerClient.copyArchiveToContainerCmd("non-existing").withHostResource("src/test/resources/testReadFile") - .exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyArchiveToContainerCmd("non-existing").withHostResource("src/test/resources/testReadFile").exec(); } @Test diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java index b9682c592..b512cfa69 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java @@ -62,12 +62,9 @@ public void copyFromContainer() throws Exception { assertTrue(responseAsString.length() > 0); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void copyFromNonExistingContainer() throws Exception { - try { - dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException ignored) { - } + + dockerClient.copyFileFromContainerCmd("non-existing", "/test").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/KillContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/KillContainerCmdExecTest.java index 867373e63..d354c8df3 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/KillContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/KillContainerCmdExecTest.java @@ -67,14 +67,10 @@ public void killContainer() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void killNonExistingContainer() throws DockerException { - try { - dockerClient.killContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.killContainerCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RemoveContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RemoveContainerCmdExecTest.java index ffe456c09..1e7abebdb 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RemoveContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RemoveContainerCmdExecTest.java @@ -69,13 +69,10 @@ public void removeContainer() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingContainer() throws DockerException { - try { - dockerClient.removeContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.removeContainerCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RemoveImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RemoveImageCmdExecTest.java index e2f69ac1e..857bec714 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RemoveImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RemoveImageCmdExecTest.java @@ -74,14 +74,10 @@ public void removeImage() throws DockerException, InterruptedException { assertThat(containers, matcher); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingImage() throws DockerException, InterruptedException { - try { - dockerClient.removeImageCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.removeImageCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RemoveNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RemoveNetworkCmdExecTest.java index 9fda49f21..f8e7d26ca 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RemoveNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RemoveNetworkCmdExecTest.java @@ -64,13 +64,10 @@ public void removeNetwork() throws DockerException { } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeNonExistingContainer() throws DockerException { - try { - dockerClient.removeNetworkCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.removeNetworkCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RemoveVolumeCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RemoveVolumeCmdExecTest.java index 59aafde67..d7995861c 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RemoveVolumeCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RemoveVolumeCmdExecTest.java @@ -41,7 +41,7 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void removeVolume() throws DockerException { String volumeName = "volume1"; @@ -55,11 +55,6 @@ public void removeVolume() throws DockerException { dockerClient.removeVolumeCmd(volumeName).exec(); - try { - dockerClient.inspectVolumeCmd(volumeName).exec(); - fail("Expected NotFoundException"); - } catch (NotFoundException e) { - // just ignore - } + dockerClient.inspectVolumeCmd(volumeName).exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/RestartContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/RestartContainerCmdExecTest.java index 3360057a8..3b1ada5c2 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/RestartContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/RestartContainerCmdExecTest.java @@ -71,14 +71,10 @@ public void restartContainer() throws DockerException { dockerClient.killContainerCmd(container.getId()).exec(); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void restartNonExistingContainer() throws DockerException, InterruptedException { - try { - dockerClient.restartContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.restartContainerCmd("non-existing").exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java index f4a36c2b1..eed82fcd9 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/StartContainerCmdExecTest.java @@ -254,7 +254,7 @@ public void startContainerWithRandomPortBindings() throws DockerException { } - @Test + @Test(expectedExceptions = InternalServerErrorException.class) public void startContainerWithConflictingPortBindings() throws DockerException { ExposedPort tcp22 = ExposedPort.tcp(22); @@ -271,13 +271,7 @@ public void startContainerWithConflictingPortBindings() throws DockerException { assertThat(container.getId(), not(isEmptyString())); - try { - dockerClient.startContainerCmd(container.getId()).exec(); - fail("expected InternalServerErrorException"); - } catch (InternalServerErrorException e) { - - } - + dockerClient.startContainerCmd(container.getId()).exec(); } @Test @@ -415,13 +409,10 @@ public void startContainer() throws DockerException { } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testStartNonExistingContainer() throws DockerException { - try { - dockerClient.startContainerCmd("non-existing").exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + + dockerClient.startContainerCmd("non-existing").exec(); } /** diff --git a/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java index b3f545a42..1dca12890 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java @@ -76,14 +76,10 @@ public void testStopContainer() throws DockerException { } } - @Test + @Test(expectedExceptions = NotFoundException.class) public void testStopNonExistingContainer() throws DockerException { - try { - dockerClient.stopContainerCmd("non-existing").withTimeout(2).exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + dockerClient.stopContainerCmd("non-existing").withTimeout(2).exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/TagImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/TagImageCmdExecTest.java index bbab169ef..6c84775ee 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/TagImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/TagImageCmdExecTest.java @@ -49,15 +49,11 @@ public void tagImage() throws Exception { dockerClient.removeImageCmd("docker-java/busybox:" + tag).exec(); } - @Test + @Test(expectedExceptions = NotFoundException.class) public void tagNonExistingImage() throws Exception { - String tag = "" + RandomUtils.nextInt(Integer.MAX_VALUE); - try { - dockerClient.tagImageCmd("non-existing", "docker-java/busybox", tag).exec(); - fail("expected NotFoundException"); - } catch (NotFoundException e) { - } + String tag = "" + RandomUtils.nextInt(Integer.MAX_VALUE); + dockerClient.tagImageCmd("non-existing", "docker-java/busybox", tag).exec(); } } From b1ed66b10c3def348091809d3ecc5234396d8190 Mon Sep 17 00:00:00 2001 From: tejksat Date: Mon, 1 Aug 2016 20:46:47 +0300 Subject: [PATCH 123/780] Fix for #643 (#648) * Fix for #643 .dockerignore rules handling refactored. A rule is translated to a regexp pattern and then a path is checked against it. * Fix for #643 Failing tests on Windows fixed: Windows file separator escaped. --- .../dockerjava/core/GoLangFileMatch.java | 305 +++++++++--------- .../core/dockerfile/Dockerfile.java | 19 +- .../dockerjava/core/GoLangFileMatchTest.java | 22 +- .../DockerfileAddMultipleFilesTest.java | 49 ++- .../.dockerignore | 3 + .../EffectiveDockerignorePatterns/Dockerfile | 3 + .../README-secret.md | 1 + .../EffectiveDockerignorePatterns/README.md | 0 .../.dockerignore | 3 + .../IneffectiveDockerignorePattern/Dockerfile | 3 + .../README-secret.md | 0 .../IneffectiveDockerignorePattern/README.md | 0 .../NestedDirsDockerignore/.dockerignore | 5 + .../NestedDirsDockerignore/Dockerfile | 3 + .../NestedDirsDockerignore/parent/README.md | 0 .../NestedDirsDockerignore/parent/a.txt | 0 .../parent/anotherChild/README-child.md | 0 .../anotherChild/grandChild/README-grand.md | 0 .../parent/anotherChild/grandChild/c.txt | 0 .../NestedDirsDockerignore/parent/child/b.txt | 0 20 files changed, 231 insertions(+), 185 deletions(-) create mode 100644 src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/.dockerignore create mode 100644 src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/Dockerfile create mode 100644 src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README-secret.md create mode 100644 src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README.md create mode 100644 src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/.dockerignore create mode 100644 src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/Dockerfile create mode 100644 src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README-secret.md create mode 100644 src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README.md create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/.dockerignore create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/Dockerfile create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/README.md create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/a.txt create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/README-child.md create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/README-grand.md create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/c.txt create mode 100644 src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/child/b.txt diff --git a/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java b/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java index fa5dba722..09d5e4978 100644 --- a/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java +++ b/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java @@ -6,6 +6,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; @@ -49,6 +50,8 @@ private GoLangFileMatch() { public static final boolean IS_WINDOWS = File.separatorChar == '\\'; + private static final String PATTERN_CHARS_TO_ESCAPE = "\\.[]{}()*+-?^$|"; + public static boolean match(List patterns, File file) { return !match(patterns, file.getPath()).isEmpty(); } @@ -71,196 +74,194 @@ public static List match(List patterns, String name) { } public static boolean match(String pattern, String name) { - Pattern: while (!pattern.isEmpty()) { - ScanResult scanResult = scanChunk(pattern); - pattern = scanResult.pattern; - if (scanResult.star && StringUtils.isEmpty(scanResult.chunk)) { - // Trailing * matches rest of string unless it has a /. - return name.indexOf(File.separatorChar) < 0; - } - // Look for match at current position. - String matchResult = matchChunk(scanResult.chunk, name); + return buildPattern(pattern).matcher(name).matches(); + } - // if we're the last chunk, make sure we've exhausted the name - // otherwise we'll give a false result even if we could still match - // using the star - if (matchResult != null && (matchResult.isEmpty() || !pattern.isEmpty())) { - name = matchResult; - continue; - } - if (scanResult.star) { - for (int i = 0; i < name.length() && name.charAt(i) != File.separatorChar; i++) { - matchResult = matchChunk(scanResult.chunk, name.substring(i + 1)); - if (matchResult != null) { - // if we're the last chunk, make sure we exhausted the name - if (pattern.isEmpty() && !matchResult.isEmpty()) { - continue; - } - name = matchResult; - continue Pattern; - } - } + private static Pattern buildPattern(String pattern) { + StringBuilder patternStringBuilder = new StringBuilder("^"); + while (!pattern.isEmpty()) { + pattern = appendChunkPattern(patternStringBuilder, pattern); + + if (!pattern.isEmpty()) { + patternStringBuilder.append(quote(File.separatorChar)); } - return false; } - return name.isEmpty(); + patternStringBuilder.append("(").append(quote(File.separatorChar)).append(".*").append(")?"); + return Pattern.compile(patternStringBuilder.toString()); } - static ScanResult scanChunk(String pattern) { - boolean star = false; - if (!pattern.isEmpty() && pattern.charAt(0) == '*') { - pattern = pattern.substring(1); - star = true; + private static String quote(char separatorChar) { + if (StringUtils.contains(PATTERN_CHARS_TO_ESCAPE, separatorChar)) { + return "\\" + separatorChar; + } else { + return String.valueOf(separatorChar); } + } + + private static String appendChunkPattern(StringBuilder patternStringBuilder, String pattern) { + if (pattern.equals("**") || pattern.startsWith("**" + File.separator)) { + patternStringBuilder.append("(") + .append("[^").append(quote(File.separatorChar)).append("]*") + .append("(") + .append(quote(File.separatorChar)).append("[^").append(quote(File.separatorChar)).append("]*") + .append(")*").append(")?"); + return pattern.substring(pattern.length() == 2 ? 2 : 3); + } + boolean inRange = false; + int rangeFrom = 0; + RangeParseState rangeParseState = RangeParseState.CHAR_EXPECTED; + boolean isEsc = false; int i; - Scan: for (i = 0; i < pattern.length(); i++) { - switch (pattern.charAt(i)) { - case '\\': { - if (!IS_WINDOWS && i + 1 < pattern.length()) { - i++; + for (i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + switch (c) { + case '/': + if (!inRange) { + if (!IS_WINDOWS && !isEsc) { + // end of chunk + return pattern.substring(i + 1); + } else { + patternStringBuilder.append(quote(c)); + } + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } + isEsc = false; break; - } - case '[': - inRange = true; - break; - case ']': - inRange = false; - break; - case '*': + case '\\': if (!inRange) { - break Scan; + if (!IS_WINDOWS) { + if (isEsc) { + patternStringBuilder.append(quote(c)); + isEsc = false; + } else { + isEsc = true; + } + } else { + // end of chunk + return pattern.substring(i + 1); + } + } else { + if (IS_WINDOWS || isEsc) { + rangeParseState = nextStateAfterChar(rangeParseState); + isEsc = false; + } else { + isEsc = true; + } } - } - } - return new ScanResult(star, pattern.substring(0, i), pattern.substring(i)); - } - - static String matchChunk(String chunk, String s) { - int chunkLength = chunk.length(); - int chunkOffset = 0; - int sLength = s.length(); - int sOffset = 0; - char r; - while (chunkOffset < chunkLength) { - if (sOffset == sLength) { - return null; - } - switch (chunk.charAt(chunkOffset)) { + break; case '[': - r = s.charAt(sOffset); - sOffset++; - chunkOffset++; - // We can't end right after '[', we're expecting at least - // a closing bracket and possibly a caret. - if (chunkOffset == chunkLength) { - throw new GoLangFileMatchException(); - } - // possibly negated - boolean negated = chunk.charAt(chunkOffset) == '^'; - if (negated) { - chunkOffset++; + if (!isEsc) { + if (inRange) { + //"[ is not expected, ] had not reached" + throw new GoLangFileMatchException(); + } + rangeFrom = i; + rangeParseState = RangeParseState.CHAR_EXPECTED; + inRange = true; + } else { + if (!inRange) { + patternStringBuilder.append(c); + } else { + rangeParseState = nextStateAfterChar(rangeParseState); + } } - // parse all ranges - boolean match = false; - int nrange = 0; - while (true) { - if (chunkOffset < chunkLength && chunk.charAt(chunkOffset) == ']' && nrange > 0) { - chunkOffset++; - break; + isEsc = false; + break; + case ']': + if (!isEsc) { + if (!inRange) { + //"] is not expected, [ was not met" + throw new GoLangFileMatchException(); } - GetEscResult result = getEsc(chunk, chunkOffset, chunkLength); - char lo = result.lo; - char hi = lo; - chunkOffset = result.chunkOffset; - if (chunk.charAt(chunkOffset) == '-') { - result = getEsc(chunk, ++chunkOffset, chunkLength); - chunkOffset = result.chunkOffset; - hi = result.lo; + if (rangeParseState == RangeParseState.CHAR_EXPECTED_AFTER_DASH) { + // character range not finished + throw new GoLangFileMatchException(); } - if (lo <= r && r <= hi) { - match = true; + patternStringBuilder.append(pattern.substring(rangeFrom, i + 1)); + inRange = false; + } else { + if (!inRange) { + patternStringBuilder.append(c); + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } - nrange++; } - if (match == negated) { - return null; + isEsc = false; + break; + case '*': + if (!inRange) { + if (!isEsc) { + patternStringBuilder.append("[^").append(quote(File.separatorChar)).append("]*"); + } else { + patternStringBuilder.append(quote(c)); + } + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } + isEsc = false; break; - case '?': - if (s.charAt(sOffset) == File.separatorChar) { - return null; + if (!inRange) { + if (!isEsc) { + patternStringBuilder.append("[^").append(quote(File.separatorChar)).append("]"); + } else { + patternStringBuilder.append(quote(c)); + } + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } - sOffset++; - chunkOffset++; + isEsc = false; break; - case '\\': - if (!IS_WINDOWS) { - chunkOffset++; - if (chunkOffset == chunkLength) { - throw new GoLangFileMatchException(); + case '-': + if (!inRange) { + patternStringBuilder.append(quote(c)); + } else { + if (!isEsc) { + if (rangeParseState != RangeParseState.CHAR_OR_DASH_EXPECTED) { + // - not expected + throw new GoLangFileMatchException(); + } + rangeParseState = RangeParseState.CHAR_EXPECTED_AFTER_DASH; + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } } - // fallthrough + isEsc = false; + break; default: - if (chunk.charAt(chunkOffset) != s.charAt(sOffset)) { - return null; + if (!inRange) { + patternStringBuilder.append(quote(c)); + } else { + rangeParseState = nextStateAfterChar(rangeParseState); } - sOffset++; - chunkOffset++; + isEsc = false; } } - return s.substring(sOffset); - } - - static GetEscResult getEsc(String chunk, int chunkOffset, int chunkLength) { - if (chunkOffset == chunkLength) { + if (isEsc) { + // "Escaped character missing" throw new GoLangFileMatchException(); } - char r = chunk.charAt(chunkOffset); - if (r == '-' || r == ']') { + if (inRange) { + // "Character range not finished" throw new GoLangFileMatchException(); } - if (r == '\\' && !IS_WINDOWS) { - chunkOffset++; - if (chunkOffset == chunkLength) { - throw new GoLangFileMatchException(); - } - - } - r = chunk.charAt(chunkOffset); - chunkOffset++; - if (chunkOffset == chunkLength) { - throw new GoLangFileMatchException(); - } - return new GetEscResult(r, chunkOffset); + return ""; } - private static final class ScanResult { - public boolean star; - - public String chunk; - - public String pattern; - - ScanResult(boolean star, String chunk, String pattern) { - this.star = star; - this.chunk = chunk; - this.pattern = pattern; + private static RangeParseState nextStateAfterChar(RangeParseState currentState) { + if (currentState == RangeParseState.CHAR_EXPECTED_AFTER_DASH) { + return RangeParseState.CHAR_EXPECTED; + } else { + return RangeParseState.CHAR_OR_DASH_EXPECTED; } } - private static final class GetEscResult { - public char lo; - - public int chunkOffset; - - GetEscResult(char lo, int chunkOffset) { - this.lo = lo; - this.chunkOffset = chunkOffset; - } + private enum RangeParseState { + CHAR_EXPECTED, + CHAR_OR_DASH_EXPECTED, + CHAR_EXPECTED_AFTER_DASH } } diff --git a/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java b/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java index c970d6c2d..9dcd20199 100644 --- a/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java +++ b/src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java @@ -204,9 +204,10 @@ private List matchingIgnorePatterns(String fileName) { int lineNumber = 0; for (String pattern : ignores) { + String goLangPattern = pattern.startsWith("!") ? pattern.substring(1) : pattern; lineNumber++; try { - if (GoLangFileMatch.match(pattern, fileName)) { + if (GoLangFileMatch.match(goLangPattern, fileName)) { matches.add(pattern); } } catch (GoLangFileMatchException e) { @@ -233,21 +234,7 @@ private String effectiveMatchingIgnorePattern(File file) { String lastMatchingPattern = matchingPattern.get(matchingPattern.size() - 1); - int lastMatchingPatternIndex = ignores.lastIndexOf(lastMatchingPattern); - - if (lastMatchingPatternIndex == ignores.size() - 1) { - return lastMatchingPattern; - } - - List remainingIgnorePattern = ignores.subList(lastMatchingPatternIndex + 1, ignores.size()); - - for (String ignorePattern : remainingIgnorePattern) { - if (ignorePattern.equals("!" + relativeFilename)) { - return null; - } - } - - return lastMatchingPattern; + return !lastMatchingPattern.startsWith("!") ? lastMatchingPattern : null; } } } diff --git a/src/test/java/com/github/dockerjava/core/GoLangFileMatchTest.java b/src/test/java/com/github/dockerjava/core/GoLangFileMatchTest.java index 0fd870194..62b342595 100644 --- a/src/test/java/com/github/dockerjava/core/GoLangFileMatchTest.java +++ b/src/test/java/com/github/dockerjava/core/GoLangFileMatchTest.java @@ -5,13 +5,14 @@ import java.io.IOException; -import com.github.dockerjava.core.exception.GoLangFileMatchException; -import junit.framework.Assert; - import org.apache.commons.io.FilenameUtils; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import com.github.dockerjava.core.exception.GoLangFileMatchException; + +import junit.framework.Assert; + public class GoLangFileMatchTest { @Test(dataProvider = "getTestData") @@ -31,7 +32,7 @@ public void testMatch(MatchTestCase testCase) throws IOException { if (testCase.expectException) { Assert.fail("Expected GoFileMatchException"); } - Assert.assertEquals(testCase.matches, matched); + Assert.assertEquals(testCase.toString(), testCase.matches, matched); } catch (GoLangFileMatchException e) { if (!testCase.expectException) { throw e; @@ -41,12 +42,13 @@ public void testMatch(MatchTestCase testCase) throws IOException { @DataProvider public Object[][] getTestData() { - return new Object[][] {new Object[] {new MatchTestCase("abc", "abc", true, false)}, + return new Object[][] {new Object[] {new MatchTestCase("", "abc", false, false)}, + new Object[] {new MatchTestCase("abc", "abc", true, false)}, new Object[] {new MatchTestCase("*", "abc", true, false)}, new Object[] {new MatchTestCase("*c", "abc", true, false)}, new Object[] {new MatchTestCase("a*", "a", true, false)}, new Object[] {new MatchTestCase("a*", "abc", true, false)}, - new Object[] {new MatchTestCase("a*", "ab/c", false, false)}, + new Object[] {new MatchTestCase("a*", "ab/c", true, false)}, new Object[] {new MatchTestCase("a*/b", "abc/b", true, false)}, new Object[] {new MatchTestCase("a*/b", "a/c/b", false, false)}, new Object[] {new MatchTestCase("a*b*c*d*e*/f", "axbxcxdxe/f", true, false)}, @@ -92,9 +94,13 @@ public Object[][] getTestData() { new Object[] {new MatchTestCase("[", "a", false, true)}, new Object[] {new MatchTestCase("[^", "a", false, true)}, new Object[] {new MatchTestCase("[^bc", "a", false, true)}, - new Object[] {new MatchTestCase("a[", "a", false, false)}, + new Object[] {new MatchTestCase("a[", "a", false, true)}, new Object[] {new MatchTestCase("a[", "ab", false, true)}, - new Object[] {new MatchTestCase("*x", "xxx", true, false)}}; + new Object[] {new MatchTestCase("*x", "xxx", true, false)}, + new Object[] {new MatchTestCase("a", "a/b/c", true, false)}, + new Object[] {new MatchTestCase("*/b", "a/b/c", true, false)}, + new Object[] {new MatchTestCase("**/b/*/d", "a/b/c/d", true, false)}, + new Object[] {new MatchTestCase("**/c", "a/b/c", true, false)}}; } private final class MatchTestCase { diff --git a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java index 164246957..b37754a6a 100644 --- a/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java +++ b/src/test/java/com/github/dockerjava/core/dockerfile/DockerfileAddMultipleFilesTest.java @@ -1,20 +1,20 @@ package com.github.dockerjava.core.dockerfile; -import com.google.common.base.Function; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.Test; +import static com.google.common.collect.Collections2.transform; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; import java.io.File; import java.io.IOException; import java.util.Collection; -import static com.google.common.collect.Collections2.transform; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; -public class DockerfileAddMultipleFilesTest { +import com.google.common.base.Function; + +public class DockerfileAddMultipleFilesTest { private static final Logger log = LoggerFactory.getLogger(DockerfileAddMultipleFilesTest.class); @@ -25,6 +25,37 @@ public String apply(File file) { } }; + @Test + public void nestedDirsPatterns() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/NestedDirsDockerignore"); + Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile"), baseDir); + Dockerfile.ScannedResult result = dockerfile.parse(); + Collection filesToAdd = transform(result.filesToAdd, TO_FILE_NAMES); + + assertThat(filesToAdd, + containsInAnyOrder("Dockerfile", ".dockerignore", "README.md", "README-grand.md", "b.txt")); + } + + @Test + public void effectiveIgnorePatterns() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/EffectiveDockerignorePatterns"); + Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile"), baseDir); + Dockerfile.ScannedResult result = dockerfile.parse(); + Collection filesToAdd = transform(result.filesToAdd, TO_FILE_NAMES); + + assertThat(filesToAdd, containsInAnyOrder("Dockerfile", ".dockerignore", "README.md")); + } + + @Test + public void ineffectiveIgnorePattern() throws Exception { + File baseDir = fileFromBuildTestResource("dockerignore/IneffectiveDockerignorePattern"); + Dockerfile dockerfile = new Dockerfile(new File(baseDir, "Dockerfile"), baseDir); + Dockerfile.ScannedResult result = dockerfile.parse(); + Collection filesToAdd = transform(result.filesToAdd, TO_FILE_NAMES); + + assertThat(filesToAdd, containsInAnyOrder("Dockerfile", ".dockerignore", "README.md", "README-secret.md")); + } + @Test public void addFiles() throws IOException { File baseDir = fileFromBuildTestResource("ADD/files"); diff --git a/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/.dockerignore b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/.dockerignore new file mode 100644 index 000000000..f22e777b8 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/.dockerignore @@ -0,0 +1,3 @@ +*.md +!README*.md +README-secret.md \ No newline at end of file diff --git a/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/Dockerfile b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/Dockerfile new file mode 100644 index 000000000..65fa210c7 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:latest + +CMD ["echo", "Success"] diff --git a/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README-secret.md b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README-secret.md new file mode 100644 index 000000000..64237b5a7 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README-secret.md @@ -0,0 +1 @@ +No markdown files are included in the context except README files other than README-secret.md. \ No newline at end of file diff --git a/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README.md b/src/test/resources/buildTests/dockerignore/EffectiveDockerignorePatterns/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/.dockerignore b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/.dockerignore new file mode 100644 index 000000000..f1a1f3799 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/.dockerignore @@ -0,0 +1,3 @@ +*.md +README-secret.md +!README*.md diff --git a/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/Dockerfile b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/Dockerfile new file mode 100644 index 000000000..65fa210c7 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:latest + +CMD ["echo", "Success"] diff --git a/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README-secret.md b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README-secret.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README.md b/src/test/resources/buildTests/dockerignore/IneffectiveDockerignorePattern/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/.dockerignore b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/.dockerignore new file mode 100644 index 000000000..d32df2a06 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/.dockerignore @@ -0,0 +1,5 @@ +**/*.txt +parent/*/grandChild/README*.md +parent/anotherChild/README*.md +!parent/anotherChild/*/*.md +!parent/child \ No newline at end of file diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/Dockerfile b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/Dockerfile new file mode 100644 index 000000000..65fa210c7 --- /dev/null +++ b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:latest + +CMD ["echo", "Success"] diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/README.md b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/a.txt b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/a.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/README-child.md b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/README-child.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/README-grand.md b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/README-grand.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/c.txt b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/anotherChild/grandChild/c.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/child/b.txt b/src/test/resources/buildTests/dockerignore/NestedDirsDockerignore/parent/child/b.txt new file mode 100644 index 000000000..e69de29bb From 5cf12cfbeec2b38f96915563e725d6e659fc025c Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 20:50:45 +0300 Subject: [PATCH 124/780] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d28a9319..c8bf1d3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Change Log --- All changes +* Updated all dependencies +* [#643] (https://github.com/docker-java/docker-java/pull/643) Fixes for .dockerignore filtering * [#627] (https://github.com/docker-java/docker-java/pull/627) Implementation of POST /images/load endpoint * [#630] (https://github.com/docker-java/docker-java/pull/630) Fix: Second execution of a docker command in Netty implementation always fails * [#596] (https://github.com/docker-java/docker-java/pull/596) Refactor configuration of SSL to allow override with custom config From 1221eddda9a382734eb5bd25967a079fb2d20794 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:02:31 +0300 Subject: [PATCH 125/780] Relax checkstyle --- src/test/resources/checkstyle/checkstyle-config.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/resources/checkstyle/checkstyle-config.xml b/src/test/resources/checkstyle/checkstyle-config.xml index 33508c723..76671ded3 100644 --- a/src/test/resources/checkstyle/checkstyle-config.xml +++ b/src/test/resources/checkstyle/checkstyle-config.xml @@ -92,7 +92,9 @@ - + + + From 6d8476e494280e122e4f2ef9b043d5870d28286f Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:03:43 +0300 Subject: [PATCH 126/780] Document debug case (#641) * Document debug case --- docs/devel.adoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/devel.adoc b/docs/devel.adoc index 50c6a7279..2305b89d0 100644 --- a/docs/devel.adoc +++ b/docs/devel.adoc @@ -23,3 +23,11 @@ * Integration tests for commands. * If model object has builders, then fill it with data and compare by `equals()` with expected response from docker daemon. If failed, then some fields mappings are wrong. + +### Debug + * When there are unreproducible Travis errors: + ** Try locally run test 10-20 times in IDE against the same docker daemon version and same connection type (tcp or socket). + ** Limit `.travis.yml` to single run (to not consume their resources with matrix run). + ** Remove `travis-logback.xml` replacement (build can't output everything in every run because travis has log limitation). + ** Set single test in `pom.xml` `for maven-failsafe-plugin` + ** Make PR or if you are maintainer push to branch, catch log and fix. From 227ca791733c73f2f7a413a1997c692931b37f85 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:20:34 +0300 Subject: [PATCH 127/780] Disable java8 doc lint --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 1d4328f9b..39695185b 100644 --- a/pom.xml +++ b/pom.xml @@ -352,6 +352,9 @@ jar + + -Xdoclint:none + From 0d9c3c3a70050557a9989e49f5fc1c777a08d625 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:25:48 +0300 Subject: [PATCH 128/780] [maven-release-plugin] prepare release 3.0.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 39695185b..337dae2ed 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.1-SNAPSHOT + 3.0.1 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.1 From 4bd03a7e6162e2ef72c5365df1ea6d57f246688f Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:25:56 +0300 Subject: [PATCH 129/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 337dae2ed..d8db16134 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.1 + 3.0.2-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.1 + HEAD From fa3310dd02466b211c6d8256198b98533a1edb8a Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 1 Aug 2016 23:46:54 +0300 Subject: [PATCH 130/780] Update for release --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 159108dd8..1ec338523 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ Developer forum for [docker-java](https://groups.google.com/forum/?#!forum/docke ###### Prerequisites: -* Java 1.7 -* Maven 3.0.5 +* Java min 1.7 +* Maven 3 Build and run integration tests as follows: @@ -47,26 +47,26 @@ For secure tls (https) communication: DOCKER_HOST=tcp://127.0.0.1:2376 DOCKER_TLS_VERIFY=1 - DOCKER_CERT_PATH=/Users/marcus/.docker/machine/machines/docker-1.10.2 + DOCKER_CERT_PATH=/Users/marcus/.docker/machine/machines/docker-1.11.2 ### Latest release version -Supports a subset of the Docker Remote API [v1.22](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.22.md), Docker Server version 1.10.x +Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.23.md), Docker Server version 1.11.x com.github.docker-java docker-java - 3.0.0 + 3.0.1 ### Latest development version -Supports a subset of the Docker Remote API [v1.22](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.22.md), Docker Server version 1.10.x +Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.23.md), Docker Server version 1.11.x You can find the latest development version including javadoc and source files on [Sonatypes OSS repository](https://oss.sonatype.org/content/groups/public/com/github/docker-java/docker-java/). com.github.docker-java docker-java - 3.0.1-SNAPSHOT + 3.0.2-SNAPSHOT @@ -82,7 +82,7 @@ There are a couple of configuration items, all of which have sensible defaults: * `DOCKER_TLS_VERIFY` enable/disable TLS verification (switch between `http` and `https` protocol) * `DOCKER_CERT_PATH` Path to the certificates needed for TLS verification * `DOCKER_CONFIG` Path for additional docker configuration files (like `.dockercfg`) -* `api.version` The API version, e.g. `1.21`. +* `api.version` The API version, e.g. `1.23`. * `registry.url` Your registry's address. * `registry.username` Your registry username (required to push containers). * `registry.password` Your registry password. @@ -98,7 +98,7 @@ In your application, e.g. .withDockerTlsVerify(true) .withDockerCertPath("/home/user/.docker/certs") .withDockerConfig("/home/user/.docker") - .withApiVersion("1.21") + .withApiVersion("1.23") .withRegistryUrl("https://index.docker.io/v1/") .withRegistryUsername("dockeruser") .withRegistryPassword("ilovedocker") @@ -112,7 +112,7 @@ In your application, e.g. DOCKER_TLS_VERIFY=1 DOCKER_CERT_PATH=/home/user/.docker/certs DOCKER_CONFIG=/home/user/.docker - api.version=1.21 + api.version=1.23 registry.url=https://index.docker.io/v1/ registry.username=dockeruser registry.password=ilovedocker From c2e4f2c54fdd136ee9c800a38bce4c160b7d5582 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 2 Aug 2016 01:36:09 +0300 Subject: [PATCH 131/780] Include integration tests (#652) --- pom.xml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d8db16134..2e0523feb 100644 --- a/pom.xml +++ b/pom.xml @@ -508,13 +508,28 @@ prepare-agent + - report + post-unit-test test report + + + pre-integration-test + pre-integration-test + + prepare-agent-integration + + + + report-integration + + report-integration + + From da6b013dbc169caafad565fe244356981887d27b Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Tue, 2 Aug 2016 15:37:58 +0300 Subject: [PATCH 132/780] Fix checkstyle of GoLangFileMatch --- .../dockerjava/core/GoLangFileMatch.java | 18 ++++++------------ .../exception/GoLangFileMatchException.java | 3 +++ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java b/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java index 09d5e4978..b26b7db44 100644 --- a/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java +++ b/src/main/java/com/github/dockerjava/core/GoLangFileMatch.java @@ -154,8 +154,7 @@ private static String appendChunkPattern(StringBuilder patternStringBuilder, Str case '[': if (!isEsc) { if (inRange) { - //"[ is not expected, ] had not reached" - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("[ not expected, closing bracket ] not yet reached"); } rangeFrom = i; rangeParseState = RangeParseState.CHAR_EXPECTED; @@ -172,12 +171,10 @@ private static String appendChunkPattern(StringBuilder patternStringBuilder, Str case ']': if (!isEsc) { if (!inRange) { - //"] is not expected, [ was not met" - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("] is not expected, [ was not met"); } if (rangeParseState == RangeParseState.CHAR_EXPECTED_AFTER_DASH) { - // character range not finished - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("Character range not finished"); } patternStringBuilder.append(pattern.substring(rangeFrom, i + 1)); inRange = false; @@ -220,8 +217,7 @@ private static String appendChunkPattern(StringBuilder patternStringBuilder, Str } else { if (!isEsc) { if (rangeParseState != RangeParseState.CHAR_OR_DASH_EXPECTED) { - // - not expected - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("- character not expected"); } rangeParseState = RangeParseState.CHAR_EXPECTED_AFTER_DASH; } else { @@ -240,12 +236,10 @@ private static String appendChunkPattern(StringBuilder patternStringBuilder, Str } } if (isEsc) { - // "Escaped character missing" - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("Escaped character missing"); } if (inRange) { - // "Character range not finished" - throw new GoLangFileMatchException(); + throw new GoLangFileMatchException("Character range not finished"); } return ""; } diff --git a/src/main/java/com/github/dockerjava/core/exception/GoLangFileMatchException.java b/src/main/java/com/github/dockerjava/core/exception/GoLangFileMatchException.java index 3bbdc2a72..2d92389e7 100644 --- a/src/main/java/com/github/dockerjava/core/exception/GoLangFileMatchException.java +++ b/src/main/java/com/github/dockerjava/core/exception/GoLangFileMatchException.java @@ -7,4 +7,7 @@ public class GoLangFileMatchException extends IllegalArgumentException { private static final long serialVersionUID = -1204971075600864898L; + public GoLangFileMatchException(String s) { + super(s); + } } From b87e0d668a2dfd233fd4178cd6f4a1ae3ec6b9cf Mon Sep 17 00:00:00 2001 From: monksy Date: Tue, 2 Aug 2016 14:29:08 -0500 Subject: [PATCH 133/780] Fixed a bad implimentation reference DockerClientConfig is an interface and does not have a method called: DockerClientConfig.createDefaultConfigBuilder(). --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ec338523..feddb82a2 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ There are three ways to configure, in descending order of precedence: #### Programmatic: In your application, e.g. - DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder() + DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder() .withDockerHost("tcp://my-docker-host.tld:2376") .withDockerTlsVerify(true) .withDockerCertPath("/home/user/.docker/certs") From fd421d800e735efe3e860999e564f54d45219bcd Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 3 Aug 2016 03:13:53 +0300 Subject: [PATCH 134/780] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index feddb82a2..da474ff85 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.github.docker-java/docker-java.svg?maxAge=2592000)]() +[![Maven Central](https://img.shields.io/maven-central/v/com.github.docker-java/docker-java.svg)]() +[![Bintray](https://api.bintray.com/packages/kostyasha/maven/com.github.docker-java%3Adocker-java/images/download.svg)](https://bintray.com/kostyasha/maven/com.github.docker-java%3Adocker-java/_latestVersion) [![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) [![Build Status](https://travis-ci.org/docker-java/docker-java.svg?branch=master)](https://travis-ci.org/docker-java/docker-java) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9177/badge.svg?flat=1)](https://scan.coverity.com/projects/9177) From f355e6e756589804cd683e0da279435066a2dc61 Mon Sep 17 00:00:00 2001 From: Pavel Eremeev Date: Thu, 11 Aug 2016 01:31:06 +0300 Subject: [PATCH 135/780] Ability to set container shm size (#659) * Added setShmSize option to 'create container' command * Changed shmSize type to Long * Exposed hostConfig --- .../api/command/CreateContainerCmd.java | 6 ++++++ .../dockerjava/api/model/HostConfig.java | 6 +++--- .../core/command/CreateContainerCmdImpl.java | 11 +++++++++++ .../command/CreateContainerCmdImplTest.java | 18 ++++++++++++++++++ .../netty/exec/CreateContainerCmdExecTest.java | 18 ++++++++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java index 196763560..77bf100ac 100644 --- a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java @@ -6,6 +6,7 @@ import com.github.dockerjava.api.model.Capability; import com.github.dockerjava.api.model.Device; import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.LogConfig; import com.github.dockerjava.api.model.LxcConf; @@ -187,6 +188,9 @@ public interface CreateContainerCmd extends SyncDockerCmd securityOpts) { /** * @see #shmSize */ - public HostConfig withShmSize(String shmSize) { + public HostConfig withShmSize(Long shmSize) { this.shmSize = shmSize; return this; } diff --git a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java index 0b6944b04..f3cfefa05 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java @@ -472,6 +472,11 @@ public String getPidMode() { return hostConfig.getPidMode(); } + @Override + public HostConfig getHostConfig() { + return hostConfig; + } + @Override public String getCgroupParent() { return hostConfig.getCgroupParent(); @@ -976,6 +981,12 @@ public CreateContainerCmd withPidMode(String pidMode) { return this; } + @Override + public CreateContainerCmd withHostConfig(HostConfig hostConfig) { + this.hostConfig = hostConfig; + return this; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 214bb2f4a..7babafc91 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -10,6 +10,7 @@ import com.github.dockerjava.api.model.Device; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.Frame; +import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.LogConfig; import com.github.dockerjava.api.model.Network; @@ -21,6 +22,7 @@ import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; +import org.apache.commons.io.FileUtils; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -735,4 +737,20 @@ public void createContainerWithCgroupParent() throws DockerException { assertThat(inspectContainer.getHostConfig().getCgroupParent(), is("/parent")); } + + @SuppressWarnings("Duplicates") + @Test + public void createContainerWithShmSize() throws DockerException { + HostConfig hostConfig = new HostConfig().withShmSize(96 * FileUtils.ONE_MB); + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withHostConfig(hostConfig).withCmd("true").exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + assertEquals(inspectContainerResponse.getHostConfig().getShmSize(), hostConfig.getShmSize()); + } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index ec35f930a..2213ca7b7 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -9,6 +9,7 @@ import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.Device; import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.LogConfig; import com.github.dockerjava.api.model.Network; @@ -20,6 +21,7 @@ import com.github.dockerjava.api.model.VolumesFrom; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +import org.apache.commons.io.FileUtils; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -676,4 +678,20 @@ public void createContainerWithCgroupParent() throws DockerException { assertThat(inspectContainer.getHostConfig().getCgroupParent(), is("/parent")); } + + @SuppressWarnings("Duplicates") + @Test + public void createContainerWithShmSize() throws DockerException { + HostConfig hostConfig = new HostConfig().withShmSize(96 * FileUtils.ONE_MB); + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withHostConfig(hostConfig).withCmd("true").exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + assertEquals(inspectContainerResponse.getHostConfig().getShmSize(), hostConfig.getShmSize()); + } } From 5893681e3969507afa4915ccab5636ee6c18f5b0 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 11 Aug 2016 11:25:29 +0300 Subject: [PATCH 136/780] [maven-release-plugin] prepare release 3.0.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2e0523feb..0dfef8ca9 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.2-SNAPSHOT + 3.0.2 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.2 From 701aa0b25bf2c0ad0f3ec0096e287b1c6660a0c5 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 11 Aug 2016 11:25:35 +0300 Subject: [PATCH 137/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0dfef8ca9..208d52705 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.2 + 3.0.3-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.2 + HEAD From ee76c14d3b9340a3e1c0ed83d530a58afe424aa4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 11 Aug 2016 11:38:33 +0300 Subject: [PATCH 138/780] Update CHANGELOG.md --- CHANGELOG.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8bf1d3c5..132f3c6b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,15 @@ Change Log === -3.0.1-SNAPSHOT ---- +## 3.0.3-SNAPSHOT + + +## 3.0.2 + * Enhanced Dockerignore filtering. + * Added shmsize for hostconfig. + * Exposed HostConfig instead of spaghetty calls. + +## 3.0.1 All changes * Updated all dependencies From e8f82e829befe25e6f45a4f8363c09a4af776a46 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 16:36:33 +0300 Subject: [PATCH 139/780] Update .travis.yml (#654) --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9e93162a..ba8c62ad0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,12 +21,12 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.0-0~trusty" - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.0-0~trusty" + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.0-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.0-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true # - repo="testing" DOCKER_HOST="tcp://127.0.0.1:2375" # - repo="testing" DOCKER_HOST="unix:///var/run/docker.sock" # - repo="experimental" DOCKER_HOST="tcp://127.0.0.1:2375" From 7af8f8f4eacb13bd4de09dfaf14b8dffc63d733c Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 17:06:05 +0300 Subject: [PATCH 140/780] Fix body request for jersey. --- .../github/dockerjava/jaxrs/StartContainerCmdExec.java | 10 +++++----- .../dockerjava/netty/exec/StartContainerCmdExec.java | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java index 0f75c4f2f..2851a26c7 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java @@ -1,7 +1,5 @@ package com.github.dockerjava.jaxrs; -import static javax.ws.rs.client.Entity.entity; - import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; @@ -22,11 +20,13 @@ public StartContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerCl @Override protected Void execute(StartContainerCmd command) { - WebTarget webResource = getBaseResource().path("/containers/{id}/start").resolveTemplate("id", - command.getContainerId()); + WebTarget webResource = getBaseResource().path("/containers/{id}/start") + .resolveTemplate("id", command.getContainerId()); LOGGER.trace("POST: {}", webResource); - webResource.request().accept(MediaType.APPLICATION_JSON).post(entity(command, MediaType.APPLICATION_JSON)) + webResource.request() + .accept(MediaType.APPLICATION_JSON) + .post(null) .close(); return null; diff --git a/src/main/java/com/github/dockerjava/netty/exec/StartContainerCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/StartContainerCmdExec.java index 12f2d8cbc..039006f2d 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/StartContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/StartContainerCmdExec.java @@ -23,7 +23,9 @@ protected Void execute(StartContainerCmd command) { command.getContainerId()); LOGGER.trace("POST: {}", webResource); - webResource.request().accept(MediaType.APPLICATION_JSON).post(command); + webResource.request() + .accept(MediaType.APPLICATION_JSON) + .post(command); return null; } From 8a3108fbb5cd844fff8e7eaef4bf509fe8299227 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 17:29:57 +0300 Subject: [PATCH 141/780] Fix integration tests --- .../get-docker-com.sh | 2 +- .travis/travis-before-install.sh | 53 +++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) rename get-docker-com.sh => .travis/get-docker-com.sh (99%) diff --git a/get-docker-com.sh b/.travis/get-docker-com.sh similarity index 99% rename from get-docker-com.sh rename to .travis/get-docker-com.sh index 66ca4aefc..d9c0142a2 100755 --- a/get-docker-com.sh +++ b/.travis/get-docker-com.sh @@ -310,4 +310,4 @@ do_install() { # wrapped up in a function so that we have some protection against only getting # half the file during "curl | sh" -do_install \ No newline at end of file +do_install diff --git a/.travis/travis-before-install.sh b/.travis/travis-before-install.sh index 13034fc74..6935f7a7d 100755 --- a/.travis/travis-before-install.sh +++ b/.travis/travis-before-install.sh @@ -3,6 +3,7 @@ sudo apt-get install -y -q ca-certificates +export HOST_PORT=2375 echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt @@ -21,7 +22,10 @@ sudo -E apt-get install -q -y wget sudo -E apt-get -q -y --purge remove docker-engine sudo -E apt-cache policy docker-engine -./get-docker-com.sh +./.travis/get-docker-com.sh + +sudo -E stop docker + #mkdir "${HOME}/.cache" || : #pushd "${HOME}/.cache" # wget -N "https://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_${DOCKER_VERSION}_amd64.deb" @@ -31,10 +35,49 @@ sudo -E apt-cache policy docker-engine #rm -f "src/test/resources/logback.xml" mv "src/test/resources/travis-logback.xml" "src/test/resources/logback.xml" -echo 'DOCKER_OPTS="-H=unix:///var/run/docker.sock -H=tcp://127.0.0.1:2375"' | sudo tee -a /etc/default/docker -sudo -E restart docker -sleep 10 -docker version +# https://github.com/docker/docker/issues/18113 +sudo rm /var/lib/docker/network/files/local-kv.db + +sudo cat /etc/default/docker + +cat << EOF | sudo tee /etc/default/docker +DOCKER_OPTS="\ +--dns 8.8.8.8 \ +--dns 8.8.4.4 \ +-D \ +-H=unix:///var/run/docker.sock \ +-H=tcp://0.0.0.0:${HOST_PORT} \ +" +EOF + +sudo cat /etc/default/docker +sudo bash -c ':> /var/log/upstart/docker.log' + +date +sudo -E start docker + +tries=20 +sleep=5 +for i in $(seq 1 $tries); do + if sudo grep "API listen on" /var/log/upstart/docker.log ; then + echo "Docker started. Delay $(($i * $sleep))" + break + elif [[ $i -ge $tries ]]; then + echo "Docker didn't start. Exiting!" + sudo cat /var/log/upstart/docker.log + exit 1 + else + echo "Docker didn't start, sleeping for 5 secs..." + sleep $sleep + fi +done + + +sudo ss -antpl + +curl -V + +docker version || sudo cat /var/log/upstart/docker.log docker info set +u From 699080417ae678d77da5b46ef39a36810d620329 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 21:30:49 +0300 Subject: [PATCH 142/780] Fix network test. --- .../command/ConnectToNetworkCmdImplTest.java | 40 ++++++++++++------ .../exec/ConnectToNetworkCmdExecTest.java | 41 +++++++++++++------ 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java index 84bb59a81..207d2a0d5 100644 --- a/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/ConnectToNetworkCmdImplTest.java @@ -3,6 +3,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.CreateNetworkResponse; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.Network; import com.github.dockerjava.client.AbstractDockerClientTest; @@ -16,6 +17,10 @@ import java.lang.reflect.Method; import java.util.Collections; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + @Test(groups = "integration") public class ConnectToNetworkCmdImplTest extends AbstractDockerClientTest { @@ -60,38 +65,49 @@ public void connectToNetwork() throws InterruptedException { @Test public void connectToNetworkWithContainerNetwork() throws InterruptedException { + final String NETWORK_SUBNET = "10.100.102.0/24"; + final String NETWORK_NAME = "jerseyTestNetwork"; + final String CONTAINER_IP = "10.100.102.100"; + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("sleep", "9999") + .exec(); - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); dockerClient.startContainerCmd(container.getId()).exec(); + try { + dockerClient.removeNetworkCmd(NETWORK_NAME).exec(); + } catch (DockerException ignore) { + } + CreateNetworkResponse network = dockerClient.createNetworkCmd() - .withName("testNetwork") + .withName(NETWORK_NAME) .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("10.100.100.0/24"))) + .withConfig(new Network.Ipam.Config() + .withSubnet(NETWORK_SUBNET))) .exec(); dockerClient.connectToNetworkCmd() .withNetworkId(network.getId()) .withContainerId(container.getId()) .withContainerNetwork(new ContainerNetwork() - .withAliases("testing") - .withIpamConfig(new ContainerNetwork.Ipam() - .withIpv4Address("10.100.100.100"))) + .withAliases("aliasName") + .withIpamConfig(new ContainerNetwork.Ipam() + .withIpv4Address(CONTAINER_IP))) .exec(); Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); Network.ContainerNetworkConfig containerNetworkConfig = updatedNetwork.getContainers().get(container.getId()); assertNotNull(containerNetworkConfig); - assertEquals(containerNetworkConfig.getIpv4Address(), "10.100.100.100/24"); + assertThat(containerNetworkConfig.getIpv4Address(), is(CONTAINER_IP + "/24")); InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork"); + ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get(NETWORK_NAME); assertNotNull(testNetwork); - assertEquals(testNetwork.getAliases(), Collections.singletonList("testing")); - assertEquals(testNetwork.getGateway(), "10.100.100.1"); - assertEquals(testNetwork.getIpAddress(), "10.100.100.100"); + assertThat(testNetwork.getAliases(), hasItem("aliasName")); + assertEquals(testNetwork.getGateway(), "10.100.102.1"); + assertEquals(testNetwork.getIpAddress(), CONTAINER_IP); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java index ee1a681b6..7e290a98e 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/ConnectToNetworkCmdExecTest.java @@ -3,6 +3,8 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.CreateNetworkResponse; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.exception.DockerException; +import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.Network; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; @@ -17,6 +19,10 @@ import java.lang.reflect.Method; import java.util.Collections; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + @Test(groups = "integration") public class ConnectToNetworkCmdExecTest extends AbstractNettyDockerClientTest { @@ -61,38 +67,49 @@ public void connectToNetwork() throws InterruptedException { @Test public void connectToNetworkWithContainerNetwork() throws InterruptedException { + final String NETWORK_SUBNET = "10.100.101.0/24"; + final String NETWORK_NAME = "nettyTestNetwork"; + final String CONTAINER_IP = "10.100.101.100"; + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox") + .withCmd("sleep", "9999") + .exec(); - CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999").exec(); dockerClient.startContainerCmd(container.getId()).exec(); + try { + dockerClient.removeNetworkCmd(NETWORK_NAME).exec(); + } catch (DockerException ignore) { + } + CreateNetworkResponse network = dockerClient.createNetworkCmd() - .withName("testNetwork") + .withName(NETWORK_NAME) .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("10.100.100.0/24"))) + .withConfig(new Network.Ipam.Config() + .withSubnet(NETWORK_SUBNET))) .exec(); dockerClient.connectToNetworkCmd() .withNetworkId(network.getId()) .withContainerId(container.getId()) .withContainerNetwork(new ContainerNetwork() - .withAliases("testing") - .withIpamConfig(new ContainerNetwork.Ipam() - .withIpv4Address("10.100.100.100"))) + .withAliases("aliasName") + .withIpamConfig(new ContainerNetwork.Ipam() + .withIpv4Address(CONTAINER_IP))) .exec(); Network updatedNetwork = dockerClient.inspectNetworkCmd().withNetworkId(network.getId()).exec(); Network.ContainerNetworkConfig containerNetworkConfig = updatedNetwork.getContainers().get(container.getId()); assertNotNull(containerNetworkConfig); - assertEquals(containerNetworkConfig.getIpv4Address(), "10.100.100.100/24"); + assertThat(containerNetworkConfig.getIpv4Address(), is(CONTAINER_IP + "/24")); InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get("testNetwork"); + ContainerNetwork testNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get(NETWORK_NAME); assertNotNull(testNetwork); - assertEquals(testNetwork.getAliases(), Collections.singletonList("testing")); - assertEquals(testNetwork.getGateway(), "10.100.100.1"); - assertEquals(testNetwork.getIpAddress(), "10.100.100.100"); + assertThat(testNetwork.getAliases(), hasItem("aliasName")); + assertEquals(testNetwork.getGateway(), "10.100.101.1"); + assertEquals(testNetwork.getIpAddress(), CONTAINER_IP); } } From a68cf85da7918886c669e7ddc92e6c246046a4ea Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 21:33:15 +0300 Subject: [PATCH 143/780] Fix create with alias tests. --- .../dockerjava/core/command/CreateContainerCmdImplTest.java | 2 +- .../dockerjava/netty/exec/CreateContainerCmdExecTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 7babafc91..1f62527e9 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -375,7 +375,7 @@ public void createContainerWithAlias() throws DockerException { .exec(); ContainerNetwork aliasNet = inspectContainerResponse.getNetworkSettings().getNetworks().get("aliasNet"); - assertEquals(aliasNet.getAliases(), Collections.singletonList("server")); + assertThat(aliasNet.getAliases(), hasItem("server")); } @Test diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index 2213ca7b7..3694ca7fb 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -370,7 +370,7 @@ public void createContainerWithAlias() throws DockerException { .exec(); ContainerNetwork aliasNet = inspectContainerResponse.getNetworkSettings().getNetworks().get("aliasNet"); - assertEquals(aliasNet.getAliases(), Collections.singletonList("server")); + assertThat(aliasNet.getAliases(), hasItem("server")); } @Test From af891e25521d6b09f0213f458be256933caded06 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 21:38:58 +0300 Subject: [PATCH 144/780] Fix test for 1.24 --- src/main/java/com/github/dockerjava/api/DockerClient.java | 1 + .../core/command/CopyFileFromContainerCmdImplTest.java | 8 ++++++++ .../netty/exec/CopyFileFromContainerCmdExecTest.java | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 491c11ac8..832890e87 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -170,6 +170,7 @@ public interface DockerClient extends Closeable { * @return created command * @see #copyArchiveFromContainerCmd(String, String) * @deprecated since docker API version 1.20, replaced by {@link #copyArchiveFromContainerCmd(String, String)} + * since 1.24 fails. */ @Deprecated CopyFileFromContainerCmd copyFileFromContainerCmd(@Nonnull String containerId, @Nonnull String resource); 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 8bd2c44fe..ec66287eb 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.core.command; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; @@ -7,7 +8,10 @@ import java.io.InputStream; import java.lang.reflect.Method; +import com.github.dockerjava.core.RemoteApiVersion; +import com.github.dockerjava.utils.TestUtils; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -43,6 +47,10 @@ public void afterMethod(ITestResult result) { @Test public void copyFromContainer() throws Exception { + if (getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_24)) { + throw new SkipException("Doesn't work since 1.24"); + } + // TODO extract this into a shared method CreateContainerResponse container = dockerClient.createContainerCmd("busybox") .withName("docker-java-itest-copyFromContainer").withCmd("touch", "/copyFromContainer").exec(); diff --git a/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java index b512cfa69..1060ae82a 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CopyFileFromContainerCmdExecTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.netty.exec; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; @@ -7,7 +8,9 @@ import java.io.InputStream; import java.lang.reflect.Method; +import com.github.dockerjava.core.RemoteApiVersion; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -43,6 +46,10 @@ public void afterMethod(ITestResult result) { @Test public void copyFromContainer() throws Exception { + if (getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_24)) { + throw new SkipException("Doesn't work since 1.24"); + } + // TODO extract this into a shared method CreateContainerResponse container = dockerClient.createContainerCmd("busybox") .withName("docker-java-itest-copyFromContainer").withCmd("touch", "/copyFromContainer").exec(); From 78a2a007303f93211fca4398198f977cf4bba173 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 14 Aug 2016 21:39:09 +0300 Subject: [PATCH 145/780] Fix typo --- .../com/github/dockerjava/core/command/UnpauseCmdImplTest.java | 2 +- .../com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java | 2 +- src/test/java/com/github/dockerjava/utils/ContainerUtils.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java index f640c4182..2f41b67ae 100644 --- a/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/UnpauseCmdImplTest.java @@ -56,7 +56,7 @@ public void unpausePausedContainer() { ContainerUtils.pauseContainer(dockerClient, container); - ContainerUtils.unpaseContainer(dockerClient, container); + ContainerUtils.unpauseContainer(dockerClient, container); } @Test(expectedExceptions = InternalServerErrorException.class) diff --git a/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java b/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java index db91bc9f9..cb30babc4 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/UnpauseCmdImplTest.java @@ -56,7 +56,7 @@ public void unpausePausedContainer() { ContainerUtils.pauseContainer(dockerClient, container); - ContainerUtils.unpaseContainer(dockerClient, container); + ContainerUtils.unpauseContainer(dockerClient, container); } @Test(expectedExceptions = InternalServerErrorException.class) diff --git a/src/test/java/com/github/dockerjava/utils/ContainerUtils.java b/src/test/java/com/github/dockerjava/utils/ContainerUtils.java index 75be6c4d9..206be0693 100644 --- a/src/test/java/com/github/dockerjava/utils/ContainerUtils.java +++ b/src/test/java/com/github/dockerjava/utils/ContainerUtils.java @@ -60,7 +60,7 @@ public static void stopContainer(DockerClient dockerClient, CreateContainerRespo * @param dockerClient docker client * @param container container */ - public static void unpaseContainer(DockerClient dockerClient, CreateContainerResponse container) { + public static void unpauseContainer(DockerClient dockerClient, CreateContainerResponse container) { dockerClient.unpauseContainerCmd(container.getId()).exec(); InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); From a520aaa56b0e8cb05dc7a84da7b04377418c2f55 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 00:35:48 +0300 Subject: [PATCH 146/780] Fix test again? --- .../dockerjava/netty/exec/AttachContainerCmdExecTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index 7daa59b25..d3e8094cf 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -93,7 +93,7 @@ public void attachContainerWithStdin() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - Thread.sleep(SECONDS.toMillis(3)); //wait bash initialisation + Thread.sleep(SECONDS.toMillis(10)); //wait bash initialisation InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); From 03b1c72caced14037d3531a636508d48a16e874f Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 13:58:19 +0300 Subject: [PATCH 147/780] Update CHANGELOG.md --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 132f3c6b1..64bea7c57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ Change Log === +## Next -## 3.0.3-SNAPSHOT - +## 3.0.3 + * [JERSEY] Don't send body for start container request. ## 3.0.2 * Enhanced Dockerignore filtering. From ec124aeee4edf771204dd1d8d7c680df65502610 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 14:05:51 +0300 Subject: [PATCH 148/780] [maven-release-plugin] prepare release 3.0.3 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 208d52705..4327d0b60 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.3-SNAPSHOT + 3.0.3 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.3 From 76bfdc9f4da0a280310212a53ae959b6e66834a4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 14:05:57 +0300 Subject: [PATCH 149/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4327d0b60..586d2a209 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.3 + 3.0.4-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.3 + HEAD From 03b8bb0ceaa45f044ef8ded07a3edf194fd8cd68 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 14:41:19 +0300 Subject: [PATCH 150/780] Don't fail build because of coverity --- .travis/travis-script.sh | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/.travis/travis-script.sh b/.travis/travis-script.sh index aeae555ef..1cdc84fa5 100755 --- a/.travis/travis-script.sh +++ b/.travis/travis-script.sh @@ -1,12 +1,34 @@ #!/usr/bin/env bash -set -ex + IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"` +export COVERITY_ALLOWED=true +# Verify upload is permitted +AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted` +if [ "$AUTH_RES" = "Access denied" ]; then + echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" + COVERITY_ALLOWED=false +else + AUTH=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']"` + if [ "$AUTH" = "true" ]; then + echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" + else + WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"` + echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m" + + COVERITY_ALLOWED=false + fi +fi + +set -ex if [ "${FAST_BUILD}" == "true" ]; then - if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && + [ "$COVERITY" == "true" ] && + [ "$IS_COVERITY_SCAN_BRANCH" = "1" ] && + [ "$COVERITY_ALLOWED" == "true" ]; then export COVERITY_SCAN_BUILD_COMMAND="mvn package" #curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash ./.travis/travisci_build_coverity_scan.sh @@ -14,7 +36,10 @@ if [ "${FAST_BUILD}" == "true" ]; then mvn package fi else - if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$COVERITY" == "true" ] && [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && + [ "$COVERITY" == "true" ] && + [ "$IS_COVERITY_SCAN_BRANCH" = "1" ] && + [ "$COVERITY_ALLOWED" == "true" ]; then export COVERITY_SCAN_BUILD_COMMAND="mvn verify" #curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash ./.travis/travisci_build_coverity_scan.sh From 26c0e277de537edfe623ea6ec531a08c5fbb296e Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 14:48:52 +0300 Subject: [PATCH 151/780] Adjust developers --- pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pom.xml b/pom.xml index 586d2a209..a14a31e5f 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,16 @@ + + marcuslinke + Marcus Linke + marcus.linke@gmx.de + + + kostyasha + Kanstantsin Shautsou + kanstantsin.sha@gmail.com + kpelykh Konstantin Pelykh From f2826175e86239c85a327c10ae98c181a8f6e762 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 15:17:23 +0300 Subject: [PATCH 152/780] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da474ff85..e65215648 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/doc com.github.docker-java docker-java - 3.0.1 + 3.0.3 ### Latest development version @@ -67,7 +67,7 @@ You can find the latest development version including javadoc and source files o com.github.docker-java docker-java - 3.0.2-SNAPSHOT + 3.0.4-SNAPSHOT From b93d0636ef0e3c24966753c79273b19aba601d97 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 19:59:42 +0300 Subject: [PATCH 153/780] Don't hide utils --- .../github/dockerjava/core/util/CertificateUtils.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java index c760331d6..b5a5dcae6 100644 --- a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java +++ b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java @@ -72,7 +72,7 @@ public static KeyStore createKeyStore(final String keypem, final String certpem) /** * from "cert.pem" String */ - private static List loadCertificates(final String certpem) throws IOException, + public static List loadCertificates(final String certpem) throws IOException, CertificateException { final StringReader certReader = new StringReader(certpem); try (BufferedReader reader = new BufferedReader(certReader)) { @@ -83,7 +83,7 @@ private static List loadCertificates(final String certpem) throws I /** * "cert.pem" from reader */ - private static List loadCertificates(final Reader reader) throws IOException, + public static List loadCertificates(final Reader reader) throws IOException, CertificateException { try (PEMParser pemParser = new PEMParser(reader)) { List certificates = new ArrayList<>(); @@ -105,7 +105,7 @@ private static List loadCertificates(final Reader reader) throws IO * Return private key ("key.pem") from Reader */ @CheckForNull - private static PrivateKey loadPrivateKey(final Reader reader) throws IOException, NoSuchAlgorithmException, + public static PrivateKey loadPrivateKey(final Reader reader) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { try (PEMParser pemParser = new PEMParser(reader)) { Object readObject = pemParser.readObject(); @@ -138,7 +138,7 @@ private static PrivateKey loadPrivateKey(final Reader reader) throws IOException } @CheckForNull - private static PrivateKey guessKey(byte[] encodedKey) throws NoSuchAlgorithmException { + public static PrivateKey guessKey(byte[] encodedKey) throws NoSuchAlgorithmException { //no way to know, so iterate for (String guessFactory : new String[]{"RSA", "ECDSA"}) { try { @@ -157,7 +157,7 @@ private static PrivateKey guessKey(byte[] encodedKey) throws NoSuchAlgorithmExce * Return KeyPair from "key.pem" */ @CheckForNull - private static PrivateKey loadPrivateKey(final String keypem) throws IOException, NoSuchAlgorithmException, + public static PrivateKey loadPrivateKey(final String keypem) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { try (StringReader certReader = new StringReader(keypem); BufferedReader reader = new BufferedReader(certReader)) { From 203fa3903b76c0e539cb7de702dded78039853d9 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 20:51:40 +0300 Subject: [PATCH 154/780] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64bea7c57..1011a4815 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Change Log === ## Next +## 3.0.4 + * Make cert util methods public. + ## 3.0.3 * [JERSEY] Don't send body for start container request. From d2b511f45e14791887e1861044ca6d3cc4b44ff4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 20:57:23 +0300 Subject: [PATCH 155/780] [maven-release-plugin] prepare release 3.0.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a14a31e5f..854782b2c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.4-SNAPSHOT + 3.0.4 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.4 From f751dc25cc9fc38c9e643a068e793d32f54c1664 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 15 Aug 2016 20:57:31 +0300 Subject: [PATCH 156/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 854782b2c..6d1ccca18 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.4 + 3.0.5-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.4 + HEAD From 36d17ca42b9fd706b864ac3d11380bd8c4ccbac6 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 16 Aug 2016 22:07:15 +0300 Subject: [PATCH 157/780] Update devel.adoc https://github.com/jenkinsci/credentials-plugin/blob/master/CONTRIBUTING.md --- docs/devel.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/devel.adoc b/docs/devel.adoc index 2305b89d0..1b6295662 100644 --- a/docs/devel.adoc +++ b/docs/devel.adoc @@ -13,6 +13,7 @@ ** Provide full information on field: *** For models define API version with `@since {@link RemoteApiVersion#VERSION_1_X}`. ** getters/setters should refernce to field `@see #$field`. + * If it is `Serializable` it shall have a `serialVersionUID` field. Unless code has shipped to users, the initial value of the `serialVersionUID` field shall be `1L`. ### Coding style * TBD, some initial styling already enforced with checkstyle. From e95f78621d4c3aeb8fad9b79f8b5a1093a8e8547 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 Aug 2016 10:39:14 +0300 Subject: [PATCH 158/780] Update Events to 1.24 model (#669) * added event type in Event class #650 * added missing import for JsonProperty * added CheckForNull * Sync event model to 1.24 Signed-off-by: Kanstantsin Shautsou --- .../github/dockerjava/api/model/Event.java | 184 ++++++++++++++++-- .../dockerjava/api/model/EventActor.java | 77 ++++++++ .../dockerjava/api/model/EventType.java | 55 ++++++ .../dockerjava/api/model/EventsTest.java | 64 ++++++ .../resources/samples/1.24/events/docs1.json | 17 ++ 5 files changed, 384 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/api/model/EventActor.java create mode 100644 src/main/java/com/github/dockerjava/api/model/EventType.java create mode 100644 src/test/java/com/github/dockerjava/api/model/EventsTest.java create mode 100644 src/test/resources/samples/1.24/events/docs1.json diff --git a/src/main/java/com/github/dockerjava/api/model/Event.java b/src/main/java/com/github/dockerjava/api/model/Event.java index 202f5a350..b8024b5ee 100644 --- a/src/main/java/com/github/dockerjava/api/model/Event.java +++ b/src/main/java/com/github/dockerjava/api/model/Event.java @@ -1,10 +1,17 @@ package com.github.dockerjava.api.model; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.CheckForNull; + +import static org.apache.commons.lang.builder.ToStringStyle.SHORT_PREFIX_STYLE; /** * Representation of a Docker event. @@ -12,16 +19,60 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) public class Event { + + /** + * @since 1.16 + */ + @JsonProperty("status") private String status; + /** + * @since 1.16 + */ + @JsonProperty("id") private String id; + /** + * @since 1.16 + */ + @JsonProperty("from") private String from; + /** + * ?? + */ + @JsonProperty("node") + private Node node; + + /* + * @since 1. + */ + @JsonProperty("Type") + private EventType type; + + /** + * @since 1.22 + */ + @JsonProperty("Action") + private String action; + + /** + * @since 1.22 + */ + @JsonProperty("Actor") + private EventActor actor; + + /** + * @since 1.16 + */ + @JsonProperty("time") private Long time; - @JsonIgnoreProperties - private Node node; + /** + * @since 1.21 + */ + @JsonProperty("timeNano") + private Long timeNano; /** * Default constructor for the deserialization. @@ -32,16 +83,12 @@ public Event() { /** * Constructor. * - * @param id - * Container ID - * @param status - * Status string. List of statuses is available in Docker API v.1.16 - * @param from - * Image, from which the container has been created - * @param time - * Event time The time is specified in milliseconds since January 1, 1970, 00:00:00 GMT - * @since TODO + * @param id Container ID + * @param status Status string. List of statuses is available in Docker API v.1.16 + * @param from Image, from which the container has been created + * @param time Event time The time is specified in milliseconds since January 1, 1970, 00:00:00 GMT + * @since 1.16 */ public Event(String status, String id, String from, Long time) { this.status = status; @@ -60,6 +107,14 @@ public String getStatus() { return status; } + /** + * @see #status + */ + public Event withStatus(String status) { + this.status = status; + return this; + } + /** * Get ID of docker container. * @@ -69,6 +124,14 @@ public String getId() { return id; } + /** + * @see #id + */ + public Event withId(String id) { + this.id = id; + return this; + } + /** * Get source image of the container. * @@ -78,6 +141,14 @@ public String getFrom() { return from; } + /** + * @see #from + */ + public Event withFrom(String from) { + this.from = from; + return this; + } + /** * Get the event time. The time is specified in milliseconds since January 1, 1970, 00:00:00 GMT * @@ -87,6 +158,30 @@ public Long getTime() { return time; } + /** + * @see #time + */ + public Event withTime(Long time) { + this.time = time; + return this; + } + + /** + * @see #timeNano + */ + @CheckForNull + public Long getTimeNano() { + return timeNano; + } + + /** + * @see #timeNano + */ + public Event withTimenano(Long timenano) { + this.timeNano = timenano; + return this; + } + /** * Returns the node when working against docker swarm */ @@ -94,8 +189,71 @@ public Node getNode() { return node; } + /** + * @see #node + */ + public Event withNode(Node node) { + this.node = node; + return this; + } + + @CheckForNull + public EventType getType() { + return type; + } + + /** + * @see #type + */ + public Event withType(EventType type) { + this.type = type; + return this; + } + + /** + * @see #action + */ + @CheckForNull + public String getAction() { + return action; + } + + /** + * @see #action + */ + public Event withAction(String action) { + this.action = action; + return this; + } + + /** + * @see #actor + */ + @CheckForNull + public EventActor getActor() { + return actor; + } + + /** + * @see #actor + */ + public Event withEventActor(EventActor actor) { + this.actor = actor; + return this; + } + @Override public String toString() { - return ToStringBuilder.reflectionToString(this); + return ToStringBuilder.reflectionToString(this, SHORT_PREFIX_STYLE); + } + + @Override + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); } } diff --git a/src/main/java/com/github/dockerjava/api/model/EventActor.java b/src/main/java/com/github/dockerjava/api/model/EventActor.java new file mode 100644 index 000000000..f7b0abbf3 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/EventActor.java @@ -0,0 +1,77 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; + +import javax.annotation.CheckForNull; +import java.io.Serializable; +import java.util.Map; + +/** + * @author Kanstantsin Shautsou + * @since 1.22 + */ +public class EventActor implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * @since 1.22 + */ + @JsonProperty("ID") + private String id; + + /** + * @since 1.22 + */ + @JsonProperty("Attributes") + private Map attributes; + + /** + * @see #id + */ + @CheckForNull + public String getId() { + return id; + } + + /** + * @see #id + */ + public EventActor withId(String id) { + this.id = id; + return this; + } + + /** + * @see #attributes + */ + @CheckForNull + public Map getAttributes() { + return attributes; + } + + /** + * @see #attributes + */ + public EventActor withAttributes(Map attributes) { + this.attributes = attributes; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @Override + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/src/main/java/com/github/dockerjava/api/model/EventType.java b/src/main/java/com/github/dockerjava/api/model/EventType.java new file mode 100644 index 000000000..697c1e429 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/EventType.java @@ -0,0 +1,55 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; + +/** + * @since 1.24 + */ +public enum EventType { + /** + * @since 1.24 + */ + CONTAINER("container"), + + /** + * @since 1.24 + */ + DAEMON("daemon"), + + /** + * @since 1.24 + */ + IMAGE("image"), + NETWORK("network"), + PLUGIN("plugin"), + VOLUME("volume"); + + private static final Map EVENT_TYPES = new HashMap<>(); + + static { + for (EventType t : values()) { + EVENT_TYPES.put(t.name().toLowerCase(), t); + } + } + + private String value; + + EventType(@Nonnull String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @JsonCreator + public static EventType forValue(String s) { + return EVENT_TYPES.get(s); + } +} diff --git a/src/test/java/com/github/dockerjava/api/model/EventsTest.java b/src/test/java/com/github/dockerjava/api/model/EventsTest.java new file mode 100644 index 000000000..ce62c7d5f --- /dev/null +++ b/src/test/java/com/github/dockerjava/api/model/EventsTest.java @@ -0,0 +1,64 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.core.RemoteApiVersion; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; + +import static com.github.dockerjava.api.model.EventType.CONTAINER; +import static com.github.dockerjava.test.serdes.JSONSamples.testRoundTrip; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; + +/** + * @author Kanstantsin Shautsou + */ +public class EventsTest { + + @Test + public void serderDocs1() throws IOException { + final ObjectMapper mapper = new ObjectMapper(); + final JavaType type = mapper.getTypeFactory().uncheckedSimpleType(Event.class); + + final Event event = testRoundTrip(RemoteApiVersion.VERSION_1_24, + "/events/docs1.json", + type + ); + + assertThat(event, notNullValue()); + assertThat(event.getType(), is(CONTAINER)); + assertThat(event.getAction(), is("create")); + assertThat(event.getId(), is("ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743")); + assertThat(event.getFrom(), is("alpine")); + assertThat(event.getTime(), is(1461943101L)); + assertThat(event.getNode(), nullValue()); + assertThat(event.getTimeNano(), is(1461943101381709551L)); + + final HashMap attributes = new HashMap<>(); + attributes.put("com.example.some-label", "some-label-value"); + attributes.put("image", "alpine"); + attributes.put("name", "my-container"); + + final EventActor actor = new EventActor() + .withId("ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743") + .withAttributes(attributes); + + final Event event1 = new Event() + .withType(CONTAINER) + .withStatus("create") + .withId("ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743") + .withFrom("alpine") + .withTime(1461943101L) + .withTimenano(1461943101381709551L) + .withAction("create") + .withEventActor(actor); + + assertThat(event1, equalTo(event)); + } +} diff --git a/src/test/resources/samples/1.24/events/docs1.json b/src/test/resources/samples/1.24/events/docs1.json new file mode 100644 index 000000000..f62f2284e --- /dev/null +++ b/src/test/resources/samples/1.24/events/docs1.json @@ -0,0 +1,17 @@ +{ + "status": "create", + "id": "ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743", + "from": "alpine", + "Type": "container", + "Action": "create", + "Actor": { + "ID": "ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743", + "Attributes": { + "com.example.some-label": "some-label-value", + "image": "alpine", + "name": "my-container" + } + }, + "time": 1461943101, + "timeNano": 1461943101381709551 +} From bb83b03207cd6a641616f1112a5a5f32d40f2467 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 Aug 2016 12:02:14 +0300 Subject: [PATCH 159/780] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1011a4815..bd6c2d278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Change Log === ## Next +## 3.0.5 + * Events updated to 1.24 API model. + ## 3.0.4 * Make cert util methods public. From af8374f622d442a81ae558fa757c03d879fa2848 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 Aug 2016 13:37:57 +0300 Subject: [PATCH 160/780] [maven-release-plugin] prepare release 3.0.5 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6d1ccca18..00a4561b5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.5-SNAPSHOT + 3.0.5 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.5 From 8c456c2334c656a6ca20cc502440fdf01175f577 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 Aug 2016 13:38:04 +0300 Subject: [PATCH 161/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 00a4561b5..b1b6d96a9 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.5 + 3.0.6-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.5 + HEAD From 96d7ddbea9a442875b33406d81b9ea678c1fb5b1 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 Aug 2016 00:16:21 +0300 Subject: [PATCH 162/780] Make all models serializable --- .../dockerjava/api/model/AuthConfig.java | 4 +- .../api/model/AuthConfigurations.java | 4 +- .../dockerjava/api/model/AuthResponse.java | 6 +- .../com/github/dockerjava/api/model/Bind.java | 5 +- .../github/dockerjava/api/model/Binds.java | 4 +- .../api/model/BuildResponseItem.java | 1 - .../dockerjava/api/model/ChangeLog.java | 5 +- .../dockerjava/api/model/Container.java | 4 +- .../dockerjava/api/model/ContainerConfig.java | 4 +- .../api/model/ContainerHostConfig.java | 6 +- .../api/model/ContainerNetwork.java | 5 +- .../api/model/ContainerNetworkSettings.java | 5 +- .../dockerjava/api/model/ContainerPort.java | 4 +- .../github/dockerjava/api/model/Device.java | 4 +- .../dockerjava/api/model/DriverStatus.java | 7 ++- .../dockerjava/api/model/ErrorDetail.java | 6 +- .../dockerjava/api/model/ErrorResponse.java | 6 +- .../github/dockerjava/api/model/Event.java | 5 +- .../dockerjava/api/model/ExposedPort.java | 4 +- .../dockerjava/api/model/ExposedPorts.java | 4 +- .../github/dockerjava/api/model/Frame.java | 5 +- .../dockerjava/api/model/HostConfig.java | 4 +- .../dockerjava/api/model/Identifier.java | 8 ++- .../github/dockerjava/api/model/Image.java | 5 +- .../com/github/dockerjava/api/model/Info.java | 4 +- .../api/model/InfoRegistryConfig.java | 5 +- .../com/github/dockerjava/api/model/Link.java | 5 +- .../github/dockerjava/api/model/Links.java | 4 +- .../dockerjava/api/model/LogConfig.java | 4 +- .../github/dockerjava/api/model/LxcConf.java | 6 +- .../github/dockerjava/api/model/Network.java | 4 +- .../dockerjava/api/model/NetworkSettings.java | 4 +- .../com/github/dockerjava/api/model/Node.java | 5 +- .../dockerjava/api/model/PortBinding.java | 6 +- .../github/dockerjava/api/model/Ports.java | 4 +- .../dockerjava/api/model/Repository.java | 5 +- .../dockerjava/api/model/ResponseItem.java | 1 - .../dockerjava/api/model/RestartPolicy.java | 5 +- .../dockerjava/api/model/SearchItem.java | 5 +- .../dockerjava/api/model/Statistics.java | 4 +- .../github/dockerjava/api/model/Ulimit.java | 5 +- .../github/dockerjava/api/model/Version.java | 4 +- .../github/dockerjava/api/model/Volume.java | 5 +- .../dockerjava/api/model/VolumeBind.java | 6 +- .../dockerjava/api/model/VolumeBinds.java | 5 +- .../github/dockerjava/api/model/VolumeRW.java | 4 +- .../github/dockerjava/api/model/Volumes.java | 4 +- .../dockerjava/api/model/VolumesFrom.java | 4 +- .../dockerjava/api/model/VolumesRW.java | 5 +- .../dockerjava/api/model/WaitResponse.java | 5 +- .../api/ModelsSerializableTest.java | 63 +++++++++++++++++++ 51 files changed, 244 insertions(+), 52 deletions(-) create mode 100644 src/test/java/com/github/dockerjava/api/ModelsSerializableTest.java diff --git a/src/main/java/com/github/dockerjava/api/model/AuthConfig.java b/src/main/java/com/github/dockerjava/api/model/AuthConfig.java index 849f26a21..074c6db61 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthConfig.java @@ -8,9 +8,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import javax.annotation.CheckForNull; +import java.io.Serializable; @JsonInclude(Include.NON_NULL) -public class AuthConfig { +public class AuthConfig implements Serializable { + private static final long serialVersionUID = 1L; /** * For backwards compatibility. Make sure you update the properties if you change this. diff --git a/src/main/java/com/github/dockerjava/api/model/AuthConfigurations.java b/src/main/java/com/github/dockerjava/api/model/AuthConfigurations.java index e8edbc950..baa8fc0b4 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthConfigurations.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthConfigurations.java @@ -1,11 +1,13 @@ package com.github.dockerjava.api.model; +import java.io.Serializable; import java.util.Map; import java.util.TreeMap; import com.fasterxml.jackson.annotation.JsonProperty; -public class AuthConfigurations { +public class AuthConfigurations implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("configs") private Map configs = new TreeMap<>(); diff --git a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java index cb5d9df80..cd6908185 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java @@ -2,7 +2,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; -public class AuthResponse { +import java.io.Serializable; + +public class AuthResponse implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty("Status") private String status; diff --git a/src/main/java/com/github/dockerjava/api/model/Bind.java b/src/main/java/com/github/dockerjava/api/model/Bind.java index bf02bbad2..0995c87ac 100644 --- a/src/main/java/com/github/dockerjava/api/model/Bind.java +++ b/src/main/java/com/github/dockerjava/api/model/Bind.java @@ -3,11 +3,14 @@ import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; +import java.io.Serializable; + /** * Represents a host path being bind mounted as a {@link Volume} in a Docker container. * The Bind can be in read only or read write access mode. */ -public class Bind { +public class Bind implements Serializable { + private static final long serialVersionUID = 1L; private String path; diff --git a/src/main/java/com/github/dockerjava/api/model/Binds.java b/src/main/java/com/github/dockerjava/api/model/Binds.java index 917cfdcbd..b24c3208d 100644 --- a/src/main/java/com/github/dockerjava/api/model/Binds.java +++ b/src/main/java/com/github/dockerjava/api/model/Binds.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -19,7 +20,8 @@ @JsonSerialize(using = Binds.Serializer.class) @JsonDeserialize(using = Binds.Deserializer.class) -public class Binds { +public class Binds implements Serializable { + private static final long serialVersionUID = 1L; private Bind[] binds; diff --git a/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java index a53a1df9a..7236be23d 100644 --- a/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java +++ b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java @@ -8,7 +8,6 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) public class BuildResponseItem extends ResponseItem { - private static final long serialVersionUID = -1252904184236343612L; private static final String BUILD_SUCCESS = "Successfully built"; diff --git a/src/main/java/com/github/dockerjava/api/model/ChangeLog.java b/src/main/java/com/github/dockerjava/api/model/ChangeLog.java index 36804362c..04b36f5ce 100644 --- a/src/main/java/com/github/dockerjava/api/model/ChangeLog.java +++ b/src/main/java/com/github/dockerjava/api/model/ChangeLog.java @@ -5,13 +5,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) * */ @JsonIgnoreProperties(ignoreUnknown = true) -public class ChangeLog { +public class ChangeLog implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Path") private String path; diff --git a/src/main/java/com/github/dockerjava/api/model/Container.java b/src/main/java/com/github/dockerjava/api/model/Container.java index 47492920d..9e04362ce 100644 --- a/src/main/java/com/github/dockerjava/api/model/Container.java +++ b/src/main/java/com/github/dockerjava/api/model/Container.java @@ -11,6 +11,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.Map; /** @@ -20,7 +21,8 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class Container { +public class Container implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Command") private String command; diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java index 224da3272..191126798 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java @@ -10,6 +10,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.Map; /** @@ -19,7 +20,8 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class ContainerConfig { +public class ContainerConfig implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("AttachStderr") private Boolean attachStderr; diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerHostConfig.java b/src/main/java/com/github/dockerjava/api/model/ContainerHostConfig.java index 43a5a94b1..8d0c3fe37 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerHostConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerHostConfig.java @@ -6,6 +6,8 @@ import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; +import java.io.Serializable; + /** * Used in {@link Container} * @@ -13,7 +15,9 @@ * @author Kanstantsin Shautsou */ @JsonIgnoreProperties(ignoreUnknown = true) -public class ContainerHostConfig { +public class ContainerHostConfig implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty("NetworkMode") private String networkMode; diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java b/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java index 9b2160e98..bc7e12d33 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerNetwork.java @@ -9,6 +9,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.Arrays; import java.util.List; @@ -21,7 +22,9 @@ * @author Kanstantsin Shautsou */ @JsonIgnoreProperties(ignoreUnknown = true) -public class ContainerNetwork { +public class ContainerNetwork implements Serializable { + private static final long serialVersionUID = 1L; + /** * FIXME verify */ diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerNetworkSettings.java b/src/main/java/com/github/dockerjava/api/model/ContainerNetworkSettings.java index 7f4b17be5..bc6165874 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerNetworkSettings.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerNetworkSettings.java @@ -7,6 +7,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; +import java.io.Serializable; import java.util.Map; /** @@ -16,7 +17,9 @@ * @since {@link RemoteApiVersion#VERSION_1_22} */ @JsonIgnoreProperties(ignoreUnknown = true) -public class ContainerNetworkSettings { +public class ContainerNetworkSettings implements Serializable { + private static final long serialVersionUID = 1L; + /** * @since {@link RemoteApiVersion#VERSION_1_22} */ diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerPort.java b/src/main/java/com/github/dockerjava/api/model/ContainerPort.java index 09f718ef6..5924e53df 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerPort.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerPort.java @@ -7,13 +7,15 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; /** * @author Kanstantsin Shautsou * @see Container */ @JsonIgnoreProperties(ignoreUnknown = true) -public class ContainerPort { +public class ContainerPort implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("IP") private String ip; diff --git a/src/main/java/com/github/dockerjava/api/model/Device.java b/src/main/java/com/github/dockerjava/api/model/Device.java index f2b75e3f5..7d73710fd 100644 --- a/src/main/java/com/github/dockerjava/api/model/Device.java +++ b/src/main/java/com/github/dockerjava/api/model/Device.java @@ -12,12 +12,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; import javax.annotation.Nonnull; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; @JsonInclude(Include.NON_NULL) -public class Device { +public class Device implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("CgroupPermissions") private String cGroupPermissions = ""; diff --git a/src/main/java/com/github/dockerjava/api/model/DriverStatus.java b/src/main/java/com/github/dockerjava/api/model/DriverStatus.java index 3e2b5037a..7c1374aae 100644 --- a/src/main/java/com/github/dockerjava/api/model/DriverStatus.java +++ b/src/main/java/com/github/dockerjava/api/model/DriverStatus.java @@ -7,12 +7,15 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** - * Created by ben on 12/12/13. + * @author ben */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class DriverStatus { +public class DriverStatus implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Root Dir") private String rootDir; diff --git a/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java b/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java index 62018a4e0..92e869d2a 100644 --- a/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java +++ b/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java @@ -4,8 +4,12 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + @JsonInclude(Include.NON_NULL) -public class ErrorDetail { +public class ErrorDetail implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty private String message; diff --git a/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java b/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java index 172bd5c79..f6abfc3eb 100644 --- a/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java +++ b/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java @@ -4,8 +4,12 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + @JsonInclude(Include.NON_NULL) -public class ErrorResponse { +public class ErrorResponse implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty private ErrorDetail errorDetail; diff --git a/src/main/java/com/github/dockerjava/api/model/Event.java b/src/main/java/com/github/dockerjava/api/model/Event.java index b8024b5ee..6e4b6f3c2 100644 --- a/src/main/java/com/github/dockerjava/api/model/Event.java +++ b/src/main/java/com/github/dockerjava/api/model/Event.java @@ -13,12 +13,15 @@ import static org.apache.commons.lang.builder.ToStringStyle.SHORT_PREFIX_STYLE; +import java.io.Serializable; + /** * Representation of a Docker event. */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class Event { +public class Event implements Serializable { + private static final long serialVersionUID = 1L; /** * @since 1.16 diff --git a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java index ec95f6273..26d727ff4 100644 --- a/src/main/java/com/github/dockerjava/api/model/ExposedPort.java +++ b/src/main/java/com/github/dockerjava/api/model/ExposedPort.java @@ -4,6 +4,7 @@ import static com.github.dockerjava.api.model.InternetProtocol.UDP; import java.io.IOException; +import java.io.Serializable; import java.util.Map.Entry; import org.apache.commons.lang.builder.EqualsBuilder; @@ -30,7 +31,8 @@ */ @JsonDeserialize(using = ExposedPort.Deserializer.class) @JsonSerialize(using = ExposedPort.Serializer.class) -public class ExposedPort { +public class ExposedPort implements Serializable { + private static final long serialVersionUID = 1L; private final InternetProtocol protocol; diff --git a/src/main/java/com/github/dockerjava/api/model/ExposedPorts.java b/src/main/java/com/github/dockerjava/api/model/ExposedPorts.java index 0ecb879b6..7670212e1 100644 --- a/src/main/java/com/github/dockerjava/api/model/ExposedPorts.java +++ b/src/main/java/com/github/dockerjava/api/model/ExposedPorts.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -21,7 +22,8 @@ @JsonSerialize(using = ExposedPorts.Serializer.class) @JsonDeserialize(using = ExposedPorts.Deserializer.class) -public class ExposedPorts { +public class ExposedPorts implements Serializable { + private static final long serialVersionUID = 1L; private ExposedPort[] exposedPorts; diff --git a/src/main/java/com/github/dockerjava/api/model/Frame.java b/src/main/java/com/github/dockerjava/api/model/Frame.java index 0ad16e8c6..9b1376f82 100644 --- a/src/main/java/com/github/dockerjava/api/model/Frame.java +++ b/src/main/java/com/github/dockerjava/api/model/Frame.java @@ -1,11 +1,14 @@ package com.github.dockerjava.api.model; +import java.io.Serializable; import java.util.Arrays; /** * Represents a logging frame. */ -public class Frame { +public class Frame implements Serializable { + private static final long serialVersionUID = 1L; + private final StreamType streamType; private final byte[] payload; diff --git a/src/main/java/com/github/dockerjava/api/model/HostConfig.java b/src/main/java/com/github/dockerjava/api/model/HostConfig.java index 5dada65cc..062082a03 100644 --- a/src/main/java/com/github/dockerjava/api/model/HostConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/HostConfig.java @@ -11,6 +11,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.Arrays; import java.util.List; @@ -20,7 +21,8 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class HostConfig { +public class HostConfig implements Serializable { + private static final long serialVersionUID = 1L; private static final List PREDEFINED_NETWORKS = Arrays.asList("bridge", "host", "none"); diff --git a/src/main/java/com/github/dockerjava/api/model/Identifier.java b/src/main/java/com/github/dockerjava/api/model/Identifier.java index 1051d857f..8f1c871a7 100644 --- a/src/main/java/com/github/dockerjava/api/model/Identifier.java +++ b/src/main/java/com/github/dockerjava/api/model/Identifier.java @@ -3,10 +3,14 @@ import com.google.common.base.Objects; import com.google.common.base.Optional; +import java.io.Serializable; + /** - * Created by magnayn on 22/07/2014. + * @author magnayn */ -public class Identifier { +public class Identifier implements Serializable { + private static final long serialVersionUID = 1L; + public final Repository repository; public final Optional tag; diff --git a/src/main/java/com/github/dockerjava/api/model/Image.java b/src/main/java/com/github/dockerjava/api/model/Image.java index 496db275e..78fee9f79 100644 --- a/src/main/java/com/github/dockerjava/api/model/Image.java +++ b/src/main/java/com/github/dockerjava/api/model/Image.java @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) @@ -14,7 +16,8 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class Image { +public class Image implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Created") private Long created; diff --git a/src/main/java/com/github/dockerjava/api/model/Info.java b/src/main/java/com/github/dockerjava/api/model/Info.java index 7270eceb8..51abe5dac 100644 --- a/src/main/java/com/github/dockerjava/api/model/Info.java +++ b/src/main/java/com/github/dockerjava/api/model/Info.java @@ -9,6 +9,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.List; import java.util.Map; @@ -19,7 +20,8 @@ */ @JsonInclude(Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) -public class Info { +public class Info implements Serializable { + private static final long serialVersionUID = 1L; /** * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_22} diff --git a/src/main/java/com/github/dockerjava/api/model/InfoRegistryConfig.java b/src/main/java/com/github/dockerjava/api/model/InfoRegistryConfig.java index 956aaebe3..2c2be5cfd 100644 --- a/src/main/java/com/github/dockerjava/api/model/InfoRegistryConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/InfoRegistryConfig.java @@ -7,6 +7,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; import java.util.List; import java.util.Map; @@ -14,7 +15,9 @@ * @since ~{@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_20} */ @JsonIgnoreProperties(ignoreUnknown = true) -public final class InfoRegistryConfig { +public final class InfoRegistryConfig implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty("IndexConfigs") private Map indexConfigs; diff --git a/src/main/java/com/github/dockerjava/api/model/Link.java b/src/main/java/com/github/dockerjava/api/model/Link.java index 89647306c..346aedcb0 100644 --- a/src/main/java/com/github/dockerjava/api/model/Link.java +++ b/src/main/java/com/github/dockerjava/api/model/Link.java @@ -3,12 +3,15 @@ import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; +import java.io.Serializable; + /** * Represents a network link between two Docker containers. The container with the name {@link #getName()} is made available in the target * container with the aliased name {@link #getAlias()}. This involves creating an entry in /etc/hosts and some environment * variables in the target container as well as creating a network bridge between both containers. */ -public class Link { +public class Link implements Serializable { + private static final long serialVersionUID = 1L; private final String name; diff --git a/src/main/java/com/github/dockerjava/api/model/Links.java b/src/main/java/com/github/dockerjava/api/model/Links.java index 2d678b3a3..1eb66ae42 100644 --- a/src/main/java/com/github/dockerjava/api/model/Links.java +++ b/src/main/java/com/github/dockerjava/api/model/Links.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -20,7 +21,8 @@ @JsonSerialize(using = Links.Serializer.class) @JsonDeserialize(using = Links.Deserializer.class) -public class Links { +public class Links implements Serializable { + private static final long serialVersionUID = 1L; private final Link[] links; diff --git a/src/main/java/com/github/dockerjava/api/model/LogConfig.java b/src/main/java/com/github/dockerjava/api/model/LogConfig.java index f4fd0e958..e2a066101 100644 --- a/src/main/java/com/github/dockerjava/api/model/LogConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/LogConfig.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -26,7 +27,8 @@ * docker will ignore them. In most cases setting the config option to null will suffice. Consult the docker remote API for a more detailed * and up-to-date explanation of the available types and their options. */ -public class LogConfig { +public class LogConfig implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Type") public LoggingType type = null; diff --git a/src/main/java/com/github/dockerjava/api/model/LxcConf.java b/src/main/java/com/github/dockerjava/api/model/LxcConf.java index aeb854285..0a60086fb 100644 --- a/src/main/java/com/github/dockerjava/api/model/LxcConf.java +++ b/src/main/java/com/github/dockerjava/api/model/LxcConf.java @@ -4,8 +4,12 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + @JsonInclude(Include.NON_NULL) -public class LxcConf { +public class LxcConf implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty("Key") public String key; diff --git a/src/main/java/com/github/dockerjava/api/model/Network.java b/src/main/java/com/github/dockerjava/api/model/Network.java index 6f4114914..c0f9f36eb 100644 --- a/src/main/java/com/github/dockerjava/api/model/Network.java +++ b/src/main/java/com/github/dockerjava/api/model/Network.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang.builder.ToStringBuilder; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -12,7 +13,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) -public class Network { +public class Network implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Id") private String id; diff --git a/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java b/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java index 1d523bf4b..8fcd8fb9b 100644 --- a/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java +++ b/src/main/java/com/github/dockerjava/api/model/NetworkSettings.java @@ -8,6 +8,7 @@ import com.github.dockerjava.core.RemoteApiVersion; import org.apache.commons.lang.builder.ToStringBuilder; +import java.io.Serializable; import java.util.Map; /** @@ -16,7 +17,8 @@ * */ @JsonIgnoreProperties(ignoreUnknown = true) -public class NetworkSettings { +public class NetworkSettings implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Bridge") private String bridge; diff --git a/src/main/java/com/github/dockerjava/api/model/Node.java b/src/main/java/com/github/dockerjava/api/model/Node.java index 9e8580e0a..89b391c0a 100644 --- a/src/main/java/com/github/dockerjava/api/model/Node.java +++ b/src/main/java/com/github/dockerjava/api/model/Node.java @@ -4,11 +4,14 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * A node as returned by the /events API, for instance, when Swarm is used. */ @JsonInclude(Include.NON_NULL) -public class Node { +public class Node implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Name") private String name; diff --git a/src/main/java/com/github/dockerjava/api/model/PortBinding.java b/src/main/java/com/github/dockerjava/api/model/PortBinding.java index e163272d7..9a30b6cd2 100644 --- a/src/main/java/com/github/dockerjava/api/model/PortBinding.java +++ b/src/main/java/com/github/dockerjava/api/model/PortBinding.java @@ -6,6 +6,8 @@ import com.github.dockerjava.api.model.Ports.Binding; +import java.io.Serializable; + /** * In a {@link PortBinding}, a network socket on the Docker host, expressed as a {@link Binding}, is bound to an {@link ExposedPort} of a * container. A {@link PortBinding} corresponds to the --publish (-p) option of the docker run (and @@ -15,7 +17,9 @@ * existing port bindings from a container configuration in {@link NetworkSettings#getPorts()} and {@link HostConfig#getPortBindings()}. In * that context, a Map<ExposedPort, Binding[]> is used. */ -public class PortBinding { +public class PortBinding implements Serializable { + private static final long serialVersionUID = 1L; + private final Binding binding; private final ExposedPort exposedPort; diff --git a/src/main/java/com/github/dockerjava/api/model/Ports.java b/src/main/java/com/github/dockerjava/api/model/Ports.java index 904a31c4e..673852d9e 100644 --- a/src/main/java/com/github/dockerjava/api/model/Ports.java +++ b/src/main/java/com/github/dockerjava/api/model/Ports.java @@ -16,6 +16,7 @@ import org.apache.commons.lang.builder.EqualsBuilder; import java.io.IOException; +import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -35,7 +36,8 @@ @SuppressWarnings(value = "checkstyle:equalshashcode") @JsonDeserialize(using = Ports.Deserializer.class) @JsonSerialize(using = Ports.Serializer.class) -public class Ports { +public class Ports implements Serializable { + private static final long serialVersionUID = 1L; private final Map ports = new HashMap(); diff --git a/src/main/java/com/github/dockerjava/api/model/Repository.java b/src/main/java/com/github/dockerjava/api/model/Repository.java index 1e814a1b5..f4e4b9ab8 100644 --- a/src/main/java/com/github/dockerjava/api/model/Repository.java +++ b/src/main/java/com/github/dockerjava/api/model/Repository.java @@ -1,5 +1,6 @@ package com.github.dockerjava.api.model; +import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; @@ -8,7 +9,9 @@ /** * A repository or image name. */ -public class Repository { +public class Repository implements Serializable { + private static final long serialVersionUID = 1L; + public final String name; /** diff --git a/src/main/java/com/github/dockerjava/api/model/ResponseItem.java b/src/main/java/com/github/dockerjava/api/model/ResponseItem.java index 12a090db8..6663b4bf0 100644 --- a/src/main/java/com/github/dockerjava/api/model/ResponseItem.java +++ b/src/main/java/com/github/dockerjava/api/model/ResponseItem.java @@ -15,7 +15,6 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) public class ResponseItem implements Serializable { - private static final long serialVersionUID = -5187169652557467828L; @JsonProperty("stream") diff --git a/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java b/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java index ac6c4a318..1f77b8b9d 100644 --- a/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java +++ b/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * Container restart policy * @@ -26,7 +28,8 @@ * @author Marcus Linke * */ -public class RestartPolicy { +public class RestartPolicy implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("MaximumRetryCount") private Integer maximumRetryCount = 0; diff --git a/src/main/java/com/github/dockerjava/api/model/SearchItem.java b/src/main/java/com/github/dockerjava/api/model/SearchItem.java index 0a5843838..4e1663655 100644 --- a/src/main/java/com/github/dockerjava/api/model/SearchItem.java +++ b/src/main/java/com/github/dockerjava/api/model/SearchItem.java @@ -5,13 +5,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) * */ @JsonIgnoreProperties(ignoreUnknown = true) -public class SearchItem { +public class SearchItem implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("star_count") private Integer starCount; diff --git a/src/main/java/com/github/dockerjava/api/model/Statistics.java b/src/main/java/com/github/dockerjava/api/model/Statistics.java index 21b9ca923..cf8c1b77e 100644 --- a/src/main/java/com/github/dockerjava/api/model/Statistics.java +++ b/src/main/java/com/github/dockerjava/api/model/Statistics.java @@ -1,5 +1,6 @@ package com.github.dockerjava.api.model; +import java.io.Serializable; import java.util.Map; import javax.annotation.CheckForNull; @@ -16,7 +17,8 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) -public class Statistics { +public class Statistics implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("read") private String read; diff --git a/src/main/java/com/github/dockerjava/api/model/Ulimit.java b/src/main/java/com/github/dockerjava/api/model/Ulimit.java index 7427fb0cc..abcf298bd 100644 --- a/src/main/java/com/github/dockerjava/api/model/Ulimit.java +++ b/src/main/java/com/github/dockerjava/api/model/Ulimit.java @@ -7,10 +7,13 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * @author Vangie Du (duwan@live.com) */ -public class Ulimit { +public class Ulimit implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("Name") private String name; diff --git a/src/main/java/com/github/dockerjava/api/model/Version.java b/src/main/java/com/github/dockerjava/api/model/Version.java index 004c85f22..f08c411e2 100644 --- a/src/main/java/com/github/dockerjava/api/model/Version.java +++ b/src/main/java/com/github/dockerjava/api/model/Version.java @@ -8,6 +8,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import javax.annotation.CheckForNull; +import java.io.Serializable; /** * Used for `/version` @@ -16,7 +17,8 @@ * @see VersionCmd */ @JsonIgnoreProperties(ignoreUnknown = true) -public class Version { +public class Version implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("ApiVersion") private String apiVersion; diff --git a/src/main/java/com/github/dockerjava/api/model/Volume.java b/src/main/java/com/github/dockerjava/api/model/Volume.java index 655a8dbfc..46989f79c 100644 --- a/src/main/java/com/github/dockerjava/api/model/Volume.java +++ b/src/main/java/com/github/dockerjava/api/model/Volume.java @@ -3,12 +3,15 @@ import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; +import java.io.Serializable; + /** * Represents a bind mounted volume in a Docker container. * * @see Bind */ -public class Volume { +public class Volume implements Serializable { + private static final long serialVersionUID = 1L; private String path; diff --git a/src/main/java/com/github/dockerjava/api/model/VolumeBind.java b/src/main/java/com/github/dockerjava/api/model/VolumeBind.java index cf9c077ab..f78fc587e 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumeBind.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumeBind.java @@ -1,6 +1,10 @@ package com.github.dockerjava.api.model; -public class VolumeBind { +import java.io.Serializable; + +public class VolumeBind implements Serializable { + private static final long serialVersionUID = 1L; + private final String hostPath; private final String containerPath; diff --git a/src/main/java/com/github/dockerjava/api/model/VolumeBinds.java b/src/main/java/com/github/dockerjava/api/model/VolumeBinds.java index d8303ec84..aeef19e9f 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumeBinds.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumeBinds.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -22,7 +23,9 @@ // This is not going to be serialized @JsonDeserialize(using = VolumeBinds.Deserializer.class) @JsonSerialize(using = VolumeBinds.Serializer.class) -public class VolumeBinds { +public class VolumeBinds implements Serializable { + private static final long serialVersionUID = 1L; + private final VolumeBind[] binds; public VolumeBinds(VolumeBind... binds) { diff --git a/src/main/java/com/github/dockerjava/api/model/VolumeRW.java b/src/main/java/com/github/dockerjava/api/model/VolumeRW.java index 7c4bdfb26..229cee3ed 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumeRW.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumeRW.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.Map.Entry; import org.apache.commons.lang.builder.EqualsBuilder; @@ -29,7 +30,8 @@ @JsonDeserialize(using = VolumeRW.Deserializer.class) @JsonSerialize(using = VolumeRW.Serializer.class) @Deprecated -public class VolumeRW { +public class VolumeRW implements Serializable { + private static final long serialVersionUID = 1L; private Volume volume; diff --git a/src/main/java/com/github/dockerjava/api/model/Volumes.java b/src/main/java/com/github/dockerjava/api/model/Volumes.java index 46175548d..3246b0e8e 100644 --- a/src/main/java/com/github/dockerjava/api/model/Volumes.java +++ b/src/main/java/com/github/dockerjava/api/model/Volumes.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -21,7 +22,8 @@ @JsonSerialize(using = Volumes.Serializer.class) @JsonDeserialize(using = Volumes.Deserializer.class) -public class Volumes { +public class Volumes implements Serializable { + private static final long serialVersionUID = 1L; private Volume[] volumes; diff --git a/src/main/java/com/github/dockerjava/api/model/VolumesFrom.java b/src/main/java/com/github/dockerjava/api/model/VolumesFrom.java index f027b6d71..fb52ff3f7 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumesFrom.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumesFrom.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; @@ -19,7 +20,8 @@ @JsonSerialize(using = VolumesFrom.Serializer.class) @JsonDeserialize(using = VolumesFrom.Deserializer.class) -public class VolumesFrom { +public class VolumesFrom implements Serializable { + private static final long serialVersionUID = 1L; private String container; diff --git a/src/main/java/com/github/dockerjava/api/model/VolumesRW.java b/src/main/java/com/github/dockerjava/api/model/VolumesRW.java index f54f8242c..1b12bd13d 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumesRW.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumesRW.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.model; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -22,7 +23,9 @@ // This is not going to be serialized @JsonSerialize(using = VolumesRW.Serializer.class) @JsonDeserialize(using = VolumesRW.Deserializer.class) -public class VolumesRW { +public class VolumesRW implements Serializable { + private static final long serialVersionUID = 1L; + private final VolumeRW[] volumesRW; public VolumesRW(VolumeRW... binds) { diff --git a/src/main/java/com/github/dockerjava/api/model/WaitResponse.java b/src/main/java/com/github/dockerjava/api/model/WaitResponse.java index a2ab16f6f..0cab338b2 100644 --- a/src/main/java/com/github/dockerjava/api/model/WaitResponse.java +++ b/src/main/java/com/github/dockerjava/api/model/WaitResponse.java @@ -3,11 +3,14 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * Represents a wait container command response */ @JsonIgnoreProperties(ignoreUnknown = true) -public class WaitResponse { +public class WaitResponse implements Serializable { + private static final long serialVersionUID = 1L; @JsonProperty("StatusCode") private Integer statusCode; diff --git a/src/test/java/com/github/dockerjava/api/ModelsSerializableTest.java b/src/test/java/com/github/dockerjava/api/ModelsSerializableTest.java new file mode 100644 index 000000000..770b136c9 --- /dev/null +++ b/src/test/java/com/github/dockerjava/api/ModelsSerializableTest.java @@ -0,0 +1,63 @@ +package com.github.dockerjava.api; + +import com.github.dockerjava.api.model.Binds; +import com.github.dockerjava.api.model.BuildResponseItem; +import com.github.dockerjava.api.model.PullResponseItem; +import com.github.dockerjava.api.model.PushResponseItem; +import com.github.dockerjava.api.model.ResponseItem; +import com.google.common.reflect.ClassPath.ClassInfo; +import org.apache.commons.lang.reflect.FieldUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +import static com.google.common.reflect.ClassPath.from; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.object.IsCompatibleType.typeCompatibleWith; +import static org.junit.Assert.assertThat; + +/** + * @author Kanstantsin Shautsou + */ +public class ModelsSerializableTest { + private static final Logger LOG = LoggerFactory.getLogger(ModelsSerializableTest.class); + + private List excludeClasses = Arrays.asList( + Binds.class.getName(), + BuildResponseItem.class.getName(), + PullResponseItem.class.getName(), + PushResponseItem.class.getName(), + ResponseItem.class.getName() + ); + + @Test + public void allModelsSerializable() throws IOException, NoSuchFieldException, IllegalAccessException { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + for (ClassInfo classInfo : from(contextClassLoader).getTopLevelClasses("com.github.dockerjava.api.model")) { + if (classInfo.getName().endsWith("Test")) { + continue; + } + + final Class aClass = classInfo.load(); + if (aClass.getProtectionDomain().getCodeSource().getLocation().getPath().endsWith("test-classes/") + || aClass.isEnum()) { + continue; + } + + LOG.debug("aClass: {}", aClass); + assertThat(aClass, typeCompatibleWith(Serializable.class)); + + final Object serialVersionUID = FieldUtils.readDeclaredStaticField(aClass, "serialVersionUID", true); + if (!excludeClasses.contains(aClass.getName())) { + assertThat(serialVersionUID, instanceOf(Long.class)); + assertThat("Follow devel docs", (Long) serialVersionUID, is(1L)); + } + } + } +} From 0183bd6271d09be07c38bfdda27d473f44f34225 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 19 Aug 2016 00:46:48 +0300 Subject: [PATCH 163/780] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd6c2d278..e2361ea85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Change Log === ## Next +## 3.0.7 + * Make all models Serializable + ## 3.0.5 * Events updated to 1.24 API model. From e7c5f278fcf783023a6a94c422da50aa85c84437 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 19 Aug 2016 00:47:09 +0300 Subject: [PATCH 164/780] Typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2361ea85..8582d4eef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Change Log === ## Next -## 3.0.7 +## 3.0.6 * Make all models Serializable ## 3.0.5 From 75309ffdeed2dcca8e679e6580a308f2e61527aa Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 19 Aug 2016 02:13:36 +0300 Subject: [PATCH 165/780] Add maven-central link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e65215648..039657807 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.github.docker-java/docker-java.svg)]() +[![Maven Central](https://img.shields.io/maven-central/v/com.github.docker-java/docker-java.svg)](https://mvnrepository.com/artifact/com.github.docker-java/docker-java) [![Bintray](https://api.bintray.com/packages/kostyasha/maven/com.github.docker-java%3Adocker-java/images/download.svg)](https://bintray.com/kostyasha/maven/com.github.docker-java%3Adocker-java/_latestVersion) [![Reference Status](https://www.versioneye.com/java/com.github.docker-java:docker-java/reference_badge.svg?style=flat)](https://www.versioneye.com/java/com.github.docker-java:docker-java/references) [![Build Status](https://travis-ci.org/docker-java/docker-java.svg?branch=master)](https://travis-ci.org/docker-java/docker-java) From c8ab23f0609cb2323114f5ce41cdce87627f956e Mon Sep 17 00:00:00 2001 From: tejksat Date: Sun, 28 Aug 2016 18:00:03 +0300 Subject: [PATCH 166/780] Fix for #670 (#680) JSON decoding disabled on /images/load command execution. --- .../dockerjava/netty/InvocationBuilder.java | 31 +++++++++++++++++++ .../netty/exec/LoadImageCmdExec.java | 7 ++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java b/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java index 9669d6818..d76918bcb 100644 --- a/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java +++ b/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java @@ -69,6 +69,12 @@ public void onNext(T object) { } } + public class SkipResultCallback extends ResultCallbackTemplate, Void> { + @Override + public void onNext(Void object) { + } + } + private ChannelProvider channelProvider; private String resource; @@ -401,6 +407,31 @@ public void post(TypeReference typeReference, ResultCallback resultCal channel.pipeline().addLast(new JsonObjectDecoder()); channel.pipeline().addLast(jsonResponseHandler); + postChunkedStreamRequest(requestProvider, channel, body); + } + + public void postStream(InputStream body) { + SkipResultCallback resultCallback = new SkipResultCallback(); + + HttpRequestProvider requestProvider = httpPostRequestProvider(null); + + Channel channel = getChannel(); + + HttpResponseHandler responseHandler = new HttpResponseHandler(requestProvider, resultCallback); + + channel.pipeline().addLast(new ChunkedWriteHandler()); + channel.pipeline().addLast(responseHandler); + + postChunkedStreamRequest(requestProvider, channel, body); + + try { + resultCallback.awaitCompletion(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + private void postChunkedStreamRequest(HttpRequestProvider requestProvider, Channel channel, InputStream body) { HttpRequest request = requestProvider.getHttpRequest(resource); // don't accept FullHttpRequest here diff --git a/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java index 23581119f..30ee716a5 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/LoadImageCmdExec.java @@ -3,7 +3,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.core.type.TypeReference; import com.github.dockerjava.api.command.LoadImageCmd; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.netty.WebTarget; @@ -22,8 +21,8 @@ protected Void execute(LoadImageCmd command) { WebTarget webResource = getBaseResource().path("/images/load"); LOGGER.trace("POST: {}", webResource); - return webResource.request() - .post(new TypeReference() { - }, command.getImageStream()); + webResource.request().postStream(command.getImageStream()); + + return null; } } From f44616f0808e1caede610594a769327a38158687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kubry=C5=84ski?= Date: Sun, 28 Aug 2016 17:43:31 +0200 Subject: [PATCH 167/780] Fix #682 - Add LogPath to docker inspect response (#683) * Fix #682 - Add LogPath to docker inspect response * Fix #682 - Add LogPath to docker inspect response - fixes after code review * Fix #682 - Add LogPath to docker inspect response - add javadoc * Fix #682 - Add LogPath to docker inspect response - clean test assertion --- .../api/command/InspectContainerResponse.java | 11 +++++++++++ .../api/command/InspectContainerResponseTest.java | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java index 59a267e9d..c8027b0ed 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java @@ -53,6 +53,12 @@ public class InspectContainerResponse { @JsonProperty("HostsPath") private String hostsPath; + /** + * @since {@link RemoteApiVersion#VERSION_1_17} + */ + @JsonProperty("LogPath") + private String logPath; + @JsonProperty("Id") private String id; @@ -168,6 +174,11 @@ public String getHostsPath() { return hostsPath; } + @CheckForNull + public String getLogPath() { + return logPath; + } + public String getName() { return name; } diff --git a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java index f64cf4ead..cd4562b4a 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java @@ -22,6 +22,7 @@ import static com.github.dockerjava.test.serdes.JSONTestHelper.testRoundTrip; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.IsNot.not; @@ -51,6 +52,7 @@ public void roundTrip_full() throws IOException { assertEquals(response.getVolumesRW()[1].getVolume().getPath(), "/bar/foo/myvol2"); assertFalse(response.getVolumesRW()[1].getAccessMode().toBoolean()); assertTrue(response.getVolumesRW()[0].getAccessMode().toBoolean()); + assertThat(response.getLogPath(), is("/mnt/sda1/var/lib/docker/containers/469e5edd8d5b33e3c905a7ffc97360ec6ee211d6782815fbcd144568045819e1/469e5edd8d5b33e3c905a7ffc97360ec6ee211d6782815fbcd144568045819e1-json.log")); } @Test From bcb2ab947ff1020dfd89838a29d540bf802e2e31 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 28 Aug 2016 18:45:25 +0300 Subject: [PATCH 168/780] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8582d4eef..735283ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ Change Log ## Next ## 3.0.6 - * Make all models Serializable + * Make all models Serializable. + * [NETTY] Fix loadImage responce on 1.24 API. + * LogPath field for inspect container. ## 3.0.5 * Events updated to 1.24 API model. From d9f6969e0c8bb7756c0d4301b23688477e3da2d5 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sun, 28 Aug 2016 21:10:49 +0300 Subject: [PATCH 169/780] Wait more for this test --- .../dockerjava/netty/exec/AttachContainerCmdExecTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index d3e8094cf..8b5759c69 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -115,7 +115,7 @@ public void onNext(Frame frame) { .withFollowStream(true) .withStdIn(stdin) .exec(callback) - .awaitCompletion(15, SECONDS); + .awaitCompletion(30, SECONDS); callback.close(); assertThat(callback.toString(), containsString(snippet)); From 615c89f30ee301ba47bd5ef82a7549b251a7be5f Mon Sep 17 00:00:00 2001 From: tejksat Date: Wed, 31 Aug 2016 01:05:13 +0300 Subject: [PATCH 170/780] Fix for #687 --- .../exec/AttachContainerCmdExecTest.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java index 8b5759c69..66219dc72 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AttachContainerCmdExecTest.java @@ -6,11 +6,10 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; -import java.io.ByteArrayInputStream; import java.io.File; -import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; import java.lang.reflect.Method; -import java.util.concurrent.TimeUnit; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; @@ -93,8 +92,6 @@ public void attachContainerWithStdin() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - Thread.sleep(SECONDS.toMillis(10)); //wait bash initialisation - InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); assertTrue(inspectContainerResponse.getState().getRunning()); @@ -107,15 +104,20 @@ public void onNext(Frame frame) { } }; - InputStream stdin = new ByteArrayInputStream((snippet + "\n").getBytes()); + PipedOutputStream out = new PipedOutputStream(); + PipedInputStream in = new PipedInputStream(out); dockerClient.attachContainerCmd(container.getId()) .withStdErr(true) .withStdOut(true) .withFollowStream(true) - .withStdIn(stdin) - .exec(callback) - .awaitCompletion(30, SECONDS); + .withStdIn(in) + .exec(callback); + + out.write((snippet + "\n").getBytes()); + out.flush(); + + callback.awaitCompletion(15, SECONDS); callback.close(); assertThat(callback.toString(), containsString(snippet)); From 74d506dca45c0cc64f567311227c7108ca0101c6 Mon Sep 17 00:00:00 2001 From: tejksat Date: Mon, 5 Sep 2016 08:42:35 +0300 Subject: [PATCH 171/780] Fix http response input stream resource leak (#633) there are several problems in the original code: - not releasing `ByteBuf` queued; - queuing `ByteBuf` until all data is read what effectively leads to `OutOfDirectMemoryError` if the data read is too big. This happens if you try to copy too big file or folder from a container. To fix this `ResponseCallback` (which in `awaitResult()` waits in fact for `readComplete()` channel method invocation) replaced with `AsyncResultCallback`; - actually queuing `ByteBuf` anyway leads to `OutOfDirectMemoryError` if data consumption is slower (the next point) than obtaining it; - poor performance because of the byte-by-byte reads. --- .../dockerjava/netty/InvocationBuilder.java | 56 ++++++- .../handler/HttpResponseStreamHandler.java | 137 ++++++++++++++---- .../netty/exec/SaveImageCmdExecTest.java | 5 +- .../HttpResponseStreamHandlerTest.java | 90 +++++++++++- 4 files changed, 249 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java b/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java index d76918bcb..26b950e4e 100644 --- a/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java +++ b/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java @@ -27,6 +27,7 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CountDownLatch; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; @@ -75,6 +76,57 @@ public void onNext(Void object) { } } + /** + * Implementation of {@link ResultCallback} with the single result event expected. + */ + public static class AsyncResultCallback + extends ResultCallbackTemplate, A_RES_T> { + + private A_RES_T result = null; + + private final CountDownLatch resultReady = new CountDownLatch(1); + + @Override + public void onNext(A_RES_T object) { + onResult(object); + } + + private void onResult(A_RES_T object) { + if (resultReady.getCount() == 0) { + throw new IllegalStateException("Result has already been set"); + } + + try { + result = object; + } finally { + resultReady.countDown(); + } + } + + @Override + public void close() throws IOException { + try { + super.close(); + } finally { + resultReady.countDown(); + } + } + + /** + * Blocks until {@link ResultCallback#onNext(Object)} was called for the first time + */ + @SuppressWarnings("unchecked") + public A_RES_T awaitResult() { + try { + resultReady.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + getFirstError(); + return result; + } + } + private ChannelProvider channelProvider; private String resource; @@ -203,7 +255,7 @@ public InputStream post(final Object entity) { Channel channel = getChannel(); - ResponseCallback callback = new ResponseCallback(); + AsyncResultCallback callback = new AsyncResultCallback<>(); HttpResponseHandler responseHandler = new HttpResponseHandler(requestProvider, callback); HttpResponseStreamHandler streamHandler = new HttpResponseStreamHandler(callback); @@ -454,7 +506,7 @@ public InputStream get() { Channel channel = getChannel(); - ResponseCallback resultCallback = new ResponseCallback(); + AsyncResultCallback resultCallback = new AsyncResultCallback<>(); HttpResponseHandler responseHandler = new HttpResponseHandler(requestProvider, resultCallback); diff --git a/src/main/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandler.java b/src/main/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandler.java index 706228d04..596334640 100644 --- a/src/main/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandler.java +++ b/src/main/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandler.java @@ -6,9 +6,6 @@ import java.io.IOException; import java.io.InputStream; -import java.util.concurrent.LinkedTransferQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import com.github.dockerjava.api.async.ResultCallback; @@ -19,45 +16,87 @@ */ public class HttpResponseStreamHandler extends SimpleChannelInboundHandler { - private HttpResponseInputStream stream = new HttpResponseInputStream(); + private ResultCallback resultCallback; + + private final HttpResponseInputStream stream = new HttpResponseInputStream(); public HttpResponseStreamHandler(ResultCallback resultCallback) { - resultCallback.onNext(stream); + this.resultCallback = resultCallback; } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { + invokeCallbackOnFirstRead(); + stream.write(msg.copy()); } + private void invokeCallbackOnFirstRead() { + if (resultCallback != null) { + resultCallback.onNext(stream); + resultCallback = null; + } + } + @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - stream.close(); - super.channelReadComplete(ctx); + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + stream.writeComplete(); + + super.channelInactive(ctx); } public static class HttpResponseInputStream extends InputStream { - private AtomicBoolean closed = new AtomicBoolean(false); + private boolean writeCompleted = false; - private LinkedTransferQueue queue = new LinkedTransferQueue(); + private boolean closed = false; private ByteBuf current = null; - public void write(ByteBuf byteBuf) { - queue.put(byteBuf); + private final Object lock = new Object(); + + public void write(ByteBuf byteBuf) throws InterruptedException { + synchronized (lock) { + if (closed) { + return; + } + while (current != null) { + lock.wait(); + + if (closed) { + return; + } + } + current = byteBuf; + + lock.notifyAll(); + } + } + + public void writeComplete() { + synchronized (lock) { + writeCompleted = true; + + lock.notifyAll(); + } } @Override public void close() throws IOException { - closed.set(true); - super.close(); + synchronized (lock) { + closed = true; + releaseCurrent(); + + lock.notifyAll(); + } } @Override public int available() throws IOException { - poll(); - return readableBytes(); + synchronized (lock) { + poll(0); + return readableBytes(); + } } private int readableBytes() { @@ -66,34 +105,72 @@ private int readableBytes() { } else { return 0; } - } @Override public int read() throws IOException { + byte[] b = new byte[1]; + int n = read(b, 0, 1); + return n != -1 ? b[0] : -1; + } - poll(); + @Override + public int read(byte[] b, int off, int len) throws IOException { + synchronized (lock) { + off = poll(off); - if (readableBytes() == 0) { - if (closed.get()) { + if (current == null) { return -1; + } else { + int availableBytes = Math.min(len, current.readableBytes() - off); + current.readBytes(b, off, availableBytes); + return availableBytes; } } + } - if (current != null && current.readableBytes() > 0) { - return current.readByte() & 0xff; - } else { - return read(); + private int poll(int off) throws IOException { + synchronized (lock) { + while (readableBytes() <= off) { + try { + if (closed) { + throw new IOException("Stream closed"); + } + + off -= releaseCurrent(); + if (writeCompleted) { + return off; + } + while (current == null) { + lock.wait(); + + if (closed) { + throw new IOException("Stream closed"); + } + if (writeCompleted && current == null) { + return off; + } + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + return off; } } - private void poll() { - if (readableBytes() == 0) { - try { - current = queue.poll(50, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); + private int releaseCurrent() { + synchronized (lock) { + if (current != null) { + int n = current.readableBytes(); + current.release(); + current = null; + + lock.notifyAll(); + + return n; } + return 0; } } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/SaveImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/SaveImageCmdExecTest.java index 0527b793f..a2fab38a7 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/SaveImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/SaveImageCmdExecTest.java @@ -47,8 +47,9 @@ public void afterMethod(ITestResult result) { @Test public void saveImage() throws Exception { - InputStream image = IOUtils.toBufferedInputStream(dockerClient.saveImageCmd("busybox").exec()); - assertThat(image.available(), greaterThan(0)); + try (InputStream image = dockerClient.saveImageCmd("busybox").exec()) { + assertThat(image.available(), greaterThan(0)); + } } diff --git a/src/test/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandlerTest.java b/src/test/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandlerTest.java index 6652f3eba..eea9ddc0f 100644 --- a/src/test/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandlerTest.java +++ b/src/test/java/com/github/dockerjava/netty/handler/HttpResponseStreamHandlerTest.java @@ -1,13 +1,21 @@ package com.github.dockerjava.netty.handler; +import static com.github.dockerjava.netty.handler.HttpResponseStreamHandler.HttpResponseInputStream; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import java.io.InputStream; - import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + import org.apache.commons.io.IOUtils; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -25,9 +33,81 @@ public void testNoBytesSkipped() throws Exception { ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class); ByteBuf buffer = generateByteBuf(); streamHandler.channelRead0(ctx, buffer); - streamHandler.channelReadComplete(ctx); + streamHandler.channelInactive(ctx); + + try (InputStream inputStream = callback.getInputStream()) { + assertTrue(IOUtils.contentEquals(inputStream, new ByteBufInputStream(buffer))); + } + } + + @Test + public void testReadByteByByte() throws Exception { + ResultCallbackTest callback = new ResultCallbackTest(); + HttpResponseStreamHandler streamHandler = new HttpResponseStreamHandler(callback); + ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class); + ByteBuf buffer = generateByteBuf(); + streamHandler.channelRead0(ctx, buffer); + streamHandler.channelInactive(ctx); + + try (InputStream inputStream = callback.getInputStream()) { + for (int i = 0; i < buffer.readableBytes(); i++) { + int b = inputStream.read(); + assertEquals(b, buffer.getByte(i)); + } + assertTrue(inputStream.read() == -1); + } + } + + @Test + public void testCloseResponseStreamBeforeWrite() throws Exception { + HttpResponseInputStream inputStream = new HttpResponseInputStream(); + ByteBuf buffer = generateByteBuf(); + + inputStream.write(buffer); + inputStream.close(); + inputStream.write(buffer); + } + + @Test + public void testCloseResponseStreamOnWrite() throws Exception { + final HttpResponseInputStream inputStream = new HttpResponseInputStream(); + + final ByteBuf buffer = generateByteBuf(); + + final CountDownLatch firstWrite = new CountDownLatch(1); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future submit = executor.submit(new Runnable() { + @Override + public void run() { + try { + inputStream.write(buffer); + firstWrite.countDown(); + inputStream.write(buffer); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + + firstWrite.await(); + assertTrue(inputStream.available() > 0); + + // second write should have started + Thread.sleep(500L); + inputStream.close(); + + submit.get(); + } + + @Test(expectedExceptions = IOException.class) + public void testReadClosedResponseStream() throws Exception { + HttpResponseInputStream inputStream = new HttpResponseInputStream(); + ByteBuf buffer = generateByteBuf(); - assertTrue(IOUtils.contentEquals(callback.getInputStream(), new ByteBufInputStream(buffer))); + inputStream.write(buffer); + inputStream.close(); + inputStream.read(); } private ByteBuf generateByteBuf() { @@ -46,7 +126,7 @@ public void onNext(InputStream stream) { this.stream = stream; } - public InputStream getInputStream() { + private InputStream getInputStream() { return stream; } } From d07e2f6be5ee4f87dd97ce725e0b9fe22c66cd8b Mon Sep 17 00:00:00 2001 From: Jiapeng Yang Date: Sat, 10 Sep 2016 01:26:56 +0800 Subject: [PATCH 172/780] =?UTF-8?q?Bugfix:donot=20throw=20RuntimeException?= =?UTF-8?q?=20when=20a=20error=20occured=20in=20awaitComp=E2=80=A6=20(#700?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bugfix:donot throw RuntimeException when a error occured in awaitCompletion(long,TimeUnit) * Fix indentation * fix format error,use docker-java-formatter.xml --- .../github/dockerjava/core/async/ResultCallbackTemplate.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java index f120012af..2437fc878 100644 --- a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java +++ b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java @@ -99,7 +99,9 @@ public RC_T awaitCompletion() throws InterruptedException { * before {@link ResultCallback#onComplete()} was called. */ public boolean awaitCompletion(long timeout, TimeUnit timeUnit) throws InterruptedException { - return completed.await(timeout, timeUnit); + boolean result = completed.await(timeout, timeUnit); + getFirstError(); + return result; } /** From 95e5075874a355bb90a365de52082932278ed9a3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 9 Sep 2016 20:27:56 +0300 Subject: [PATCH 173/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 735283ae8..f8b6dcd86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Change Log * Make all models Serializable. * [NETTY] Fix loadImage responce on 1.24 API. * LogPath field for inspect container. + * [#700] (https://github.com/docker-java/docker-java/pull/700) Bugfix:donot throw RuntimeException when a error occured in awaitCompletion(long,TimeUnit) ## 3.0.5 * Events updated to 1.24 API model. From d39d7f210ab6c9190b21b70f3ec6117e5d4f9864 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Sat, 10 Sep 2016 18:54:03 +0200 Subject: [PATCH 174/780] Fix issue with jersey and unix domain sockets (#697) --- .gitignore | 3 +- pom.xml | 29 +- .../core/async/ResultCallbackTemplate.java | 10 +- .../util/WrappedResponseInputStream.java | 5 +- .../http/impl/io/ChunkedInputStream.java | 337 ++++++++++++++ .../newsclub/net/unix/AFUNIXSocketImpl.java | 415 ++++++++++++++++++ .../core/command/EventsCmdImplTest.java | 120 ++--- .../command/StopContainerCmdImplTest.java | 8 +- .../command/UpdateContainerCmdImplTest.java | 4 +- .../netty/exec/EventsCmdExecTest.java | 116 ++--- .../netty/exec/StopContainerCmdExecTest.java | 12 +- .../exec/UpdateContainerCmdExecTest.java | 4 +- 12 files changed, 914 insertions(+), 149 deletions(-) create mode 100644 src/main/java/org/apache/http/impl/io/ChunkedInputStream.java create mode 100644 src/main/java/org/newsclub/net/unix/AFUNIXSocketImpl.java diff --git a/.gitignore b/.gitignore index 8f1fdc779..a705c1129 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ target *.log #Ignore Test Output -test-output \ No newline at end of file +test-output +/.checkstyle diff --git a/pom.xml b/pom.xml index b1b6d96a9..5cc227ee3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -67,7 +68,7 @@ 1.7.21 1.54 - 2015-01-27T15-02-14 + 2.0.4 19.0 @@ -115,11 +116,15 @@ ${jersey.version} - de.gesellix - unix-socket-factory - ${unix-socket-factory.version} + com.kohlschutter.junixsocket + junixsocket-common + ${junixsocket.version} + + + com.kohlschutter.junixsocket + junixsocket-native-common + ${junixsocket.version} - org.apache.commons commons-compress @@ -266,13 +271,6 @@ - - - - - - - @@ -419,7 +417,7 @@ true 1 integration - integration-auth + integration-auth **/*Test.java @@ -483,7 +481,8 @@ true true false - + src/test/resources/checkstyle/checkstyle-config.xml diff --git a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java index 2437fc878..2238dfcea 100644 --- a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java +++ b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java @@ -75,11 +75,13 @@ public void onComplete() { @Override public void close() throws IOException { - closed = true; - if (stream != null) { - stream.close(); + if (!closed) { + closed = true; + if (stream != null) { + stream.close(); + } + completed.countDown(); } - completed.countDown(); } /** diff --git a/src/main/java/com/github/dockerjava/jaxrs/util/WrappedResponseInputStream.java b/src/main/java/com/github/dockerjava/jaxrs/util/WrappedResponseInputStream.java index afe0dce92..4ec74ddcc 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/util/WrappedResponseInputStream.java +++ b/src/main/java/com/github/dockerjava/jaxrs/util/WrappedResponseInputStream.java @@ -53,9 +53,12 @@ public int available() throws IOException { } public void close() throws IOException { + if (closed) { + return; + } closed = true; - response.close(); delegate.close(); + response.close(); } public void mark(int readlimit) { diff --git a/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java b/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java new file mode 100644 index 000000000..17c339e3e --- /dev/null +++ b/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java @@ -0,0 +1,337 @@ +// Modified version (see https://github.com/docker-java/docker-java/pull/697) +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.io; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.http.ConnectionClosedException; +import org.apache.http.Header; +import org.apache.http.HttpException; +import org.apache.http.MalformedChunkCodingException; +import org.apache.http.TruncatedChunkException; +import org.apache.http.config.MessageConstraints; +import org.apache.http.io.BufferInfo; +import org.apache.http.io.SessionInputBuffer; +import org.apache.http.util.Args; +import org.apache.http.util.CharArrayBuffer; + +/** + * Implements chunked transfer coding. The content is received in small chunks. + * Entities transferred using this input stream can be of unlimited length. + * After the stream is read to the end, it provides access to the trailers, + * if any. + *

+ * Note that this class NEVER closes the underlying stream, even when close + * gets called. Instead, it will read until the "end" of its chunking on + * close, which allows for the seamless execution of subsequent HTTP 1.1 + * requests, while not requiring the client to remember to read the entire + * contents of the response. + * + * + * @since 4.0 + * + */ +public class ChunkedInputStream extends InputStream { + + private static final int CHUNK_LEN = 1; + private static final int CHUNK_DATA = 2; + private static final int CHUNK_CRLF = 3; + private static final int CHUNK_INVALID = Integer.MAX_VALUE; + + private static final int BUFFER_SIZE = 2048; + + /** The session input buffer */ + private final SessionInputBuffer in; + private final CharArrayBuffer buffer; + private final MessageConstraints constraints; + + private int state; + + /** The chunk size */ + private long chunkSize; + + /** The current position within the current chunk */ + private long pos; + + /** True if we've reached the end of stream */ + private boolean eof = false; + + /** True if this stream is closed */ + private boolean closed = false; + + private Header[] footers = new Header[] {}; + + /** + * Wraps session input stream and reads chunk coded input. + * + * @param in The session input buffer + * @param constraints Message constraints. If {@code null} + * {@link MessageConstraints#DEFAULT} will be used. + * + * @since 4.4 + */ + public ChunkedInputStream(final SessionInputBuffer in, final MessageConstraints constraints) { + super(); + this.in = Args.notNull(in, "Session input buffer"); + this.pos = 0L; + this.buffer = new CharArrayBuffer(16); + this.constraints = constraints != null ? constraints : MessageConstraints.DEFAULT; + this.state = CHUNK_LEN; + } + + /** + * Wraps session input stream and reads chunk coded input. + * + * @param in The session input buffer + */ + public ChunkedInputStream(final SessionInputBuffer in) { + this(in, null); + } + + @Override + public int available() throws IOException { + if (this.in instanceof BufferInfo) { + final int len = ((BufferInfo) this.in).length(); + return (int) Math.min(len, this.chunkSize - this.pos); + } else { + return 0; + } + } + + /** + *

Returns all the data in a chunked stream in coalesced form. A chunk + * is followed by a CRLF. The method returns -1 as soon as a chunksize of 0 + * is detected.

+ * + *

Trailer headers are read automatically at the end of the stream and + * can be obtained with the getResponseFooters() method.

+ * + * @return -1 of the end of the stream has been reached or the next data + * byte + * @throws IOException in case of an I/O error + */ + @Override + public int read() throws IOException { + if (this.closed) { + throw new IOException("Attempted read from closed stream."); + } + if (this.eof) { + return -1; + } + if (state != CHUNK_DATA) { + nextChunk(); + if (this.eof) { + return -1; + } + } + final int b = in.read(); + if (b != -1) { + pos++; + if (pos >= chunkSize) { + state = CHUNK_CRLF; + } + } + return b; + } + + /** + * Read some bytes from the stream. + * @param b The byte array that will hold the contents from the stream. + * @param off The offset into the byte array at which bytes will start to be + * placed. + * @param len the maximum number of bytes that can be returned. + * @return The number of bytes returned or -1 if the end of stream has been + * reached. + * @throws IOException in case of an I/O error + */ + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + + if (closed) { + throw new IOException("Attempted read from closed stream."); + } + + if (eof) { + return -1; + } + if (state != CHUNK_DATA) { + nextChunk(); + if (eof) { + return -1; + } + } + final int bytesRead = in.read(b, off, (int) Math.min(len, chunkSize - pos)); + if (bytesRead != -1) { + pos += bytesRead; + if (pos >= chunkSize) { + state = CHUNK_CRLF; + } + return bytesRead; + } else { + eof = true; + throw new TruncatedChunkException("Truncated chunk " + + "( expected size: " + chunkSize + + "; actual size: " + pos + ")"); + } + } + + /** + * Read some bytes from the stream. + * @param b The byte array that will hold the contents from the stream. + * @return The number of bytes returned or -1 if the end of stream has been + * reached. + * @throws IOException in case of an I/O error + */ + @Override + public int read(final byte[] b) throws IOException { + return read(b, 0, b.length); + } + + /** + * Read the next chunk. + * @throws IOException in case of an I/O error + */ + private void nextChunk() throws IOException { + if (state == CHUNK_INVALID) { + throw new MalformedChunkCodingException("Corrupt data stream"); + } + try { + chunkSize = getChunkSize(); + if (chunkSize < 0L) { + throw new MalformedChunkCodingException("Negative chunk size"); + } + state = CHUNK_DATA; + pos = 0L; + if (chunkSize == 0L) { + eof = true; + parseTrailerHeaders(); + } + } catch (MalformedChunkCodingException ex) { + state = CHUNK_INVALID; + throw ex; + } + } + + /** + * Expects the stream to start with a chunksize in hex with optional + * comments after a semicolon. The line must end with a CRLF: "a3; some + * comment\r\n" Positions the stream at the start of the next line. + */ + private long getChunkSize() throws IOException { + final int st = this.state; + switch (st) { + case CHUNK_CRLF: + this.buffer.clear(); + final int bytesRead1 = this.in.readLine(this.buffer); + if (bytesRead1 == -1) { + throw new MalformedChunkCodingException( + "CRLF expected at end of chunk"); + } + if (!this.buffer.isEmpty()) { + throw new MalformedChunkCodingException( + "Unexpected content at the end of chunk"); + } + state = CHUNK_LEN; + //$FALL-THROUGH$ + case CHUNK_LEN: + this.buffer.clear(); + final int bytesRead2 = this.in.readLine(this.buffer); + if (bytesRead2 == -1) { + throw new ConnectionClosedException("Premature end of chunk coded message body: " + + "closing chunk expected"); + } + int separator = this.buffer.indexOf(';'); + if (separator < 0) { + separator = this.buffer.length(); + } + final String s = this.buffer.substringTrimmed(0, separator); + try { + return Long.parseLong(s, 16); + } catch (final NumberFormatException e) { + throw new MalformedChunkCodingException("Bad chunk header: " + s); + } + default: + throw new IllegalStateException("Inconsistent codec state"); + } + } + + /** + * Reads and stores the Trailer headers. + * @throws IOException in case of an I/O error + */ + private void parseTrailerHeaders() throws IOException { + try { + this.footers = AbstractMessageParser.parseHeaders(in, + constraints.getMaxHeaderCount(), + constraints.getMaxLineLength(), + null); + } catch (final HttpException ex) { + final IOException ioe = new MalformedChunkCodingException("Invalid footer: " + + ex.getMessage()); + ioe.initCause(ex); + throw ioe; + } + } + + /** + * Upon close, this reads the remainder of the chunked message, + * leaving the underlying socket at a position to start reading the + * next response without scanning. + * @throws IOException in case of an I/O error + */ + @Override + public void close() throws IOException { + if (!closed) { + try { + if (!eof && state != CHUNK_INVALID) { + // read and discard the remainder of the message + final byte[] buff = new byte[BUFFER_SIZE]; + try { + while (read(buff) >= 0) { + continue; + } + } catch (ConnectionClosedException e) { + // just ignore + } catch (TruncatedChunkException e) { + // just ignore + } + } + } finally { + eof = true; + closed = true; + } + } + } + + public Header[] getFooters() { + return this.footers.clone(); + } + +} diff --git a/src/main/java/org/newsclub/net/unix/AFUNIXSocketImpl.java b/src/main/java/org/newsclub/net/unix/AFUNIXSocketImpl.java new file mode 100644 index 000000000..869d987f2 --- /dev/null +++ b/src/main/java/org/newsclub/net/unix/AFUNIXSocketImpl.java @@ -0,0 +1,415 @@ +// Modified version (see https://github.com/docker-java/docker-java/pull/697) +/** + * junixsocket + * + * Copyright (c) 2009,2014 Christian Kohlschütter + * + * The author licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.newsclub.net.unix; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketImpl; +import java.net.SocketOptions; + +/** + * The Java-part of the {@link AFUNIXSocket} implementation. + * + * @author Christian Kohlschütter + */ +class AFUNIXSocketImpl extends SocketImpl { + private static final int SHUT_RD = 0; + private static final int SHUT_WR = 1; + private static final int SHUT_RD_WR = 2; + + private String socketFile; + private boolean closed = false; + private boolean bound = false; + private boolean connected = false; + + private boolean closedInputStream = false; + private boolean closedOutputStream = false; + + private final AFUNIXInputStream in = new AFUNIXInputStream(); + private final AFUNIXOutputStream out = new AFUNIXOutputStream(); + + AFUNIXSocketImpl() { + super(); + this.fd = new FileDescriptor(); + } + + FileDescriptor getFD() { + return fd; + } + + @Override + protected void accept(SocketImpl socket) throws IOException { + final AFUNIXSocketImpl si = (AFUNIXSocketImpl) socket; + NativeUnixSocket.accept(socketFile, fd, si.fd); + si.socketFile = socketFile; + si.connected = true; + } + + @Override + protected int available() throws IOException { + return NativeUnixSocket.available(fd); + } + + protected void bind(SocketAddress addr) throws IOException { + bind(0, addr); + } + + protected void bind(int backlog, SocketAddress addr) throws IOException { + if (!(addr instanceof AFUNIXSocketAddress)) { + throw new SocketException("Cannot bind to this type of address: " + addr.getClass()); + } + final AFUNIXSocketAddress socketAddress = (AFUNIXSocketAddress) addr; + socketFile = socketAddress.getSocketFile(); + NativeUnixSocket.bind(socketFile, fd, backlog); + bound = true; + this.localport = socketAddress.getPort(); + } + + @Override + @SuppressWarnings("hiding") + protected void bind(InetAddress host, int port) throws IOException { + throw new SocketException("Cannot bind to this type of address: " + InetAddress.class); + } + + private void checkClose() throws IOException { + //if (closedInputStream && closedOutputStream) { + // close(); + //} + } + + @Override + protected synchronized void close() throws IOException { + if (closed) { + return; + } + closed = true; + if (fd.valid()) { + NativeUnixSocket.shutdown(fd, SHUT_RD_WR); + NativeUnixSocket.close(fd); + } + if (bound) { + NativeUnixSocket.unlink(socketFile); + } + connected = false; + } + + @Override + @SuppressWarnings("hiding") + protected void connect(String host, int port) throws IOException { + throw new SocketException("Cannot bind to this type of address: " + InetAddress.class); + } + + @Override + @SuppressWarnings("hiding") + protected void connect(InetAddress address, int port) throws IOException { + throw new SocketException("Cannot bind to this type of address: " + InetAddress.class); + } + + @Override + protected void connect(SocketAddress addr, int timeout) throws IOException { + if (!(addr instanceof AFUNIXSocketAddress)) { + throw new SocketException("Cannot bind to this type of address: " + addr.getClass()); + } + final AFUNIXSocketAddress socketAddress = (AFUNIXSocketAddress) addr; + socketFile = socketAddress.getSocketFile(); + NativeUnixSocket.connect(socketFile, fd); + this.address = socketAddress.getAddress(); + this.port = socketAddress.getPort(); + this.localport = 0; + this.connected = true; + } + + @Override + protected void create(boolean stream) throws IOException { + } + + @Override + protected InputStream getInputStream() throws IOException { + if (!connected && !bound) { + throw new IOException("Not connected/not bound"); + } + return in; + } + + @Override + protected OutputStream getOutputStream() throws IOException { + if (!connected && !bound) { + throw new IOException("Not connected/not bound"); + } + return out; + } + + @Override + protected void listen(int backlog) throws IOException { + NativeUnixSocket.listen(fd, backlog); + } + + @Override + protected void sendUrgentData(int data) throws IOException { + NativeUnixSocket.write(fd, new byte[] {(byte) (data & 0xFF)}, 0, 1); + } + + private final class AFUNIXInputStream extends InputStream { + private boolean streamClosed = false; + + @Override + public int read(byte[] buf, int off, int len) throws IOException { + if (streamClosed) { + throw new IOException("This InputStream has already been closed."); + } + if (len == 0) { + return 0; + } + if (closed) { + return -1; + } + int maxRead = buf.length - off; + if (len > maxRead) { + len = maxRead; + } + try { + return NativeUnixSocket.read(fd, buf, off, len); + } catch (final IOException e) { + throw (IOException) new IOException(e.getMessage() + " at " + + AFUNIXSocketImpl.this.toString()).initCause(e); + } + } + + @Override + public int read() throws IOException { + final byte[] buf1 = new byte[1]; + final int numRead = read(buf1, 0, 1); + if (numRead <= 0) { + return -1; + } else { + return buf1[0] & 0xFF; + } + } + + @Override + public void close() throws IOException { + if (streamClosed) { + return; + } + streamClosed = true; + if (fd.valid()) { + NativeUnixSocket.shutdown(fd, SHUT_RD); + } + + closedInputStream = true; + checkClose(); + } + + @Override + public int available() throws IOException { + final int av = NativeUnixSocket.available(fd); + return av; + } + } + + private final class AFUNIXOutputStream extends OutputStream { + private boolean streamClosed = false; + + @Override + public void write(int oneByte) throws IOException { + final byte[] buf1 = new byte[] {(byte) oneByte}; + write(buf1, 0, 1); + } + + @Override + public void write(byte[] buf, int off, int len) throws IOException { + if (streamClosed) { + throw new AFUNIXSocketException("This OutputStream has already been closed."); + } + if (len > buf.length - off) { + throw new IndexOutOfBoundsException(); + } + try { + while (len > 0 && !Thread.interrupted()) { + final int written = NativeUnixSocket.write(fd, buf, off, len); + if (written == -1) { + throw new IOException("Unspecific error while writing"); + } + len -= written; + off += written; + } + } catch (final IOException e) { + throw (IOException) new IOException(e.getMessage() + " at " + + AFUNIXSocketImpl.this.toString()).initCause(e); + } + } + + @Override + public void close() throws IOException { + if (streamClosed) { + return; + } + streamClosed = true; + if (fd.valid()) { + NativeUnixSocket.shutdown(fd, SHUT_WR); + } + closedOutputStream = true; + checkClose(); + } + } + + @Override + public String toString() { + return super.toString() + "[fd=" + fd + "; file=" + this.socketFile + "; connected=" + + connected + "; bound=" + bound + "]"; + } + + private static int expectInteger(Object value) throws SocketException { + try { + return (Integer) value; + } catch (final ClassCastException e) { + throw new AFUNIXSocketException("Unsupported value: " + value, e); + } catch (final NullPointerException e) { + throw new AFUNIXSocketException("Value must not be null", e); + } + } + + private static int expectBoolean(Object value) throws SocketException { + try { + return ((Boolean) value).booleanValue() ? 1 : 0; + } catch (final ClassCastException e) { + throw new AFUNIXSocketException("Unsupported value: " + value, e); + } catch (final NullPointerException e) { + throw new AFUNIXSocketException("Value must not be null", e); + } + } + + @Override + public Object getOption(int optID) throws SocketException { + try { + switch (optID) { + case SocketOptions.SO_KEEPALIVE: + case SocketOptions.TCP_NODELAY: + return NativeUnixSocket.getSocketOptionInt(fd, optID) != 0 ? true : false; + case SocketOptions.SO_LINGER: + case SocketOptions.SO_TIMEOUT: + case SocketOptions.SO_RCVBUF: + case SocketOptions.SO_SNDBUF: + return NativeUnixSocket.getSocketOptionInt(fd, optID); + default: + throw new AFUNIXSocketException("Unsupported option: " + optID); + } + } catch (final AFUNIXSocketException e) { + throw e; + } catch (final Exception e) { + throw new AFUNIXSocketException("Error while getting option", e); + } + } + + @Override + public void setOption(int optID, Object value) throws SocketException { + try { + switch (optID) { + case SocketOptions.SO_LINGER: + + if (value instanceof Boolean) { + final boolean b = (Boolean) value; + if (b) { + throw new SocketException("Only accepting Boolean.FALSE here"); + } + NativeUnixSocket.setSocketOptionInt(fd, optID, -1); + return; + } + NativeUnixSocket.setSocketOptionInt(fd, optID, expectInteger(value)); + return; + case SocketOptions.SO_RCVBUF: + case SocketOptions.SO_SNDBUF: + case SocketOptions.SO_TIMEOUT: + NativeUnixSocket.setSocketOptionInt(fd, optID, expectInteger(value)); + return; + case SocketOptions.SO_KEEPALIVE: + case SocketOptions.TCP_NODELAY: + NativeUnixSocket.setSocketOptionInt(fd, optID, expectBoolean(value)); + return; + default: + throw new AFUNIXSocketException("Unsupported option: " + optID); + } + } catch (final AFUNIXSocketException e) { + throw e; + } catch (final Exception e) { + throw new AFUNIXSocketException("Error while setting option", e); + } + } + + @Override + protected void shutdownInput() throws IOException { + if (!closed && fd.valid()) { + NativeUnixSocket.shutdown(fd, SHUT_RD); + } + } + + @Override + protected void shutdownOutput() throws IOException { + if (!closed && fd.valid()) { + NativeUnixSocket.shutdown(fd, SHUT_WR); + } + } + + /** + * Changes the behavior to be somewhat lenient with respect to the specification. + * + * In particular, we ignore calls to {@link Socket#getTcpNoDelay()} and + * {@link Socket#setTcpNoDelay(boolean)}. + */ + static class Lenient extends AFUNIXSocketImpl { + Lenient() { + super(); + } + + @Override + public void setOption(int optID, Object value) throws SocketException { + try { + super.setOption(optID, value); + } catch (SocketException e) { + switch (optID) { + case SocketOptions.TCP_NODELAY: + return; + default: + throw e; + } + } + } + + @Override + public Object getOption(int optID) throws SocketException { + try { + return super.getOption(optID); + } catch (SocketException e) { + switch (optID) { + case SocketOptions.TCP_NODELAY: + case SocketOptions.SO_KEEPALIVE: + return false; + default: + throw e; + } + } + } + } +} diff --git a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java index 939f95087..d05327a06 100644 --- a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java @@ -17,11 +17,14 @@ import com.github.dockerjava.api.model.Event; import com.github.dockerjava.client.AbstractDockerClientTest; +/* + * NOTE: These tests may fail if there is a difference between local and daemon time + * (this is especially a problem when using boot2docker as time may not in sync + * with the virtualbox host system) + */ @Test(groups = "integration") public class EventsCmdImplTest extends AbstractDockerClientTest { - private static int KNOWN_NUM_EVENTS = 4; - private static String getEpochTime() { return String.valueOf(System.currentTimeMillis() / 1000); } @@ -46,9 +49,6 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - /* - * This specific test may fail with boot2docker as time may not in sync with host system - */ @Test public void testEventStreamTimeBound() throws Exception { // Don't include other tests events @@ -58,82 +58,84 @@ public void testEventStreamTimeBound() throws Exception { int expectedEvents = generateEvents(); String endTime = getEpochTime(); - CountDownLatch countDownLatch = new CountDownLatch(expectedEvents); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); - - dockerClient.eventsCmd().withSince(startTime).withUntil(endTime).exec(eventCallback); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); + dockerClient.eventsCmd() + .withSince(startTime) + .withUntil(endTime) + .exec(eventCallback); - eventCallback.close(); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + // we may receive more events as expected + assertTrue(events.size() >= expectedEvents, "Received events: " + events); } @Test - public void testEventStreaming1() throws Exception { - // Don't include other tests events - TimeUnit.SECONDS.sleep(1); - - CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); - - dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback); - - generateEvents(); - - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); - } - - @Test - public void testEventStreaming2() throws Exception { + public void testEventStreaming() throws Exception { // Don't include other tests events TimeUnit.SECONDS.sleep(1); + + String startTime = getEpochTime(); + int expectedEvents = generateEvents(); - CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); - dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback); + dockerClient.eventsCmd() + .withSince(startTime) + .exec(eventCallback); generateEvents(); - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); + + // we may receive more events as expected + assertTrue(events.size() >= expectedEvents, "Received events: " + events); } + public void testEventStreamingWithFilter() throws Exception { // Don't include other tests events TimeUnit.SECONDS.sleep(1); + + String startTime = getEpochTime(); + int expectedEvents = 1; - CountDownLatch countDownLatch = new CountDownLatch(1); - EventsTestCallback eventCallback = dockerClient.eventsCmd().withEventFilter("start") - .exec(new EventsTestCallback(countDownLatch)); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); + + dockerClient.eventsCmd() + .withSince(startTime) + .withEventFilter("start") + .exec(eventCallback); generateEvents(); - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); + + // we should get exactly one "start" event here + assertEquals(events.size(), expectedEvents, "Received events: " + events); } /** - * This method generates {#link KNOWN_NUM_EVENTS} events + * This method generates some events and returns the number of events being generated */ private int generateEvents() throws Exception { - String testImage = "busybox"; + String testImage = "busybox:latest"; dockerClient.pullImageCmd(testImage).exec(new PullImageResultCallback()).awaitSuccess(); - CreateContainerResponse container = dockerClient.createContainerCmd(testImage).withCmd("sleep", "9999").exec(); dockerClient.startContainerCmd(container.getId()).exec(); - dockerClient.stopContainerCmd(container.getId()).exec(); - return KNOWN_NUM_EVENTS; + dockerClient.stopContainerCmd(container.getId()).withTimeout(1).exec(); + + // generates 5 events with remote api 1.24: + + // Event[status=pull,id=busybox:latest,from=,node=,type=IMAGE,action=pull,actor=com.github.dockerjava.api.model.EventActor@417db6d7[id=busybox:latest,attributes={name=busybox}],time=1473455186,timeNano=1473455186436681587] + // Event[status=create,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=create,actor=com.github.dockerjava.api.model.EventActor@40bcec[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport}],time=1473455186,timeNano=1473455186470713257] + // Event[status=,id=,from=,node=,type=NETWORK,action=connect,actor=com.github.dockerjava.api.model.EventActor@318a1b01[id=10870ceb13abb7cf841ea68868472da881b33c8ed08d2cde7dbb39d7c24d1d27,attributes={container=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c, name=bridge, type=bridge}],time=1473455186,timeNano=1473455186544318466] + // Event[status=start,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=start,actor=com.github.dockerjava.api.model.EventActor@606f43a3[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport}],time=1473455186,timeNano=1473455186786163819] + // Event[status=kill,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=kill,actor=com.github.dockerjava.api.model.EventActor@72a9ffcf[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport, signal=15}],time=1473455186,timeNano=1473455186792963392] + + return 5; } private class EventsTestCallback extends EventsResultCallback { @@ -142,18 +144,24 @@ private class EventsTestCallback extends EventsResultCallback { private final List events = new ArrayList(); - public EventsTestCallback(CountDownLatch countDownLatch) { - this.countDownLatch = countDownLatch; + public EventsTestCallback(int expextedEvents) { + this.countDownLatch = new CountDownLatch(expextedEvents); } public void onNext(Event event) { LOG.info("Received event #{}: {}", countDownLatch.getCount(), event); - countDownLatch.countDown(); events.add(event); + countDownLatch.countDown(); } - - public List getEvents() { - return new ArrayList(events); + + public List awaitExpectedEvents(long timeout, TimeUnit unit ) { + try { + countDownLatch.await(timeout, unit); + close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + return new ArrayList(events); } } } diff --git a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java index 382e5b29c..7ae6a09cc 100644 --- a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java @@ -69,11 +69,9 @@ public void testStopContainer() throws DockerException { assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); final Integer exitCode = inspectContainerResponse.getState().getExitCode(); - if (apiVersion.equals(VERSION_1_22)) { - assertThat(exitCode, is(0)); - } else { - assertThat(exitCode, not(0)); - } + + assertThat(exitCode, is(137)); + } @Test(expectedExceptions = NotFoundException.class) diff --git a/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java index 3c7a9fd47..df53d671b 100644 --- a/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/UpdateContainerCmdImplTest.java @@ -79,7 +79,7 @@ public void updateContainer() throws DockerException, IOException { // .withCpusetCpus("0") // depends on env .withCpusetMems("0") .withMemory(314572800L) - .withMemorySwap(514288000L) +// .withMemorySwap(514288000L) Your kernel does not support swap limit capabilities, memory limited without swap. .withMemoryReservation(209715200L) // .withKernelMemory(52428800) Can not update kernel memory to a running container, please stop it first. .exec(); @@ -102,7 +102,7 @@ public void updateContainer() throws DockerException, IOException { assertThat(afterHostConfig.getCpusetMems(), is("0")); assertThat(afterHostConfig.getMemoryReservation(), is(209715200L)); - assertThat(afterHostConfig.getMemorySwap(), is(514288000L)); +// assertThat(afterHostConfig.getMemorySwap(), is(514288000L)); } diff --git a/src/test/java/com/github/dockerjava/netty/exec/EventsCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/EventsCmdExecTest.java index a634e2562..2a446569d 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/EventsCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/EventsCmdExecTest.java @@ -22,8 +22,6 @@ @Test(groups = "integration") public class EventsCmdExecTest extends AbstractNettyDockerClientTest { - private static int KNOWN_NUM_EVENTS = 4; - private static String getEpochTime() { return String.valueOf(System.currentTimeMillis() / 1000); } @@ -48,9 +46,6 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - /* - * This specific test may fail with boot2docker as time may not in sync with host system - */ @Test public void testEventStreamTimeBound() throws Exception { // Don't include other tests events @@ -60,82 +55,84 @@ public void testEventStreamTimeBound() throws Exception { int expectedEvents = generateEvents(); String endTime = getEpochTime(); - CountDownLatch countDownLatch = new CountDownLatch(expectedEvents); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); - - dockerClient.eventsCmd().withSince(startTime).withUntil(endTime).exec(eventCallback); - - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); - } - - @Test - public void testEventStreaming1() throws Exception { - // Don't include other tests events - TimeUnit.SECONDS.sleep(1); - - CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); - dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback); + dockerClient.eventsCmd() + .withSince(startTime) + .withUntil(endTime) + .exec(eventCallback); - generateEvents(); - - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + // we may receive more events as expected + assertTrue(events.size() >= expectedEvents, "Received events: " + events); } @Test - public void testEventStreaming2() throws Exception { + public void testEventStreaming() throws Exception { // Don't include other tests events TimeUnit.SECONDS.sleep(1); + + String startTime = getEpochTime(); + int expectedEvents = generateEvents(); - CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS); - EventsTestCallback eventCallback = new EventsTestCallback(countDownLatch); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); - dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback); + dockerClient.eventsCmd() + .withSince(startTime) + .exec(eventCallback); generateEvents(); - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); + + // we may receive more events as expected + assertTrue(events.size() >= expectedEvents, "Received events: " + events); } + public void testEventStreamingWithFilter() throws Exception { // Don't include other tests events TimeUnit.SECONDS.sleep(1); + + String startTime = getEpochTime(); + int expectedEvents = 1; - CountDownLatch countDownLatch = new CountDownLatch(1); - EventsTestCallback eventCallback = dockerClient.eventsCmd().withEventFilter("start") - .exec(new EventsTestCallback(countDownLatch)); + EventsTestCallback eventCallback = new EventsTestCallback(expectedEvents); + + dockerClient.eventsCmd() + .withSince(startTime) + .withEventFilter("start") + .exec(eventCallback); generateEvents(); - Boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); - - eventCallback.close(); - assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + List events = eventCallback.awaitExpectedEvents(3, TimeUnit.MINUTES); + + // we should get exactly one "start" event here + assertEquals(events.size(), expectedEvents, "Received events: " + events); } /** - * This method generates {#link KNOWN_NUM_EVENTS} events + * This method generates some events and returns the number of events being generated */ private int generateEvents() throws Exception { - String testImage = "busybox"; + String testImage = "busybox:latest"; dockerClient.pullImageCmd(testImage).exec(new PullImageResultCallback()).awaitSuccess(); - CreateContainerResponse container = dockerClient.createContainerCmd(testImage).withCmd("sleep", "9999").exec(); dockerClient.startContainerCmd(container.getId()).exec(); - dockerClient.stopContainerCmd(container.getId()).exec(); - return KNOWN_NUM_EVENTS; + dockerClient.stopContainerCmd(container.getId()).withTimeout(1).exec(); + + // generates 5 events with remote api 1.24: + + // Event[status=pull,id=busybox:latest,from=,node=,type=IMAGE,action=pull,actor=com.github.dockerjava.api.model.EventActor@417db6d7[id=busybox:latest,attributes={name=busybox}],time=1473455186,timeNano=1473455186436681587] + // Event[status=create,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=create,actor=com.github.dockerjava.api.model.EventActor@40bcec[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport}],time=1473455186,timeNano=1473455186470713257] + // Event[status=,id=,from=,node=,type=NETWORK,action=connect,actor=com.github.dockerjava.api.model.EventActor@318a1b01[id=10870ceb13abb7cf841ea68868472da881b33c8ed08d2cde7dbb39d7c24d1d27,attributes={container=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c, name=bridge, type=bridge}],time=1473455186,timeNano=1473455186544318466] + // Event[status=start,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=start,actor=com.github.dockerjava.api.model.EventActor@606f43a3[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport}],time=1473455186,timeNano=1473455186786163819] + // Event[status=kill,id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,from=busybox:latest,node=,type=CONTAINER,action=kill,actor=com.github.dockerjava.api.model.EventActor@72a9ffcf[id=6ec10182cde227040bfead8547b63105e6bbc4e94b99f6098bfad6e158ce0d3c,attributes={image=busybox:latest, name=sick_lamport, signal=15}],time=1473455186,timeNano=1473455186792963392] + + return 5; } private class EventsTestCallback extends EventsResultCallback { @@ -144,18 +141,25 @@ private class EventsTestCallback extends EventsResultCallback { private final List events = new ArrayList(); - public EventsTestCallback(CountDownLatch countDownLatch) { - this.countDownLatch = countDownLatch; + public EventsTestCallback(int expextedEvents) { + this.countDownLatch = new CountDownLatch(expextedEvents); } public void onNext(Event event) { LOG.info("Received event #{}: {}", countDownLatch.getCount(), event); - countDownLatch.countDown(); events.add(event); + countDownLatch.countDown(); } - - public List getEvents() { - return new ArrayList(events); + + public List awaitExpectedEvents(long timeout, TimeUnit unit ) { + try { + countDownLatch.await(timeout, unit); + close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + return new ArrayList(events); } } } + diff --git a/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java index 1dca12890..063bcee30 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/StopContainerCmdExecTest.java @@ -61,7 +61,7 @@ public void testStopContainer() throws DockerException { dockerClient.startContainerCmd(container.getId()).exec(); LOG.info("Stopping container: {}", container.getId()); - dockerClient.stopContainerCmd(container.getId()).withTimeout(2).exec(); + dockerClient.stopContainerCmd(container.getId()).withTimeout(10).exec(); InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); LOG.info("Container Inspect: {}", inspectContainerResponse.toString()); @@ -69,17 +69,15 @@ public void testStopContainer() throws DockerException { assertThat(inspectContainerResponse.getState().getRunning(), is(equalTo(false))); final Integer exitCode = inspectContainerResponse.getState().getExitCode(); - if (apiVersion.equals(VERSION_1_22)) { - assertThat(exitCode, is(0)); - } else { - assertThat(exitCode, not(0)); - } + + assertThat(exitCode, is(137)); + } @Test(expectedExceptions = NotFoundException.class) public void testStopNonExistingContainer() throws DockerException { - dockerClient.stopContainerCmd("non-existing").withTimeout(2).exec(); + dockerClient.stopContainerCmd("non-existing").withTimeout(10).exec(); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java index 1134afd6d..681839c17 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/UpdateContainerCmdExecTest.java @@ -78,7 +78,7 @@ public void updateContainer() throws DockerException, IOException { // .withCpusetCpus("0") // depends on env .withCpusetMems("0") .withMemory(314572800L) - .withMemorySwap(514288000L) +// .withMemorySwap(514288000L) Your kernel does not support swap limit capabilities, memory limited without swap. .withMemoryReservation(209715200L) // .withKernelMemory(52428800) Can not update kernel memory to a running container, please stop it first. .exec(); @@ -101,7 +101,7 @@ public void updateContainer() throws DockerException, IOException { assertThat(afterHostConfig.getCpusetMems(), is("0")); assertThat(afterHostConfig.getMemoryReservation(), is(209715200L)); - assertThat(afterHostConfig.getMemorySwap(), is(514288000L)); +// assertThat(afterHostConfig.getMemorySwap(), is(514288000L)); } } From 1bfe308c5321fb3e136fd5c5add09e424f3fec86 Mon Sep 17 00:00:00 2001 From: Martin Caslavsky Date: Mon, 12 Sep 2016 18:53:50 +0200 Subject: [PATCH 175/780] Allow to configure connection pool timeout (#703) The default connection pool timeout of Apache HTTP Client is -1 (unlimited) --- .../jaxrs/JerseyDockerCmdExecFactory.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java index 3339a2696..73bab979e 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java @@ -20,6 +20,7 @@ import com.github.dockerjava.api.command.UpdateContainerCmd; import com.github.dockerjava.core.SSLConfig; +import org.apache.http.client.config.RequestConfig; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -110,6 +111,8 @@ public class JerseyDockerCmdExecFactory implements DockerCmdExecFactory { private Integer maxPerRouteConnections = null; + private Integer connectionRequestTimeout = null; + private ClientRequestFilter[] clientRequestFilters = null; private ClientResponseFilter[] clientResponseFilters = null; @@ -216,9 +219,10 @@ public void shutdown() { clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connManager); // Configure connection pool timeout - // clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, RequestConfig.custom() - // .setConnectionRequestTimeout(1000).build()); - + if (connectionRequestTimeout != null) { + clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, RequestConfig.custom() + .setConnectionRequestTimeout(connectionRequestTimeout).build()); + } ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); if (sslContext != null) { @@ -570,6 +574,11 @@ public JerseyDockerCmdExecFactory withMaxPerRouteConnections(Integer maxPerRoute return this; } + public JerseyDockerCmdExecFactory withConnectionRequestTimeout(Integer connectionRequestTimeout) { + this.connectionRequestTimeout = connectionRequestTimeout; + return this; + } + public JerseyDockerCmdExecFactory withClientResponseFilters(ClientResponseFilter... clientResponseFilter) { this.clientResponseFilters = clientResponseFilter; return this; From c31716377f29bb2ece8f83bfaefc8368c3c72abb Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 14 Sep 2016 01:15:42 +0300 Subject: [PATCH 176/780] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8b6dcd86..908c2d906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Change Log ## Next ## 3.0.6 + * Fixed issue with jersey and unix domain sockets. + * [#703](https://github.com/docker-java/docker-java/pull/703) Allow to configure connection pool timeout. * Make all models Serializable. * [NETTY] Fix loadImage responce on 1.24 API. * LogPath field for inspect container. From 03181feda5bbaced61edb715fec600a5236775e3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 14 Sep 2016 01:21:10 +0300 Subject: [PATCH 177/780] [maven-release-plugin] prepare release 3.0.6 --- pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 5cc227ee3..3727ac2e9 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 @@ -11,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.6-SNAPSHOT + 3.0.6 docker-java https://github.com/docker-java/docker-java @@ -29,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.6 From c3e03be12299c34988980ade3dc7d7a6d3956b12 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 14 Sep 2016 01:21:17 +0300 Subject: [PATCH 178/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3727ac2e9..216c48631 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.6 + 3.0.7-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.6 + HEAD From 450a51670e5667e0789127f2a2d7e1a4d0fcbcb5 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 14 Sep 2016 01:33:47 +0300 Subject: [PATCH 179/780] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba8c62ad0..d055f76e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,8 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.0-0~trusty" CODECOV=true - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.0-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.1-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.1-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true From 305b73a9763f8d47bdc9698ecfaa9c844a6e087f Mon Sep 17 00:00:00 2001 From: Corey Beres Date: Wed, 28 Sep 2016 20:34:55 -0400 Subject: [PATCH 180/780] Label image during build #681 (#684) * Ability to set labels on image build (#681) * Check API version in new tests (#681) * remove unnecessary this (#681) * change withLabel to withLabels (#681) --- .../dockerjava/api/command/BuildImageCmd.java | 11 ++++++++ .../core/command/BuildImageCmdImpl.java | 16 ++++++++++++ .../dockerjava/jaxrs/BuildImageCmdExec.java | 25 +++++++++++++------ .../netty/exec/BuildImageCmdExec.java | 23 +++++++++++------ .../core/command/BuildImageCmdImplTest.java | 24 ++++++++++++++++++ .../netty/exec/BuildImageCmdExecTest.java | 24 ++++++++++++++++++ .../resources/buildTests/labels/Dockerfile | 3 +++ 7 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 src/test/resources/buildTests/labels/Dockerfile diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java index 20b23e903..ac98db2f9 100644 --- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java @@ -101,6 +101,12 @@ public interface BuildImageCmd extends AsyncDockerCmd getLabels(); + // setters BuildImageCmd withTag(String tag); @@ -145,6 +151,11 @@ public interface BuildImageCmd extends AsyncDockerCmd labels); + interface Exec extends DockerCmdAsyncExec { } diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java index 487f0b264..c34b05155 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java @@ -56,6 +56,8 @@ public class BuildImageCmdImpl extends AbstrAsyncDockerCmd buildArgs; + private Map labels; + public BuildImageCmdImpl(BuildImageCmd.Exec exec) { super(exec); } @@ -149,6 +151,11 @@ public Map getBuildArgs() { return buildArgs; } + @Override + public Map getLabels() { + return labels; + } + // getter lib specific @Override @@ -303,6 +310,15 @@ public BuildImageCmd withShmsize(Long shmsize) { return this; } + /** + * @see #labels + */ + @Override + public BuildImageCmd withLabels(Map labels) { + this.labels = labels; + return this; + } + @Override public void close() { super.close(); diff --git a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java index 43e7687eb..2a7aea40e 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.net.URLEncoder; +import java.util.Map; public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec implements BuildImageCmd.Exec { @@ -99,19 +100,14 @@ protected AbstractCallbackNotifier callbackNotifier(BuildImag webTarget = webTarget.queryParam("rm", "false"); } - if (command.getBuildArgs() != null && !command.getBuildArgs().isEmpty()) { - try { - webTarget = webTarget.queryParam("buildargs", - URLEncoder.encode(MAPPER.writeValueAsString(command.getBuildArgs()), "UTF-8")); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + webTarget = writeMap(webTarget, "buildargs", command.getBuildArgs()); if (command.getShmsize() != null) { webTarget = webTarget.queryParam("shmsize", command.getShmsize()); } + webTarget = writeMap(webTarget, "labels", command.getLabels()); + webTarget.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED); webTarget.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024 * 1024); @@ -123,4 +119,17 @@ protected AbstractCallbackNotifier callbackNotifier(BuildImag entity(command.getTarInputStream(), "application/tar") ); } + + private WebTarget writeMap(WebTarget webTarget, String name, Map value) { + if (value != null && !value.isEmpty()) { + try { + return webTarget.queryParam(name, + URLEncoder.encode(MAPPER.writeValueAsString(value), "UTF-8")); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + return webTarget; + } + } } diff --git a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java index f4ff04576..43152570e 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java @@ -15,6 +15,7 @@ import com.github.dockerjava.netty.WebTarget; import java.io.IOException; +import java.util.Map; public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec implements BuildImageCmd.Exec { @@ -85,18 +86,14 @@ protected Void execute0(BuildImageCmd command, ResultCallback webTarget = webTarget.queryParam("cpusetcpus", command.getCpusetcpus()); } - if (command.getBuildArgs() != null && !command.getBuildArgs().isEmpty()) { - try { - webTarget = webTarget.queryParam("buildargs", MAPPER.writeValueAsString(command.getBuildArgs())); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + webTarget = writeMap(webTarget, "buildargs", command.getBuildArgs()); if (command.getShmsize() != null) { webTarget = webTarget.queryParam("shmsize", command.getShmsize()); } + webTarget = writeMap(webTarget, "labels", command.getLabels()); + LOGGER.trace("POST: {}", webTarget); InvocationBuilder builder = resourceWithOptionalAuthConfig(command, webTarget.request()) @@ -109,4 +106,16 @@ protected Void execute0(BuildImageCmd command, ResultCallback return null; } + + private WebTarget writeMap(WebTarget webTarget, String name, Map value) { + if (value != null && !value.isEmpty()) { + try { + return webTarget.queryParam(name, MAPPER.writeValueAsString(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + return webTarget; + } + } } diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index 31f3c3045..cb4c1b2a8 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.core.command; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -12,11 +13,13 @@ import java.io.InputStream; import java.lang.reflect.Method; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -33,6 +36,7 @@ import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.core.RemoteApiVersion; import com.github.dockerjava.core.util.CompressArchiveUtil; @Test(groups = "integration") @@ -250,6 +254,26 @@ public void buildArgs() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void labels() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("API version should be >= 1.23"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withLabels(Collections.singletonMap("test", "abc")) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index 1474ef25f..f567dcfc8 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.netty.exec; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -12,11 +13,13 @@ import java.io.InputStream; import java.lang.reflect.Method; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -34,6 +37,7 @@ import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; import com.github.dockerjava.api.model.Ports.Binding; +import com.github.dockerjava.core.RemoteApiVersion; import com.github.dockerjava.core.command.BuildImageResultCallback; import com.github.dockerjava.core.command.PushImageResultCallback; import com.github.dockerjava.core.command.WaitContainerResultCallback; @@ -255,6 +259,26 @@ public void buildArgs() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void labels() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("API version should be >= 1.23"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withLabels(Collections.singletonMap("test", "abc")) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); diff --git a/src/test/resources/buildTests/labels/Dockerfile b/src/test/resources/buildTests/labels/Dockerfile new file mode 100644 index 000000000..6a8106b86 --- /dev/null +++ b/src/test/resources/buildTests/labels/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:latest + +CMD ["echo", "Success"] From 1ec83d60ea4a30a6e22aa5620fa4ca01f8d23e21 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 29 Sep 2016 03:35:36 +0300 Subject: [PATCH 181/780] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 908c2d906..efbed07d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Change Log === -## Next +## Next 3.0.7 + * Label image during build ## 3.0.6 * Fixed issue with jersey and unix domain sockets. From 069987852c842e3bba85ed3325a8877c36f9e87f Mon Sep 17 00:00:00 2001 From: Christopher Dancy Date: Fri, 30 Sep 2016 13:39:51 -0400 Subject: [PATCH 182/780] Expose 'User' property on ExecCreateCmd (#707) (#708) * Expose 'User' property on ExecCreateCmd (#707) --- .../dockerjava/api/command/ExecCreateCmd.java | 5 +++ .../core/command/ExecCreateCmdImpl.java | 17 +++++++++ .../core/command/ExecCreateCmdImplTest.java | 2 +- .../core/command/ExecStartCmdImplTest.java | 37 ++++++++++++++----- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java b/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java index fe2329290..829ebf8ee 100644 --- a/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java @@ -20,6 +20,9 @@ public interface ExecCreateCmd extends SyncDockerCmd { @CheckForNull Boolean hasTtyEnabled(); + @CheckForNull + String getUser(); + ExecCreateCmd withAttachStderr(Boolean attachStderr); ExecCreateCmd withAttachStdin(Boolean attachStdin); @@ -32,6 +35,8 @@ public interface ExecCreateCmd extends SyncDockerCmd { ExecCreateCmd withTty(Boolean tty); + ExecCreateCmd withUser(String user); + interface Exec extends DockerCmdSyncExec { } diff --git a/src/main/java/com/github/dockerjava/core/command/ExecCreateCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/ExecCreateCmdImpl.java index 14da4626a..fc8bf1c0b 100644 --- a/src/main/java/com/github/dockerjava/core/command/ExecCreateCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/ExecCreateCmdImpl.java @@ -26,6 +26,12 @@ public class ExecCreateCmdImpl extends AbstrDockerCmd 0); } + + @Test(groups = "ignoreInCircleCi", expectedExceptions = NotFoundException.class) + public void execStartWithNonExistentUser() throws Exception { + String containerName = "generated_" + new SecureRandom().nextInt(); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999") + .withName(containerName).exec(); + LOG.info("Created container {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()) + .withAttachStdout(true).withCmd("touch", "/execStartTest.log").withUser("NonExistentUser").exec(); + dockerClient.execStartCmd(execCreateCmdResponse.getId()).withDetach(false).withTty(true) + .exec(new ExecStartResultCallback(System.out, System.err)).awaitCompletion(); + + dockerClient.copyArchiveFromContainerCmd(container.getId(), "/execStartTest.log").exec(); + } } From b3be4fb1b9cdf3c1cd6a7d30ac91fff2d2e31264 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 30 Sep 2016 21:32:07 +0300 Subject: [PATCH 183/780] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efbed07d8..8f41b2938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Change Log === ## Next 3.0.7 * Label image during build + * Expose 'User' property on ExecCreateCmd #707 #708 ## 3.0.6 * Fixed issue with jersey and unix domain sockets. From 5736b4bb235afab960866b0d0f18bb7aa7a3e527 Mon Sep 17 00:00:00 2001 From: Hendrik-H Date: Fri, 7 Oct 2016 22:33:51 +0200 Subject: [PATCH 184/780] Support volumes propagation flags (Issue 554) (#705) * Support nocopy option in volume binds (#688) * support volumes propagation flags, fixes #554 * renamed values to match java convention --- .../com/github/dockerjava/api/model/Bind.java | 54 ++++++++++++- .../dockerjava/api/model/PropagationMode.java | 50 ++++++++++++ .../github/dockerjava/api/model/BindTest.java | 79 +++++++++++++++++++ .../exec/CreateContainerCmdExecTest.java | 37 +++++++++ 4 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/api/model/PropagationMode.java diff --git a/src/main/java/com/github/dockerjava/api/model/Bind.java b/src/main/java/com/github/dockerjava/api/model/Bind.java index 0995c87ac..9a7ebf18d 100644 --- a/src/main/java/com/github/dockerjava/api/model/Bind.java +++ b/src/main/java/com/github/dockerjava/api/model/Bind.java @@ -18,24 +18,48 @@ public class Bind implements Serializable { private AccessMode accessMode; + /** + * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_23} + */ + private Boolean noCopy; + /** * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_17} */ private SELContext secMode; + /** + * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_22} + */ + private PropagationMode propagationMode; + public Bind(String path, Volume volume) { this(path, volume, AccessMode.DEFAULT, SELContext.DEFAULT); } + public Bind(String path, Volume volume, Boolean noCopy) { + this(path, volume, AccessMode.DEFAULT, SELContext.DEFAULT, noCopy); + } + public Bind(String path, Volume volume, AccessMode accessMode) { this(path, volume, accessMode, SELContext.DEFAULT); } public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMode) { + this(path, volume, accessMode, secMode, null); + } + + public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMode, Boolean noCopy) { + this(path, volume, accessMode, secMode, noCopy, PropagationMode.DEFAULT_MODE); + } + + public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMode, Boolean noCopy, PropagationMode propagationMode) { this.path = path; this.volume = volume; this.accessMode = accessMode; this.secMode = secMode; + this.noCopy = noCopy; + this.propagationMode = propagationMode; } public String getPath() { @@ -54,6 +78,14 @@ public SELContext getSecMode() { return secMode; } + public Boolean getNoCopy() { + return noCopy; + } + + public PropagationMode getPropagationMode() { + return propagationMode; + } + /** * Parses a bind mount specification to a {@link Bind}. * @@ -74,15 +106,25 @@ public static Bind parse(String serialized) { String[] flags = parts[2].split(","); AccessMode accessMode = AccessMode.DEFAULT; SELContext seMode = SELContext.DEFAULT; + Boolean nocopy = null; + PropagationMode propagationMode = PropagationMode.DEFAULT_MODE; for (String p : flags) { if (p.length() == 2) { accessMode = AccessMode.valueOf(p.toLowerCase()); + } else if ("nocopy".equals(p)) { + nocopy = true; + } else if (PropagationMode.SHARED.toString().equals(p)) { + propagationMode = PropagationMode.SHARED; + } else if (PropagationMode.SLAVE.toString().equals(p)) { + propagationMode = PropagationMode.SLAVE; + } else if (PropagationMode.PRIVATE.toString().equals(p)) { + propagationMode = PropagationMode.PRIVATE; } else { seMode = SELContext.fromString(p); } } - return new Bind(parts[0], new Volume(parts[1]), accessMode, seMode); + return new Bind(parts[0], new Volume(parts[1]), accessMode, seMode, nocopy, propagationMode); } default: { throw new IllegalArgumentException(); @@ -102,6 +144,8 @@ public boolean equals(Object obj) { .append(volume, other.getVolume()) .append(accessMode, other.getAccessMode()) .append(secMode, other.getSecMode()) + .append(noCopy, other.getNoCopy()) + .append(propagationMode, other.getPropagationMode()) .isEquals(); } else { return super.equals(obj); @@ -115,6 +159,8 @@ public int hashCode() { .append(volume) .append(accessMode) .append(secMode) + .append(noCopy) + .append(propagationMode) .toHashCode(); } @@ -127,10 +173,12 @@ public int hashCode() { */ @Override public String toString() { - return String.format("%s:%s:%s%s", + return String.format("%s:%s:%s%s%s%s", path, volume.getPath(), accessMode.toString(), - secMode != SELContext.none ? "," + secMode.toString() : ""); + secMode != SELContext.none ? "," + secMode.toString() : "", + noCopy != null ? ",nocopy" : "", + propagationMode != PropagationMode.DEFAULT_MODE ? "," + propagationMode.toString() : ""); } } diff --git a/src/main/java/com/github/dockerjava/api/model/PropagationMode.java b/src/main/java/com/github/dockerjava/api/model/PropagationMode.java new file mode 100644 index 000000000..9be7d6e43 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/PropagationMode.java @@ -0,0 +1,50 @@ +package com.github.dockerjava.api.model; + +/** + * The propagation mode of a file system or file: shared, slave or private. + * + * @see https://github.com/docker/docker/pull/17034 + * @since 1.22 + */ +public enum PropagationMode { + /** default */ + DEFAULT(""), + + /** shared */ + SHARED("shared"), + + /** slave */ + SLAVE("slave"), + + /** private */ + PRIVATE("private"); + + /** + * The default {@link PropagationMode}: {@link #DEFAULT} + */ + public static final PropagationMode DEFAULT_MODE = DEFAULT; + + private String value; + + PropagationMode(String v) { + value = v; + } + + @Override + public String toString() { + return value; + } + + public static PropagationMode fromString(String v) { + switch (v) { + case "shared": + return SHARED; + case "slave": + return SLAVE; + case "private": + return PRIVATE; + default: + return DEFAULT; + } + } +} diff --git a/src/test/java/com/github/dockerjava/api/model/BindTest.java b/src/test/java/com/github/dockerjava/api/model/BindTest.java index 3204ee716..2e6fd8353 100644 --- a/src/test/java/com/github/dockerjava/api/model/BindTest.java +++ b/src/test/java/com/github/dockerjava/api/model/BindTest.java @@ -3,6 +3,7 @@ import static com.github.dockerjava.api.model.AccessMode.ro; import static com.github.dockerjava.api.model.AccessMode.rw; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; import org.testng.annotations.Test; @@ -16,6 +17,8 @@ public void parseUsingDefaultAccessMode() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT)); assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); } @Test @@ -25,6 +28,52 @@ public void parseReadWrite() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(rw)); assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); + } + + @Test + public void parseReadWriteNoCopy() { + Bind bind = Bind.parse("/host:/container:rw,nocopy"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), is(true)); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); + } + + @Test + public void parseReadWriteShared() { + Bind bind = Bind.parse("/host:/container:rw,shared"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.SHARED)); + } + + @Test + public void parseReadWriteSlave() { + Bind bind = Bind.parse("/host:/container:rw,slave"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.SLAVE)); + } + + @Test + public void parseReadWritePrivate() { + Bind bind = Bind.parse("/host:/container:rw,private"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.PRIVATE)); } @Test @@ -34,6 +83,8 @@ public void parseReadOnly() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(ro)); assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); } @Test @@ -43,12 +94,16 @@ public void parseSELOnly() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT)); assertThat(bind.getSecMode(), is(SELContext.single)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); bind = Bind.parse("/host:/container:z"); assertThat(bind.getPath(), is("/host")); assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT)); assertThat(bind.getSecMode(), is(SELContext.shared)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); } @Test @@ -58,6 +113,8 @@ public void parseReadWriteSEL() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(rw)); assertThat(bind.getSecMode(), is(SELContext.single)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); } @Test @@ -67,6 +124,8 @@ public void parseReadOnlySEL() { assertThat(bind.getVolume().getPath(), is("/container")); assertThat(bind.getAccessMode(), is(ro)); assertThat(bind.getSecMode(), is(SELContext.shared)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT_MODE)); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing Bind.*") @@ -94,6 +153,26 @@ public void toStringReadWrite() { assertThat(Bind.parse("/host:/container:rw").toString(), is("/host:/container:rw")); } + @Test + public void toStringReadWriteNoCopy() { + assertThat(Bind.parse("/host:/container:rw,nocopy").toString(), is("/host:/container:rw,nocopy")); + } + + @Test + public void toStringReadWriteShared() { + assertThat(Bind.parse("/host:/container:rw,shared").toString(), is("/host:/container:rw,shared")); + } + + @Test + public void toStringReadWriteSlave() { + assertThat(Bind.parse("/host:/container:rw,slave").toString(), is("/host:/container:rw,slave")); + } + + @Test + public void toStringReadWritePrivate() { + assertThat(Bind.parse("/host:/container:rw,private").toString(), is("/host:/container:rw,private")); + } + @Test public void toStringDefaultAccessMode() { assertThat(Bind.parse("/host:/container").toString(), is("/host:/container:rw")); diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index 3694ca7fb..aa97b8839 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -2,6 +2,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.CreateNetworkResponse; +import com.github.dockerjava.api.command.CreateVolumeResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.exception.ConflictException; import com.github.dockerjava.api.exception.DockerException; @@ -15,6 +16,7 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.Ports; import com.github.dockerjava.api.model.Ports.Binding; +import com.github.dockerjava.core.RemoteApiVersion; import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.api.model.Ulimit; import com.github.dockerjava.api.model.Volume; @@ -23,6 +25,7 @@ import org.apache.commons.io.FileUtils; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -40,6 +43,7 @@ import static com.github.dockerjava.api.model.Capability.MKNOD; import static com.github.dockerjava.api.model.Capability.NET_ADMIN; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -138,6 +142,39 @@ public void createContainerWithReadOnlyVolume() throws DockerException { // assertFalse(inspectContainerResponse.getMounts().get(0).getRW()); } + @Test + public void createContainerWithNoCopyVolumes() throws DockerException { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("API version should be >= 1.23"); + } + + Volume volume1 = new Volume("/opt/webapp1"); + String container1Name = UUID.randomUUID().toString(); + + CreateVolumeResponse volumeResponse = dockerClient.createVolumeCmd().withName("webapp1").exec(); + assertThat(volumeResponse.getName(), equalTo("webapp1")); + assertThat(volumeResponse.getDriver(), equalTo("local")); + assertThat(volumeResponse.getMountpoint(), containsString("/webapp1/")); + + Bind bind1 = new Bind("webapp1", volume1, true); + + CreateContainerResponse container1 = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999") + .withName(container1Name) + .withBinds(bind1).exec(); + LOG.info("Created container1 {}", container1.toString()); + + InspectContainerResponse inspectContainerResponse1 = dockerClient.inspectContainerCmd(container1.getId()).exec(); + + assertThat(Arrays.asList(inspectContainerResponse1.getHostConfig().getBinds()), contains(bind1)); + assertThat(inspectContainerResponse1, mountedVolumes(contains(volume1))); + + assertThat(inspectContainerResponse1.getMounts().get(0).getDestination(), equalTo(volume1)); + assertThat(inspectContainerResponse1.getMounts().get(0).getMode(), equalTo("rw,nocopy")); + assertThat(inspectContainerResponse1.getMounts().get(0).getRW(), equalTo(true)); + } + @Test public void createContainerWithVolumesFrom() throws DockerException { From 6c748c61330cc996c78d5c294e40d98c8294e37e Mon Sep 17 00:00:00 2001 From: valerijf Date: Tue, 11 Oct 2016 13:23:26 +0200 Subject: [PATCH 185/780] Added getter for previous cpu stats --- .../github/dockerjava/api/model/Statistics.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/model/Statistics.java b/src/main/java/com/github/dockerjava/api/model/Statistics.java index cf8c1b77e..6827be4e8 100644 --- a/src/main/java/com/github/dockerjava/api/model/Statistics.java +++ b/src/main/java/com/github/dockerjava/api/model/Statistics.java @@ -46,6 +46,12 @@ public class Statistics implements Serializable { @JsonProperty("cpu_stats") private Map cpuStats; + /** + * @since Docker Remote API 1.19 + */ + @JsonProperty("precpu_stats") + private Map precpuStats; + /** * @since Docker Remote API 1.21 */ @@ -66,6 +72,14 @@ public Map getCpuStats() { return cpuStats; } + /** + * The cpu statistic of last read, which is used for calculating the cpu usage percent. + * It is not the exact copy of the {@link #getCpuStats()}. + */ + public Map getPreviousCpuStats() { + return precpuStats; + } + public Map getMemoryStats() { return memoryStats; } From 9d2c93e5eacf4807f5368d28c3277d85aa6bd546 Mon Sep 17 00:00:00 2001 From: valerijf Date: Fri, 14 Oct 2016 09:49:01 +0200 Subject: [PATCH 186/780] Renamed getter as field --- src/main/java/com/github/dockerjava/api/model/Statistics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/api/model/Statistics.java b/src/main/java/com/github/dockerjava/api/model/Statistics.java index 6827be4e8..9307da6b3 100644 --- a/src/main/java/com/github/dockerjava/api/model/Statistics.java +++ b/src/main/java/com/github/dockerjava/api/model/Statistics.java @@ -76,7 +76,7 @@ public Map getCpuStats() { * The cpu statistic of last read, which is used for calculating the cpu usage percent. * It is not the exact copy of the {@link #getCpuStats()}. */ - public Map getPreviousCpuStats() { + public Map getPrecpuStats() { return precpuStats; } From 75e9a2cd3d1bf1489f7a94fd9dc8d624359fa430 Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 27 Oct 2016 20:09:07 +0200 Subject: [PATCH 187/780] Expose netty connect timeout (#725) --- .../netty/NettyDockerCmdExecFactory.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java index cead92e92..c91d4af21 100644 --- a/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java @@ -108,6 +108,9 @@ import com.github.dockerjava.netty.exec.RenameContainerCmdExec; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelFactory; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollDomainSocketChannel; @@ -178,6 +181,8 @@ public DuplexChannel getChannel() { } }; + private Integer connectTimeout = null; + @Override public void init(DockerClientConfig dockerClientConfig) { checkNotNull(dockerClientConfig, "config was not specified"); @@ -218,7 +223,15 @@ private class UnixDomainSocketInitializer implements NettyInitializer { @Override public EventLoopGroup init(Bootstrap bootstrap, DockerClientConfig dockerClientConfig) { EventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(0, new DefaultThreadFactory(threadPrefix)); - bootstrap.group(epollEventLoopGroup).channel(EpollDomainSocketChannel.class) + + ChannelFactory factory = new ChannelFactory() { + @Override + public EpollDomainSocketChannel newChannel() { + return configure(new EpollDomainSocketChannel()); + } + }; + + bootstrap.group(epollEventLoopGroup).channelFactory(factory) .handler(new ChannelInitializer() { @Override protected void initChannel(final UnixChannel channel) throws Exception { @@ -245,7 +258,14 @@ public EventLoopGroup init(Bootstrap bootstrap, final DockerClientConfig dockerC Security.addProvider(new BouncyCastleProvider()); - bootstrap.group(nioEventLoopGroup).channel(NioSocketChannel.class) + ChannelFactory factory = new ChannelFactory() { + @Override + public NioSocketChannel newChannel() { + return configure(new NioSocketChannel()); + } + }; + + bootstrap.group(nioEventLoopGroup).channelFactory(factory) .handler(new ChannelInitializer() { @Override protected void initChannel(final SocketChannel channel) throws Exception { @@ -580,6 +600,24 @@ public void close() throws IOException { eventLoopGroup.shutdownGracefully(); } + /** + * Configure connection timeout in milliseconds + */ + public NettyDockerCmdExecFactory withConnectTimeout(Integer connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + private T configure(T channel) { + ChannelConfig channelConfig = channel.config(); + + if (connectTimeout != null) { + channelConfig.setConnectTimeoutMillis(connectTimeout); + } + + return channel; + } + private WebTarget getBaseResource() { return new WebTarget(channelProvider); } From 39ef5d14bb7a6b217bba97525585fac08be39d00 Mon Sep 17 00:00:00 2001 From: Matt Fulgo Date: Wed, 2 Nov 2016 09:55:49 -0400 Subject: [PATCH 188/780] Fixes broken Docker documentation link The official Docker documentation has moved around a bit and the link for how to configure the Docker Engine needed to be updated. The previous link pointed to a page that no longer exists. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 039657807..c2fa5d854 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ client also uses UNIX domain sockets to connect to the docker daemon by default. DOCKER_OPTS="-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock" -More details about setting up Docker server can be found in official documentation: http://docs.docker.io/en/latest/use/basics/ +More details about setting up Docker Engine can be found in the official documentation: https://docs.docker.com/engine/admin/ To force docker-java to use TCP (http) configure the following (see [Configuration](https://github.com/docker-java/docker-java#configuration) for details): From 49b94f6fd6fd6f59c45138698051047e82719dd8 Mon Sep 17 00:00:00 2001 From: ooxi Date: Fri, 25 Nov 2016 08:32:41 +0100 Subject: [PATCH 189/780] Add javadoc for `saveImageCmd' Maybe we can automatically copy the documentation from `SaveImageCmd.withName`, but I don't know how. --- src/main/java/com/github/dockerjava/api/DockerClient.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index 832890e87..8f35fac12 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -111,6 +111,10 @@ public interface DockerClient extends Closeable { InspectImageCmd inspectImageCmd(@Nonnull String imageId); + /** + * @param name + * The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null. + */ SaveImageCmd saveImageCmd(@Nonnull String name); /** From 3c04924a2deb4419bf6d987ed615bec88e7ed4f4 Mon Sep 17 00:00:00 2001 From: ooxi Date: Fri, 25 Nov 2016 08:36:37 +0100 Subject: [PATCH 190/780] Fixed Docker Remote API link (#747) File was moved in docker repository. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 039657807..79bad7fa9 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ For secure tls (https) communication: DOCKER_CERT_PATH=/Users/marcus/.docker/machine/machines/docker-1.11.2 ### Latest release version -Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.23.md), Docker Server version 1.11.x +Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/api/v1.23.md), Docker Server version 1.11.x com.github.docker-java @@ -60,7 +60,7 @@ Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/doc ### Latest development version -Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.23.md), Docker Server version 1.11.x +Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/docker/blob/master/docs/api/v1.23.md), Docker Server version 1.11.x You can find the latest development version including javadoc and source files on [Sonatypes OSS repository](https://oss.sonatype.org/content/groups/public/com/github/docker-java/docker-java/). From 15aa30eaa6ed5c40dbbe1ef4dc3e4a4caeb867ec Mon Sep 17 00:00:00 2001 From: ooxi Date: Fri, 25 Nov 2016 08:37:28 +0100 Subject: [PATCH 191/780] Fix Maven package version (#748) Version `3.0.6` was released, current snapshot is `3.0.7-SNAPSHOT` --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79bad7fa9..d5052e6b9 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Supports a subset of the Docker Remote API [v1.23](https://github.com/docker/doc com.github.docker-java docker-java - 3.0.3 + 3.0.6 ### Latest development version @@ -67,7 +67,7 @@ You can find the latest development version including javadoc and source files o com.github.docker-java docker-java - 3.0.4-SNAPSHOT + 3.0.7-SNAPSHOT From 259b7d638e20781c3085e679176f34b1c5d92c89 Mon Sep 17 00:00:00 2001 From: Raffael Stein Date: Wed, 4 Jan 2017 10:22:03 +0100 Subject: [PATCH 192/780] Clone system properties on access in default config --- .../com/github/dockerjava/core/DefaultDockerClientConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java index a9a15bb36..9d13ec71e 100644 --- a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -188,7 +188,7 @@ private static Properties overrideDockerPropertiesWithSystemProperties(Propertie } public static Builder createDefaultConfigBuilder() { - return createDefaultConfigBuilder(System.getenv(), System.getProperties()); + return createDefaultConfigBuilder(System.getenv(), (Properties) System.getProperties().clone()); } /** From 5ba770cf010271632980029f73856081f45b7ef0 Mon Sep 17 00:00:00 2001 From: Aboubacar Toure Date: Thu, 12 Jan 2017 02:15:33 -0500 Subject: [PATCH 193/780] Add support for private docker registry version 2 (#756) Private docker registry version 1 expects the authentication credentials in $DOCKER_HOME/.dockercfg while version 2 expects them in $DOCKER_HOME/config.json. Support for both paths should be added to make docker-java more portable. This pull request has the following modifications: * When resolving the path of the authentication configuration file, $DOCKER_HOME/config.json (v2) is tried before $DOCKER_HOME/.dockercfg (v1) * When parsing the content of the authentication configuration file, the format of config.json (v2) is tried before .dockercfg (v1) * Test for both config.json (v2) and dockercfg (v1) have been added --- .../dockerjava/core/AuthConfigFile.java | 30 ++++++++++++--- .../core/DefaultDockerClientConfig.java | 30 ++++++++++++--- .../core/DefaultDockerClientConfigTest.java | 37 +++++++++++++++++++ .../registry.v1/.dockercfg | 5 +++ .../registry.v2/config.json | 7 ++++ 5 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/com.github.dockerjava.core/registry.v1/.dockercfg create mode 100644 src/test/resources/com.github.dockerjava.core/registry.v2/config.json diff --git a/src/main/java/com/github/dockerjava/core/AuthConfigFile.java b/src/main/java/com/github/dockerjava/core/AuthConfigFile.java index f796fd7c9..539ac7f75 100644 --- a/src/main/java/com/github/dockerjava/core/AuthConfigFile.java +++ b/src/main/java/com/github/dockerjava/core/AuthConfigFile.java @@ -19,8 +19,13 @@ public class AuthConfigFile { private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final TypeReference> CONFIG_MAP_TYPE = new TypeReference>() { - }; + private static final TypeReference> CONFIG_CFG_MAP_TYPE = + new TypeReference>() { + }; + + private static final TypeReference>> CONFIG_JSON_MAP_TYPE = + new TypeReference>>() { + }; private final Map authConfigMap; @@ -101,12 +106,27 @@ public static AuthConfigFile loadConfig(File confFile) throws IOException { if (!confFile.exists()) { return new AuthConfigFile(); } + Map configMap = null; + /* + Registry v2 expects config expects config.json while v2 expects .dockercfg + The only difference between them is that config.json wraps "auths" around the AuthConfig + */ try { - configMap = MAPPER.readValue(confFile, CONFIG_MAP_TYPE); - } catch (IOException e) { - // pass + // try registry version 2 + Map> configJson = MAPPER.readValue(confFile, CONFIG_JSON_MAP_TYPE); + if (configJson != null) { + configMap = configJson.get("auths"); + } + } catch (IOException e1) { + try { + // try registry version 1 + configMap = MAPPER.readValue(confFile, CONFIG_CFG_MAP_TYPE); + } catch (IOException e2) { + // pass + } } + if (configMap != null) { for (Map.Entry entry : configMap.entrySet()) { AuthConfig authConfig = entry.getValue(); diff --git a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java index 9d13ec71e..5857227ae 100644 --- a/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -9,6 +9,9 @@ import java.io.InputStream; import java.io.Serializable; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashSet; import java.util.Map; import java.util.Properties; @@ -55,6 +58,8 @@ public class DefaultDockerClientConfig implements Serializable, DockerClientConf private static final String DOCKER_CFG = ".dockercfg"; + private static final String CONFIG_JSON = "config.json"; + private static final Set CONFIG_KEYS = new HashSet(); static { @@ -253,9 +258,9 @@ && getRegistryUrl() != null) { public AuthConfig effectiveAuthConfig(String imageName) { AuthConfig authConfig = null; - File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); + File dockerCfgFile = getDockerConfigFile(); - if (dockerCfgFile.exists() && dockerCfgFile.isFile() && imageName != null) { + if (dockerCfgFile != null) { AuthConfigFile authConfigFile; try { authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); @@ -279,13 +284,15 @@ public AuthConfig effectiveAuthConfig(String imageName) { @Override public AuthConfigurations getAuthConfigurations() { - File dockerCfgFile = new File(getDockerConfig() + File.separator + DOCKER_CFG); - if (dockerCfgFile.exists() && dockerCfgFile.isFile()) { + File dockerCfgFile = getDockerConfigFile(); + + if (dockerCfgFile != null) { AuthConfigFile authConfigFile; try { authConfigFile = AuthConfigFile.loadConfig(dockerCfgFile); } catch (IOException e) { - throw new DockerClientException("Failed to parse dockerCfgFile", e); + throw new DockerClientException("Failed to parse dockerCfgFile: " + + dockerCfgFile.getAbsolutePath(), e); } return authConfigFile.getAuthConfigurations(); @@ -294,6 +301,19 @@ public AuthConfigurations getAuthConfigurations() { return new AuthConfigurations(); } + private File getDockerConfigFile() { + final Path configJson = Paths.get(getDockerConfig(), CONFIG_JSON); + final Path dockerCfg = Paths.get(getDockerConfig(), DOCKER_CFG); + + if (Files.exists(configJson)) { + return configJson.toFile(); + } else if (Files.exists(dockerCfg)) { + return dockerCfg.toFile(); + } else { + return null; + } + } + @Override public SSLConfig getSSLConfig() { return sslConfig; diff --git a/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java index 54e70c511..3a4238b22 100644 --- a/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java @@ -2,12 +2,15 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.core.Is.is; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; +import java.io.File; import java.lang.reflect.Field; import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -18,6 +21,8 @@ import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.api.model.AuthConfigurations; +import com.google.common.io.Resources; public class DefaultDockerClientConfigTest { @@ -201,4 +206,36 @@ public void withDockerTlsVerify() throws Exception { assertThat((Boolean) field.get(builder), is(true)); } + @Test + public void testGetAuthConfigurationsFromDockerCfg() throws URISyntaxException { + File cfgFile = new File(Resources.getResource("com.github.dockerjava.core/registry.v1").toURI()); + DefaultDockerClientConfig clientConfig = new DefaultDockerClientConfig(URI.create( + "unix://foo"), cfgFile.getAbsolutePath(), "apiVersion", "registryUrl", "registryUsername", "registryPassword", + "registryEmail", null); + + AuthConfigurations authConfigurations = clientConfig.getAuthConfigurations(); + assertThat(authConfigurations, notNullValue()); + assertThat(authConfigurations.getConfigs().get("https://test.docker.io/v1/"), notNullValue()); + + AuthConfig authConfig = authConfigurations.getConfigs().get("https://test.docker.io/v1/"); + assertThat(authConfig.getUsername(), equalTo("user")); + assertThat(authConfig.getPassword(), equalTo("password")); + } + + @Test + public void testGetAuthConfigurationsFromConfigJson() throws URISyntaxException { + File cfgFile = new File(Resources.getResource("com.github.dockerjava.core/registry.v2").toURI()); + DefaultDockerClientConfig clientConfig = new DefaultDockerClientConfig(URI.create( + "unix://foo"), cfgFile.getAbsolutePath(), "apiVersion", "registryUrl", "registryUsername", "registryPassword", + "registryEmail", null); + + AuthConfigurations authConfigurations = clientConfig.getAuthConfigurations(); + assertThat(authConfigurations, notNullValue()); + assertThat(authConfigurations.getConfigs().get("https://test.docker.io/v2/"), notNullValue()); + + AuthConfig authConfig = authConfigurations.getConfigs().get("https://test.docker.io/v2/"); + assertThat(authConfig.getUsername(), equalTo("user")); + assertThat(authConfig.getPassword(), equalTo("password")); + } + } diff --git a/src/test/resources/com.github.dockerjava.core/registry.v1/.dockercfg b/src/test/resources/com.github.dockerjava.core/registry.v1/.dockercfg new file mode 100644 index 000000000..3ab173fba --- /dev/null +++ b/src/test/resources/com.github.dockerjava.core/registry.v1/.dockercfg @@ -0,0 +1,5 @@ +{ + "https://test.docker.io/v1/": { + "auth": "dXNlcjpwYXNzd29yZA==" + } +} diff --git a/src/test/resources/com.github.dockerjava.core/registry.v2/config.json b/src/test/resources/com.github.dockerjava.core/registry.v2/config.json new file mode 100644 index 000000000..73ab82aca --- /dev/null +++ b/src/test/resources/com.github.dockerjava.core/registry.v2/config.json @@ -0,0 +1,7 @@ +{ + "auths": { + "https://test.docker.io/v2/": { + "auth": "dXNlcjpwYXNzd29yZA==" + } + } +} From 5b8ed07cfbbd409cad344ffc7d21c905cd2d4886 Mon Sep 17 00:00:00 2001 From: Logan O'Sullivan Bruns Date: Fri, 13 Jan 2017 14:09:13 -0800 Subject: [PATCH 194/780] Issue 674: 3.0.x switch from docker host using https|http scheme to tcp breaks proxy configure (#675) https://github.com/docker-java/docker-java/issues/674 With the 3.0.x release, the code has been changed to use docker hosts of the format: tcp://host:port Instead of: https://host:port This breaks some of the logic in JerseyDockerCmdExecFactory that configures the proxy setting. --- .../github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java index 73bab979e..4b7f2f67e 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java @@ -190,7 +190,7 @@ public void init(DockerClientConfig dockerClientConfig) { throw new RuntimeException(e); } - configureProxy(clientConfig, protocol); + configureProxy(clientConfig, originalUri, protocol); } connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry( @@ -241,9 +241,9 @@ private URI sanitizeUrl(URI originalUri) { return originalUri; } - private void configureProxy(ClientConfig clientConfig, String protocol) { + private void configureProxy(ClientConfig clientConfig, URI originalUri, String protocol) { - List proxies = ProxySelector.getDefault().select(dockerClientConfig.getDockerHost()); + List proxies = ProxySelector.getDefault().select(originalUri); for (Proxy proxy : proxies) { InetSocketAddress address = (InetSocketAddress) proxy.address(); From 3ad75e0870a35ac166a0e1cb33a636e152cc0dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sekunda?= Date: Tue, 17 Jan 2017 19:43:50 +0100 Subject: [PATCH 195/780] add support for PidsLimit #734 (#764) * add support for PidsLimit #734 * add support for PidsLimit #734 - using hamcrest in assertions * add support for PidsLimit #734 - remove proxing * add support for PidsLimit #734 - remove proxing * add support for PidsLimit #734 - formatting fixed --- .../dockerjava/api/model/HostConfig.java | 22 +++++++++++++++ .../command/CreateContainerCmdImplTest.java | 28 +++++++++++++++++-- .../exec/CreateContainerCmdExecTest.java | 25 +++++++++++++++-- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/HostConfig.java b/src/main/java/com/github/dockerjava/api/model/HostConfig.java index 062082a03..d808ef245 100644 --- a/src/main/java/com/github/dockerjava/api/model/HostConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/HostConfig.java @@ -194,6 +194,12 @@ public class HostConfig implements Serializable { @JsonProperty("ShmSize") private Long shmSize; + /** + * @since ~{@link RemoteApiVersion#VERSION_1_23} + */ + @JsonProperty("PidsLimit") + private Long pidsLimit; + @JsonIgnore public Bind[] getBinds() { @@ -415,6 +421,14 @@ public String getVolumeDriver() { return volumeDriver; } + /** + * @see #pidsLimit + */ + @CheckForNull + public Long getPidsLimit() { + return pidsLimit; + } + /** * Parse the network mode as specified at * {@see https://github.com/docker/engine-api/blob/master/types/container/hostconfig_unix.go} @@ -794,6 +808,14 @@ public HostConfig withVolumesFrom(VolumesFrom[] volumesFrom) { this.volumesFrom = volumesFrom; return this; } + + /** + * @see #pidsLimit + */ + public HostConfig withPidsLimit(Long pidsLimit) { + this.pidsLimit = pidsLimit; + return this; + } // end of auto-generated @Override diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 1f62527e9..7c625ea94 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -22,8 +22,10 @@ import com.github.dockerjava.api.model.Ports.Binding; import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.core.RemoteApiVersion; import org.apache.commons.io.FileUtils; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -34,7 +36,6 @@ import java.lang.reflect.Method; import java.security.SecureRandom; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -42,6 +43,7 @@ import static com.github.dockerjava.api.model.Capability.MKNOD; import static com.github.dockerjava.api.model.Capability.NET_ADMIN; +import static com.github.dockerjava.utils.TestUtils.getVersion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -751,6 +753,28 @@ public void createContainerWithShmSize() throws DockerException { InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - assertEquals(inspectContainerResponse.getHostConfig().getShmSize(), hostConfig.getShmSize()); + assertThat(inspectContainerResponse.getHostConfig().getShmSize(), is(hostConfig.getShmSize())); + } + + @SuppressWarnings("Duplicates") + @Test + public void createContainerWithShmPidsLimit() throws DockerException { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("API version should be >= 1.23"); + } + + HostConfig hostConfig = new HostConfig().withPidsLimit(2L); + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withHostConfig(hostConfig).withCmd("true").exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + assertThat(inspectContainerResponse.getHostConfig().getPidsLimit(), is(hostConfig.getPidsLimit())); } } diff --git a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java index aa97b8839..ab2bd36a0 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CreateContainerCmdExecTest.java @@ -36,7 +36,6 @@ import java.lang.reflect.Method; import java.security.SecureRandom; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -729,6 +728,28 @@ public void createContainerWithShmSize() throws DockerException { InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - assertEquals(inspectContainerResponse.getHostConfig().getShmSize(), hostConfig.getShmSize()); + assertThat(inspectContainerResponse.getHostConfig().getShmSize(), is(hostConfig.getShmSize())); + } + + @SuppressWarnings("Duplicates") + @Test + public void createContainerWithShmPidsLimit() throws DockerException { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("API version should be >= 1.23"); + } + + HostConfig hostConfig = new HostConfig().withPidsLimit(2L); + CreateContainerResponse container = dockerClient.createContainerCmd(BUSYBOX_IMAGE) + .withHostConfig(hostConfig).withCmd("true").exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + assertThat(inspectContainerResponse.getHostConfig().getPidsLimit(), is(hostConfig.getPidsLimit())); } } From cccc1b6da7af0ba3fe470389478ccee7339ba4b3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 18 Jan 2017 03:29:07 +0300 Subject: [PATCH 196/780] [maven-release-plugin] prepare release 3.0.7 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 216c48631..609059f0b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.7-SNAPSHOT + 3.0.7 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.7 From 15c61b33a3dd4b197fd8b1afe7fcb077b2a08b50 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 18 Jan 2017 03:29:17 +0300 Subject: [PATCH 197/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 609059f0b..852ad8283 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.7 + 3.0.8-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.7 + HEAD From b465546f7300819103b6c614b6680e5ecf0d1fff Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 18 Jan 2017 03:45:30 +0300 Subject: [PATCH 198/780] 3.0.7 release link to milestone --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f41b2938..ca927c2c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Change Log === -## Next 3.0.7 +## (dev) 3.1.0 (reserverd for swarm features) + +## next... + +## 3.0.7 + * https://github.com/docker-java/docker-java/milestone/17?closed=1 + * HostConfig pidLimits * Label image during build * Expose 'User' property on ExecCreateCmd #707 #708 From c49f598fb0ee79a4a3b463312da4aab1b55d3050 Mon Sep 17 00:00:00 2001 From: Sukhanov Stas Date: Wed, 25 Jan 2017 22:33:49 +0500 Subject: [PATCH 199/780] Add support for multiple certificates in ca.pem file A single PEM file can contain a number of certificates. Usually keys and certificates are split into different files, but ca.pem still can contain several certificates in some cases. --- .../core/util/CertificateUtils.java | 21 +++++--- .../core/util/CertificateUtilsTest.java | 40 +++++++++++++++ .../caTest/multiple_ca.pem | 50 +++++++++++++++++++ .../CertificateUtilsTest/caTest/single_ca.pem | 25 ++++++++++ 4 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/multiple_ca.pem create mode 100644 src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/single_ca.pem diff --git a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java index b5a5dcae6..63e66952d 100644 --- a/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java +++ b/src/main/java/com/github/dockerjava/core/util/CertificateUtils.java @@ -18,11 +18,11 @@ import java.util.List; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.slf4j.Logger; @@ -88,7 +88,8 @@ public static List loadCertificates(final Reader reader) throws IOE try (PEMParser pemParser = new PEMParser(reader)) { List certificates = new ArrayList<>(); - JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter().setProvider("BC"); + JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter() + .setProvider(BouncyCastleProvider.PROVIDER_NAME); Object certObj = pemParser.readObject(); if (certObj instanceof X509CertificateHolder) { @@ -181,14 +182,20 @@ public static KeyStore createTrustStore(String capem) throws IOException, Certif public static KeyStore createTrustStore(final Reader certReader) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { try (PEMParser pemParser = new PEMParser(certReader)) { - X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject(); - Certificate caCertificate = new JcaX509CertificateConverter() - .setProvider("BC") - .getCertificate(certificateHolder); KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(null); - trustStore.setCertificateEntry("ca", caCertificate); + + int index = 1; + Object pemCert; + + while ((pemCert = pemParser.readObject()) != null) { + Certificate caCertificate = new JcaX509CertificateConverter() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .getCertificate((X509CertificateHolder) pemCert); + trustStore.setCertificateEntry("ca-" + index, caCertificate); + index++; + } return trustStore; } diff --git a/src/test/java/com/github/dockerjava/core/util/CertificateUtilsTest.java b/src/test/java/com/github/dockerjava/core/util/CertificateUtilsTest.java index 36c00c076..9c7120d1f 100644 --- a/src/test/java/com/github/dockerjava/core/util/CertificateUtilsTest.java +++ b/src/test/java/com/github/dockerjava/core/util/CertificateUtilsTest.java @@ -1,5 +1,14 @@ package com.github.dockerjava.core.util; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.Security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -9,6 +18,16 @@ public class CertificateUtilsTest { private static final String baseDir = CertificateUtilsTest.class.getResource( CertificateUtilsTest.class.getSimpleName() + "/").getFile(); + @BeforeClass + public static void init() { + Security.addProvider(new BouncyCastleProvider()); + } + + @AfterClass + public static void tearDown() { + Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); + } + @Test public void allFilesExist() { assertThat(CertificateUtils.verifyCertificatesExist(baseDir + "allFilesExist"), is(true)); @@ -48,4 +67,25 @@ public void certMissing() { public void keyMissing() { assertThat(CertificateUtils.verifyCertificatesExist(baseDir + "keyMissing"), is(false)); } + + @Test + public void readCaCert() throws Exception { + String capem = readFileAsString("caTest/single_ca.pem"); + KeyStore keyStore = CertificateUtils.createTrustStore(capem); + assertThat(keyStore.size(), is(1)); + assertThat(keyStore.isCertificateEntry("ca-1"), is(true)); + } + + @Test + public void readMultipleCaCerts() throws Exception { + String capem = readFileAsString("caTest/multiple_ca.pem"); + KeyStore keyStore = CertificateUtils.createTrustStore(capem); + assertThat(keyStore.size(), is(2)); + assertThat(keyStore.isCertificateEntry("ca-1"), is(true)); + assertThat(keyStore.isCertificateEntry("ca-2"), is(true)); + } + + private String readFileAsString(String path) throws IOException { + return new String(Files.readAllBytes(Paths.get(baseDir + path))); + } } diff --git a/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/multiple_ca.pem b/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/multiple_ca.pem new file mode 100644 index 000000000..53b571269 --- /dev/null +++ b/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/multiple_ca.pem @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIJALOOFdRswGmDMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMTA0NBMTEaMBgGCSqGSIb3DQEJARYLY2FA +dGVzdC5jb20wHhcNMTcwMTI1MTc0ODE5WhcNMjcwMTIzMTc0ODE5WjBvMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQg +V2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDEwNDQTExGjAYBgkqhkiG9w0BCQEWC2Nh +QHRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA346h3pA5 +5Uu6t7I8oNsiwF9PNgY7FKL/fXAiGAi1GMcPvil5Sf+GOYenQNsh4unfMRu8C+Xn +0NSnQNRkgJ2eIR5w3qDDK+UFj34rLdBK+wNze3gMGOaTFiSZLeoxrXs6fGbJ7Jmd +GaW7u8+P1+1Iej2k7lz61SXRL7+fn5lo3Lpfi+7s44zzOHoPkbHYNyl3md5Wgsoc +U+VGcABl1cq956ycQU1/jWZgclaTL3sQjNvLJ+dnN4+IwbFiPE9tY+cJtdNn2YXd +jLqxkfr/MZXoxArASanzPa4S7sKl8nnGrYM8cnppMeFk2a/p1YT+507V6VEmLM1A +IlqtzOAWpZ4vSQIDAQABo4HUMIHRMB0GA1UdDgQWBBRTvtGtQ298/2Ukc6ncXNUI +plkkxjCBoQYDVR0jBIGZMIGWgBRTvtGtQ298/2Ukc6ncXNUIplkkxqFzpHEwbzEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVy +bmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAxMDQ0ExMRowGAYJKoZIhvcNAQkB +FgtjYUB0ZXN0LmNvbYIJALOOFdRswGmDMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQEFBQADggEBAIs8PjXPWvTWVDQ8xsZHLosD5BzCqM6ac+W7pjKEVNaiIo+UT3st +bl1rZS2U924M9xtOkmAOPCQx1ozMxqKk2SVYztll3/Nw7p3qbP2/7L1tOTjoNZqT +o2dd4Jf8txj9AaDus9FW8gmR6TLSgm7xeNb/kEa1b5ZW6l0zYRSBNT4I38d9wCa4 +QeohD8t1T1QOSc82dTHqccSiCSRiOX883I/fK+cTo8o1gdyUjYoCQlsJESr1rUun +C3zMTZ4Lkt72vM88Hf0OyK/+sw7sqVEf+95VMx+a/UaYYkJY3Bg6JTJb9vukbtAl +5GrDZOGM1AgW8iZyG/jSJlwkjiB9vy8RRnI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIJAL4WwpOexcT8MA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMTA0NBMjEaMBgGCSqGSIb3DQEJARYLY2FA +dGVzdC5jb20wHhcNMTcwMTI1MTc0ODQ4WhcNMjcwMTIzMTc0ODQ4WjBvMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQg +V2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDEwNDQTIxGjAYBgkqhkiG9w0BCQEWC2Nh +QHRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA346h3pA5 +5Uu6t7I8oNsiwF9PNgY7FKL/fXAiGAi1GMcPvil5Sf+GOYenQNsh4unfMRu8C+Xn +0NSnQNRkgJ2eIR5w3qDDK+UFj34rLdBK+wNze3gMGOaTFiSZLeoxrXs6fGbJ7Jmd +GaW7u8+P1+1Iej2k7lz61SXRL7+fn5lo3Lpfi+7s44zzOHoPkbHYNyl3md5Wgsoc +U+VGcABl1cq956ycQU1/jWZgclaTL3sQjNvLJ+dnN4+IwbFiPE9tY+cJtdNn2YXd +jLqxkfr/MZXoxArASanzPa4S7sKl8nnGrYM8cnppMeFk2a/p1YT+507V6VEmLM1A +IlqtzOAWpZ4vSQIDAQABo4HUMIHRMB0GA1UdDgQWBBRTvtGtQ298/2Ukc6ncXNUI +plkkxjCBoQYDVR0jBIGZMIGWgBRTvtGtQ298/2Ukc6ncXNUIplkkxqFzpHEwbzEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVy +bmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAxMDQ0EyMRowGAYJKoZIhvcNAQkB +FgtjYUB0ZXN0LmNvbYIJAL4WwpOexcT8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQEFBQADggEBAKVIxgBQ76JQYfejcaK946J6VglSKaHuPZ8bDVM9e2KB1HFwTzAA +oRtMBIJaSO1+CSopTnzvzv/j8XeXbAUt6UHWiejGcIke1wW1CSVHeDQM7KUzXYtu +2jWzlGHXtnni4EeSwdE628Kfk82r/NU3+3+zo/3ASkYcSGBEYgIdvLBmbvQ8sviJ +rQZ1HCDP/TgP/ExBDi2QWBHe3XSTD0pBK153FC2YT1Q0AG5mxsIeq7C85m22aNX9 +fUmG5ORnVMkT/ktY+jg5aP+50o58MX24ZG1mh59vZtuBbvD74qZ2eNauStt1ji34 +V43XhW5Bigsp/z7GyFb2VzejH9n+VvPmTnU= +-----END CERTIFICATE----- diff --git a/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/single_ca.pem b/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/single_ca.pem new file mode 100644 index 000000000..8e67cb783 --- /dev/null +++ b/src/test/resources/com/github/dockerjava/core/util/CertificateUtilsTest/caTest/single_ca.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIJAL4WwpOexcT8MA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMTA0NBMjEaMBgGCSqGSIb3DQEJARYLY2FA +dGVzdC5jb20wHhcNMTcwMTI1MTc0ODQ4WhcNMjcwMTIzMTc0ODQ4WjBvMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQg +V2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDEwNDQTIxGjAYBgkqhkiG9w0BCQEWC2Nh +QHRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA346h3pA5 +5Uu6t7I8oNsiwF9PNgY7FKL/fXAiGAi1GMcPvil5Sf+GOYenQNsh4unfMRu8C+Xn +0NSnQNRkgJ2eIR5w3qDDK+UFj34rLdBK+wNze3gMGOaTFiSZLeoxrXs6fGbJ7Jmd +GaW7u8+P1+1Iej2k7lz61SXRL7+fn5lo3Lpfi+7s44zzOHoPkbHYNyl3md5Wgsoc +U+VGcABl1cq956ycQU1/jWZgclaTL3sQjNvLJ+dnN4+IwbFiPE9tY+cJtdNn2YXd +jLqxkfr/MZXoxArASanzPa4S7sKl8nnGrYM8cnppMeFk2a/p1YT+507V6VEmLM1A +IlqtzOAWpZ4vSQIDAQABo4HUMIHRMB0GA1UdDgQWBBRTvtGtQ298/2Ukc6ncXNUI +plkkxjCBoQYDVR0jBIGZMIGWgBRTvtGtQ298/2Ukc6ncXNUIplkkxqFzpHEwbzEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVy +bmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAxMDQ0EyMRowGAYJKoZIhvcNAQkB +FgtjYUB0ZXN0LmNvbYIJAL4WwpOexcT8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQEFBQADggEBAKVIxgBQ76JQYfejcaK946J6VglSKaHuPZ8bDVM9e2KB1HFwTzAA +oRtMBIJaSO1+CSopTnzvzv/j8XeXbAUt6UHWiejGcIke1wW1CSVHeDQM7KUzXYtu +2jWzlGHXtnni4EeSwdE628Kfk82r/NU3+3+zo/3ASkYcSGBEYgIdvLBmbvQ8sviJ +rQZ1HCDP/TgP/ExBDi2QWBHe3XSTD0pBK153FC2YT1Q0AG5mxsIeq7C85m22aNX9 +fUmG5ORnVMkT/ktY+jg5aP+50o58MX24ZG1mh59vZtuBbvD74qZ2eNauStt1ji34 +V43XhW5Bigsp/z7GyFb2VzejH9n+VvPmTnU= +-----END CERTIFICATE----- From 5d00d5e75c4e2a79b5f5ca2bfaccfbde39b8a15d Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 14 Feb 2017 00:08:26 +0300 Subject: [PATCH 200/780] Disable failing tests. --- .../dockerjava/core/command/AuthCmdImplTest.java | 10 ++++++++++ .../dockerjava/netty/exec/AuthCmdExecTest.java | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java index 887c99130..2a9ce0fbf 100644 --- a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java @@ -2,7 +2,9 @@ import java.lang.reflect.Method; +import com.github.dockerjava.core.RemoteApiVersion; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -14,6 +16,8 @@ import com.github.dockerjava.client.AbstractDockerClientTest; import com.github.dockerjava.core.DockerClientBuilder; +import static com.github.dockerjava.utils.TestUtils.getVersion; + @Test(groups = "integration") public class AuthCmdImplTest extends AbstractDockerClientTest { @@ -39,6 +43,12 @@ public void afterMethod(ITestResult result) { @Test public void testAuth() throws Exception { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("Fails on 1.22. Temporary disabled."); + } + AuthResponse response = dockerClient.authCmd().exec(); assertEquals(response.getStatus(), "Login Succeeded"); diff --git a/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java index 690d478f4..d753fca2b 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/AuthCmdExecTest.java @@ -2,7 +2,9 @@ import java.lang.reflect.Method; +import com.github.dockerjava.core.RemoteApiVersion; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -14,6 +16,8 @@ import com.github.dockerjava.core.DockerClientBuilder; import com.github.dockerjava.netty.AbstractNettyDockerClientTest; +import static com.github.dockerjava.utils.TestUtils.getVersion; + @Test(groups = "integration") public class AuthCmdExecTest extends AbstractNettyDockerClientTest { @@ -39,6 +43,11 @@ public void afterMethod(ITestResult result) { @Test public void testAuth() throws Exception { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("Fails on 1.22. Temporary disabled."); + } + AuthResponse response = dockerClient.authCmd().exec(); assertEquals(response.getStatus(), "Login Succeeded"); @@ -46,6 +55,11 @@ public void testAuth() throws Exception { @Test(expectedExceptions = UnauthorizedException.class) public void testAuthInvalid() throws Exception { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) { + throw new SkipException("Fails on 1.22. Temporary disabled."); + } + DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); } } From acb7ee41d8d67610b882b1ac59790b1784aebfb0 Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Sun, 5 Feb 2017 14:10:23 -0500 Subject: [PATCH 201/780] Add ability to add labels when running commit --- .../dockerjava/api/command/CommitCmd.java | 10 ++++++++ .../core/command/CommitCmdImpl.java | 19 +++++++++++++++ .../core/command/CommitCmdImplTest.java | 24 ++++++++++++++++++- .../netty/exec/CommitCmdExecTest.java | 24 ++++++++++++++++++- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/CommitCmd.java b/src/main/java/com/github/dockerjava/api/command/CommitCmd.java index c5da5bab6..a182751b8 100644 --- a/src/main/java/com/github/dockerjava/api/command/CommitCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CommitCmd.java @@ -3,6 +3,8 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; +import java.util.Map; + import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.ExposedPorts; import com.github.dockerjava.api.model.Volumes; @@ -29,6 +31,9 @@ public interface CommitCmd extends SyncDockerCmd { @CheckForNull String getHostname(); + @CheckForNull + Map getLabels(); + @CheckForNull Integer getMemory(); @@ -88,6 +93,11 @@ public interface CommitCmd extends SyncDockerCmd { CommitCmd withHostname(String hostname); + /** + * @since 1.19 + */ + CommitCmd withLabels(Map labels); + CommitCmd withMemory(Integer memory); CommitCmd withMemorySwap(Integer memorySwap); diff --git a/src/main/java/com/github/dockerjava/core/command/CommitCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CommitCmdImpl.java index 534cce52c..1c8ad26a4 100644 --- a/src/main/java/com/github/dockerjava/core/command/CommitCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CommitCmdImpl.java @@ -2,6 +2,8 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Map; + import com.fasterxml.jackson.annotation.JsonProperty; import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.exception.NotFoundException; @@ -43,6 +45,12 @@ public class CommitCmdImpl extends AbstrDockerCmd implements @JsonProperty("Hostname") private String hostname; + /** + * @since 1.19 + */ + @JsonProperty("Labels") + private Map labels; + @JsonProperty("Memory") private Integer memory; @@ -189,6 +197,17 @@ public CommitCmdImpl withEnv(String... env) { return this; } + @Override + public Map getLabels() { + return labels; + } + + @Override + public CommitCmdImpl withLabels(Map labels) { + this.labels = labels; + return this; + } + @Override public ExposedPorts getExposedPorts() { return exposedPorts; diff --git a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java index 64e1d7ddf..a6195ed4d 100644 --- a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java @@ -8,7 +8,9 @@ import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField; import java.lang.reflect.Method; +import java.util.Map; +import com.google.common.collect.ImmutableMap; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -54,7 +56,7 @@ public void commit() throws DockerException { assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainerCmd(container.getId()).exec(); - LOG.info("Commiting container: {}", container.toString()); + LOG.info("Committing container: {}", container.toString()); String imageId = dockerClient.commitCmd(container.getId()).exec(); InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); @@ -68,6 +70,26 @@ public void commit() throws DockerException { assertThat(inspectImageResponse.getParent(), equalTo(busyboxImg.getId())); } + @Test + public void commitWithLabels() throws DockerException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("touch", "/test").exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainerCmd(container.getId()).exec(); + + LOG.info("Committing container: {}", container.toString()); + Map labels = ImmutableMap.of("label1", "abc", "label2", "123"); + String imageId = dockerClient.commitCmd(container.getId()).withLabels(labels).exec(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + Map responseLabels = inspectImageResponse.getContainerConfig().getLabels(); + assertThat(responseLabels.get("label1"), equalTo("abc")); + assertThat(responseLabels.get("label2"), equalTo("123")); + } + @Test(expectedExceptions = NotFoundException.class) public void commitNonExistingContainer() throws DockerException { diff --git a/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java index 3d1a66333..8d8f6e6bb 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/CommitCmdExecTest.java @@ -8,7 +8,9 @@ import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField; import java.lang.reflect.Method; +import java.util.Map; +import com.google.common.collect.ImmutableMap; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; @@ -54,7 +56,7 @@ public void commit() throws DockerException { assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainerCmd(container.getId()).exec(); - LOG.info("Commiting container: {}", container.toString()); + LOG.info("Committing container: {}", container.toString()); String imageId = dockerClient.commitCmd(container.getId()).exec(); InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); @@ -68,6 +70,26 @@ public void commit() throws DockerException { assertThat(inspectImageResponse.getParent(), equalTo(busyboxImg.getId())); } + @Test + public void commitWithLabels() throws DockerException { + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("touch", "/test").exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainerCmd(container.getId()).exec(); + + LOG.info("Committing container: {}", container.toString()); + Map labels = ImmutableMap.of("label1", "abc", "label2", "123"); + String imageId = dockerClient.commitCmd(container.getId()).withLabels(labels).exec(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + Map responseLabels = inspectImageResponse.getContainerConfig().getLabels(); + assertThat(responseLabels.get("label1"), equalTo("abc")); + assertThat(responseLabels.get("label2"), equalTo("123")); + } + @Test(expectedExceptions = NotFoundException.class) public void commitNonExistingContainer() throws DockerException { From aa75982f3e43cb212cad80524fa8441617038562 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 14 Feb 2017 00:36:04 +0300 Subject: [PATCH 202/780] Test all latest --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d055f76e0..69aa64780 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,10 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.1-0~trusty" CODECOV=true - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.1-0~trusty" CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.6-0~ubuntu-trusty" CODECOV=true + - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.6-0~ubuntu-trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true From 1fbe1c401a6fc97d55a80cc93b00826d51206c0a Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 14 Feb 2017 01:12:23 +0300 Subject: [PATCH 203/780] Disable 1.13.1 Some tests failing. --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 69aa64780..eaf11b514 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,11 +21,11 @@ env: - COVERITY_SCAN_NOTIFICATION_EMAIL="kanstantsin.sha@gmail.com" matrix: - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true - - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.6-0~ubuntu-trusty" CODECOV=true +# - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true +# - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.13.1-0~ubuntu-trusty" CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.12.6-0~ubuntu-trusty" DEPLOY=true COVERITY=true CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.12.6-0~ubuntu-trusty" CODECOV=true - - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" DEPLOY=true COVERITY=true CODECOV=true + - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.11.2-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.11.2-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="tcp://127.0.0.1:2375" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true - repo="main" DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_VERSION="1.10.3-0~trusty" CODECOV=true From 17d04f6d9565696c7d527da622ddc99e6e6f46c2 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 14 Feb 2017 02:22:33 +0300 Subject: [PATCH 204/780] rerun failing tests count to 3 --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 852ad8283..726afefa4 100644 --- a/pom.xml +++ b/pom.xml @@ -397,6 +397,7 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 integration,integration-auth @@ -412,6 +413,7 @@ verify + 3 true true 1 From 80ba61f434a9a67fd0428f8c5e606be7d4485f07 Mon Sep 17 00:00:00 2001 From: Valerij Date: Wed, 15 Feb 2017 18:35:32 +0100 Subject: [PATCH 205/780] Capitalize variable name --- .../java/com/github/dockerjava/api/model/Statistics.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/Statistics.java b/src/main/java/com/github/dockerjava/api/model/Statistics.java index 9307da6b3..6bb1930e1 100644 --- a/src/main/java/com/github/dockerjava/api/model/Statistics.java +++ b/src/main/java/com/github/dockerjava/api/model/Statistics.java @@ -50,7 +50,7 @@ public class Statistics implements Serializable { * @since Docker Remote API 1.19 */ @JsonProperty("precpu_stats") - private Map precpuStats; + private Map preCpuStats; /** * @since Docker Remote API 1.21 @@ -76,8 +76,8 @@ public Map getCpuStats() { * The cpu statistic of last read, which is used for calculating the cpu usage percent. * It is not the exact copy of the {@link #getCpuStats()}. */ - public Map getPrecpuStats() { - return precpuStats; + public Map getPreCpuStats() { + return preCpuStats; } public Map getMemoryStats() { From 1c1833709beaa1d103cc9e02827347c0c696d263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Warcha=C5=82?= Date: Thu, 16 Feb 2017 10:35:13 +0100 Subject: [PATCH 206/780] Use TLSv2 by default --- .../dockerjava/core/LocalDirectorySSLConfig.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java b/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java index 961c282de..5e4a7fa57 100644 --- a/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java +++ b/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java @@ -45,14 +45,6 @@ public SSLContext getSSLContext() { Security.addProvider(new BouncyCastleProvider()); - // properties acrobatics not needed for java > 1.6 - String httpProtocols = System.getProperty("https.protocols"); - System.setProperty("https.protocols", "TLSv1"); - SslConfigurator sslConfig = SslConfigurator.newInstance(true); - if (httpProtocols != null) { - System.setProperty("https.protocols", httpProtocols); - } - String caPemPath = dockerCertPath + File.separator + "ca.pem"; String keyPemPath = dockerCertPath + File.separator + "key.pem"; String certPemPath = dockerCertPath + File.separator + "cert.pem"; @@ -61,6 +53,8 @@ public SSLContext getSSLContext() { String certpem = new String(Files.readAllBytes(Paths.get(certPemPath))); String capem = new String(Files.readAllBytes(Paths.get(caPemPath))); + SslConfigurator sslConfig = SslConfigurator.newInstance(true); + sslConfig.securityProtocol("TLSv1.2"); sslConfig.keyStore(CertificateUtils.createKeyStore(keypem, certpem)); sslConfig.keyStorePassword("docker"); sslConfig.trustStore(CertificateUtils.createTrustStore(capem)); From a3be9a5c32fd90c6c5d2f19e8c903b5df67fed2f Mon Sep 17 00:00:00 2001 From: "Lubos.Palisek" Date: Thu, 15 Dec 2016 13:30:57 +0100 Subject: [PATCH 207/780] Added healthcheck support in container inspect JSON result --- .../dockerjava/api/command/HealthState.java | 30 ++++ .../api/command/HealthStateLog.java | 36 ++++ .../api/command/InspectContainerResponse.java | 13 +- .../dockerjava/api/model/ContainerConfig.java | 11 ++ .../dockerjava/api/model/HealthCheck.java | 45 +++++ .../command/InspectContainerResponseTest.java | 27 ++- .../samples/1.24/containers/inspect/1.json | 167 ++++++++++++++++++ 7 files changed, 326 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/api/command/HealthState.java create mode 100644 src/main/java/com/github/dockerjava/api/command/HealthStateLog.java create mode 100644 src/main/java/com/github/dockerjava/api/model/HealthCheck.java create mode 100644 src/test/resources/samples/1.24/containers/inspect/1.json diff --git a/src/main/java/com/github/dockerjava/api/command/HealthState.java b/src/main/java/com/github/dockerjava/api/command/HealthState.java new file mode 100644 index 000000000..6f5418713 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/HealthState.java @@ -0,0 +1,30 @@ +package com.github.dockerjava.api.command; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class HealthState { + + @JsonProperty("Status") + private String status; + + @JsonProperty("FailingStreak") + private Integer failingStreak; + + @JsonProperty("Log") + private List log; + + public String getStatus() { + return status; + } + + public Integer getFailingStreak() { + return failingStreak; + } + + public List getLog() { + return log; + } +} diff --git a/src/main/java/com/github/dockerjava/api/command/HealthStateLog.java b/src/main/java/com/github/dockerjava/api/command/HealthStateLog.java new file mode 100644 index 000000000..e7f4c15a9 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/HealthStateLog.java @@ -0,0 +1,36 @@ +package com.github.dockerjava.api.command; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class HealthStateLog { + + @JsonProperty("Start") + private String start; + + @JsonProperty("End") + private String end; + + @JsonProperty("ExitCode") + private Integer exitCode; + + @JsonProperty("Output") + private String output; + + public String getStart() { + return start; + } + + public String getEnd() { + return end; + } + + public Integer getExitCode() { + return exitCode; + } + + public String getOutput() { + return output; + } +} diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java index c8027b0ed..497aaad2b 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java @@ -112,7 +112,7 @@ public String getId() { } public Integer getSizeRootFs() { - return sizeRootFs; + return sizeRootFs; } public String getCreated() { @@ -302,6 +302,13 @@ public class ContainerState { @JsonProperty("FinishedAt") private String finishedAt; + + /** + * @since Docker version 1.12 + */ + @JsonProperty("Health") + private HealthState health; + /** * See {@link #status} */ @@ -390,6 +397,10 @@ public String getFinishedAt() { return finishedAt; } + public HealthState getHealth() { + return health; + } + @Override public boolean equals(Object o) { return EqualsBuilder.reflectionEquals(this, o); diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java index 191126798..6d3265afa 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java @@ -86,6 +86,9 @@ public class ContainerConfig implements Serializable { @JsonProperty("WorkingDir") private String workingDir; + @JsonProperty("Healthcheck") + private HealthCheck healthCheck; + @JsonIgnore public ExposedPort[] getExposedPorts() { return exposedPorts != null ? exposedPorts.getExposedPorts() : null; @@ -411,6 +414,14 @@ public String getWorkingDir() { return workingDir; } + /** + * @see #healthCheck + */ + @CheckForNull + public HealthCheck getHealthcheck() { + return healthCheck; + } + /** * @see #workingDir */ diff --git a/src/main/java/com/github/dockerjava/api/model/HealthCheck.java b/src/main/java/com/github/dockerjava/api/model/HealthCheck.java new file mode 100644 index 000000000..514bf4f41 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/HealthCheck.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 cdancy. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * + * @author cdancy + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class HealthCheck implements Serializable { + private static final long serialVersionUID = 1L; + + @JsonProperty("Interval") + private Long interval; + + @JsonProperty("Timeout") + private Long timeout; + + public Long getInterval() { + return interval; + } + + public Long getTimeout() { + return timeout; + } +} diff --git a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java index cd4562b4a..51e8bd1dc 100644 --- a/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java +++ b/src/test/java/com/github/dockerjava/api/command/InspectContainerResponseTest.java @@ -15,10 +15,15 @@ */ package com.github.dockerjava.api.command; -import org.testng.annotations.Test; - +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Event; +import com.github.dockerjava.core.RemoteApiVersion; +import static com.github.dockerjava.test.serdes.JSONSamples.testRoundTrip; import java.io.IOException; +import org.testng.annotations.Test; + import static com.github.dockerjava.test.serdes.JSONTestHelper.testRoundTrip; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -55,6 +60,24 @@ public void roundTrip_full() throws IOException { assertThat(response.getLogPath(), is("/mnt/sda1/var/lib/docker/containers/469e5edd8d5b33e3c905a7ffc97360ec6ee211d6782815fbcd144568045819e1/469e5edd8d5b33e3c905a7ffc97360ec6ee211d6782815fbcd144568045819e1-json.log")); } + @Test + public void roundTrip_full_healthcheck() throws IOException { + + final ObjectMapper mapper = new ObjectMapper(); + final JavaType type = mapper.getTypeFactory().uncheckedSimpleType(InspectContainerResponse.class); + + final InspectContainerResponse response = testRoundTrip(RemoteApiVersion.VERSION_1_24, + "/containers/inspect/1.json", + type + ); + + assertEquals(response.getState().getHealth().getStatus(), "healthy"); + assertEquals(response.getState().getHealth().getFailingStreak(), new Integer(0)); + assertEquals(response.getState().getHealth().getLog().size(), 2); + assertEquals(response.getState().getHealth().getLog().get(0).getOutput(), "Hello"); + assertEquals(response.getState().getHealth().getLog().get(1).getOutput(), "World"); + } + @Test public void roundTrip_1_21_full() throws IOException { InspectContainerResponse[] responses = testRoundTrip(CommandJSONSamples.inspectContainerResponse_full_1_21, diff --git a/src/test/resources/samples/1.24/containers/inspect/1.json b/src/test/resources/samples/1.24/containers/inspect/1.json new file mode 100644 index 000000000..54d23923f --- /dev/null +++ b/src/test/resources/samples/1.24/containers/inspect/1.json @@ -0,0 +1,167 @@ +{ + "Id": "fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045", + "Created": "2015-11-20T21:10:34.775649753Z", + "Path": "cat", + "Args": [], + "State": { + "Status": "running", + "Running": true, + "Paused": false, + "Restarting": false, + "OOMKilled": false, + "Dead": false, + "Pid": 10912, + "ExitCode": 0, + "Error": "", + "StartedAt": "2015-11-20T21:10:34.845546358Z", + "FinishedAt": "0001-01-01T00:00:00Z", + "Health": { + "Status": "healthy", + "FailingStreak": 0, + "Log": [ + { + "Start": "2016-11-12T03:23:03.351561Z", + "End": "2016-11-12T03:23:03.422176171Z", + "ExitCode": 0, + "Output" : "Hello" + }, + { + "Start": "2016-11-12T03:23:08.423558928Z", + "End": "2016-11-12T03:23:08.510122392Z", + "ExitCode": 0, + "Output" : "World" + } + ] + } + }, + "Image": "c51f86c283408d1749d066333f7acd5d33b053b003a61ff6a7b36819ddcbc7b7", + "ResolvConfPath": "/mnt/sda1/var/lib/docker/containers/fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045/resolv.conf", + "HostnamePath": "/mnt/sda1/var/lib/docker/containers/fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045/hostname", + "HostsPath": "/mnt/sda1/var/lib/docker/containers/fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045/hosts", + "LogPath": "/mnt/sda1/var/lib/docker/containers/fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045/fc1243c01bbb791d9eca64204d76f72fc47fbebbca892d7dd0a5cd0e4e346045-json.log", + "Name": "/small_hodgkin", + "RestartCount": 0, + "Driver": "aufs", + "ExecDriver": "native-0.2", + "MountLabel": "", + "ProcessLabel": "", + "AppArmorProfile": "", + "ExecIDs": null, + "HostConfig": { + "Binds": null, + "ContainerIDFile": "", + "LxcConf": [], + "Memory": 0, + "MemoryReservation": 0, + "MemorySwap": 0, + "KernelMemory": 0, + "CpuShares": 0, + "CpuPeriod": 0, + "CpusetCpus": "", + "CpusetMems": "", + "CpuQuota": 0, + "BlkioWeight": 0, + "OomKillDisable": false, + "MemorySwappiness": -1, + "Privileged": false, + "PortBindings": {}, + "Links": null, + "PublishAllPorts": false, + "Dns": null, + "DnsOptions": null, + "DnsSearch": null, + "ExtraHosts": null, + "VolumesFrom": null, + "Devices": [], + "NetworkMode": "default", + "IpcMode": "", + "PidMode": "", + "UTSMode": "", + "CapAdd": null, + "CapDrop": null, + "GroupAdd": null, + "RestartPolicy": { + "Name": "no", + "MaximumRetryCount": 0 + }, + "SecurityOpt": null, + "ReadonlyRootfs": false, + "Ulimits": null, + "LogConfig": { + "Type": "json-file", + "Config": {} + }, + "CgroupParent": "", + "ConsoleSize": [ + 0, + 0 + ], + "VolumeDriver": "" + }, + "GraphDriver": { + "Name": "aufs", + "Data": null + }, + "Mounts": [], + "Config": { + "Hostname": "fc1243c01bbb", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": true, + "StdinOnce": false, + "Env": null, + "Cmd": [ + "cat" + ], + "Healthcheck": { + "Test": [ + "CMD-SHELL", + "mysqladmin ping --silent" + ], + "Interval": 2000000000, + "Timeout": 3000000000 + }, + "Image": "busybox", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": {}, + "StopSignal": "SIGTERM" + }, + "NetworkSettings": { + "Bridge": "", + "SandboxID": "5a6ded01bf23cc180e8ba6a059449ac832f28fa1d8367127e316607f92d3228c", + "HairpinMode": false, + "LinkLocalIPv6Address": "", + "LinkLocalIPv6PrefixLen": 0, + "Ports": {}, + "SandboxKey": "/var/run/docker/netns/5a6ded01bf23", + "SecondaryIPAddresses": null, + "SecondaryIPv6Addresses": null, + "EndpointID": "6b4bb2aff9981d6e132cf37ebbfd370069061fab848ae56247b154717a99aba7", + "Gateway": "172.17.0.1", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAddress": "172.17.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "MacAddress": "02:42:ac:11:00:02", + "Networks": { + "bridge": { + "EndpointID": "6b4bb2aff9981d6e132cf37ebbfd370069061fab848ae56247b154717a99aba7", + "Gateway": "172.17.0.1", + "IPAddress": "172.17.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "MacAddress": "02:42:ac:11:00:02" + } + } + } +} From 7427db3f5d8cd03f294f1c5b0929b2fcda7122fa Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 3 Mar 2017 22:22:24 +0300 Subject: [PATCH 208/780] Update CHANGELOG.md --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca927c2c3..114c66147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,11 @@ Change Log === ## (dev) 3.1.0 (reserverd for swarm features) -## next... +## 3.0.8 + - Use TLSv1.2 by default + - Health api + - Labels + - Support for multiple certificates ## 3.0.7 * https://github.com/docker-java/docker-java/milestone/17?closed=1 From c57c6b184ac3fb8a347463f07bd140054d903908 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 3 Mar 2017 22:32:03 +0300 Subject: [PATCH 209/780] [maven-release-plugin] prepare release 3.0.8 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 726afefa4..a6f046ba4 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.8-SNAPSHOT + 3.0.8 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.8 From 0a3ac8d071b297d681d37080649a90a64ef59417 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 3 Mar 2017 22:32:16 +0300 Subject: [PATCH 210/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a6f046ba4..bc1970e66 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.8 + 3.0.9-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.8 + HEAD From 32e1116d0f869597967682de18678260b4cd9e6a Mon Sep 17 00:00:00 2001 From: James Netherton Date: Sat, 4 Mar 2017 14:35:16 +0000 Subject: [PATCH 211/780] Fixes #807. NettyDockerCmdExecFactory ignores API version configuration --- .../netty/NettyDockerCmdExecFactory.java | 7 +- .../NettyDockerCmdExecFactoryConfigTest.java | 142 ++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java diff --git a/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java index c91d4af21..2c8a83b0e 100644 --- a/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java @@ -172,6 +172,8 @@ public class NettyDockerCmdExecFactory implements DockerCmdExecFactory { private NettyInitializer nettyInitializer; + private WebTarget baseResource; + private ChannelProvider channelProvider = new ChannelProvider() { @Override public DuplexChannel getChannel() { @@ -199,6 +201,8 @@ public void init(DockerClientConfig dockerClientConfig) { } eventLoopGroup = nettyInitializer.init(bootstrap, dockerClientConfig); + + baseResource = new WebTarget(channelProvider).path(dockerClientConfig.getApiVersion().asWebPathPart()); } private DuplexChannel connect() { @@ -619,6 +623,7 @@ private T configure(T channel) { } private WebTarget getBaseResource() { - return new WebTarget(channelProvider); + checkNotNull(baseResource, "Factory not initialized, baseResource not set. You probably forgot to call init()!"); + return baseResource; } } diff --git a/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java new file mode 100644 index 000000000..54184f674 --- /dev/null +++ b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java @@ -0,0 +1,142 @@ +package com.github.dockerjava.netty; + +import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH; +import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE; +import static io.netty.handler.codec.http.HttpResponseStatus.OK; +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; +import static org.testng.Assert.assertEquals; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.util.CharsetUtil; + +import java.util.ArrayList; +import java.util.List; + +import org.testng.annotations.Test; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.core.DefaultDockerClientConfig; +import com.github.dockerjava.core.DefaultDockerClientConfig.Builder; +import com.github.dockerjava.core.DockerClientBuilder; + +public class NettyDockerCmdExecFactoryConfigTest { + + @Test + public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception { + NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); + Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder() + .withDockerHost("tcp://localhost:2378") + .withApiVersion("1.23"); + + DockerClient client = DockerClientBuilder.getInstance(configBuilder) + .withDockerCmdExecFactory(factory) + .build(); + + FakeDockerServer server = new FakeDockerServer(2378); + server.start(); + try { + client.versionCmd().exec(); + + List requests = server.getRequests(); + + assertEquals(requests.size(), 1); + assertEquals(requests.get(0).uri(), "/v1.23/version"); + } finally { + server.stop(); + } + } + + @Test + public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Exception { + NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); + Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:2378"); + + DockerClient client = DockerClientBuilder.getInstance(configBuilder) + .withDockerCmdExecFactory(factory) + .build(); + + FakeDockerServer server = new FakeDockerServer(2378); + server.start(); + try { + client.versionCmd().exec(); + + List requests = server.getRequests(); + + assertEquals(requests.size(), 1); + assertEquals(requests.get(0).uri(), "/version"); + } finally { + server.stop(); + } + } + + private class FakeDockerServer { + private final int port; + private final NioEventLoopGroup parent; + private final NioEventLoopGroup child; + private final List requests = new ArrayList<>(); + private Channel channel; + + private FakeDockerServer(int port) { + this.port = port; + this.parent = new NioEventLoopGroup(); + this.child = new NioEventLoopGroup(); + } + + private void start() throws Exception { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(parent, child) + .channel(NioServerSocketChannel.class) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast("codec", new HttpServerCodec()); + pipeline.addLast("httpHandler", new SimpleChannelInboundHandler() { + @Override + protected void channelRead0(ChannelHandlerContext context, Object message) throws Exception { + if (message instanceof HttpRequest) { + // Keep track of processed requests + HttpRequest request = (HttpRequest) message; + requests.add(request); + } + + if (message instanceof HttpContent) { + // Write an empty JSON response back to the client + FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8)); + response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8"); + response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); + context.writeAndFlush(response); + } + } + }); + } + }); + + channel = bootstrap.bind(port).syncUninterruptibly().channel(); + } + + private void stop() throws Exception { + parent.shutdownGracefully(); + child.shutdownGracefully(); + channel.closeFuture().sync(); + } + + private List getRequests() { + return requests; + } + } +} From 221fff63fba1a82296198d67679f3eb7590d15ef Mon Sep 17 00:00:00 2001 From: James Netherton Date: Mon, 6 Mar 2017 20:46:56 +0000 Subject: [PATCH 212/780] Ensure FakeDockerServer is started on a random free port --- .../NettyDockerCmdExecFactoryConfigTest.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java index 54184f674..d0ddccca8 100644 --- a/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java +++ b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java @@ -23,6 +23,8 @@ import io.netty.handler.codec.http.HttpServerCodec; import io.netty.util.CharsetUtil; +import java.io.IOException; +import java.net.ServerSocket; import java.util.ArrayList; import java.util.List; @@ -37,16 +39,18 @@ public class NettyDockerCmdExecFactoryConfigTest { @Test public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception { + int dockerPort = getFreePort(); + NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder() - .withDockerHost("tcp://localhost:2378") + .withDockerHost("tcp://localhost:" + dockerPort) .withApiVersion("1.23"); DockerClient client = DockerClientBuilder.getInstance(configBuilder) .withDockerCmdExecFactory(factory) .build(); - FakeDockerServer server = new FakeDockerServer(2378); + FakeDockerServer server = new FakeDockerServer(dockerPort); server.start(); try { client.versionCmd().exec(); @@ -62,14 +66,16 @@ public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception @Test public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Exception { + int dockerPort = getFreePort(); + NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); - Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:2378"); + Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:" + dockerPort); DockerClient client = DockerClientBuilder.getInstance(configBuilder) .withDockerCmdExecFactory(factory) .build(); - FakeDockerServer server = new FakeDockerServer(2378); + FakeDockerServer server = new FakeDockerServer(dockerPort); server.start(); try { client.versionCmd().exec(); @@ -83,6 +89,13 @@ public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Except } } + private int getFreePort() throws IOException { + ServerSocket socket = new ServerSocket(0); + int freePort = socket.getLocalPort(); + socket.close(); + return freePort; + } + private class FakeDockerServer { private final int port; private final NioEventLoopGroup parent; From d9ca42c5a2f8d54f26f29ef5c2f06637254d9021 Mon Sep 17 00:00:00 2001 From: Maxim Chireychik Date: Tue, 14 Mar 2017 10:43:25 +0200 Subject: [PATCH 213/780] Unable to deserialize status response from amazon ECR login --- src/main/java/com/github/dockerjava/api/model/AuthResponse.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java index cd6908185..590fb7fb3 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java @@ -1,9 +1,11 @@ package com.github.dockerjava.api.model; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serializable; +@JsonIgnoreProperties(ignoreUnknown = true) public class AuthResponse implements Serializable { private static final long serialVersionUID = 1L; From 0b2abbc3a8bedeee1c5ab67eee65badfcd1f5d6e Mon Sep 17 00:00:00 2001 From: David Byron Date: Wed, 15 Mar 2017 09:13:23 -0700 Subject: [PATCH 214/780] exclude commons-logging since docker-java uses slf4j/logback --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index bc1970e66..acc3a160c 100644 --- a/pom.xml +++ b/pom.xml @@ -108,6 +108,12 @@ org.apache.httpcomponents httpclient ${httpclient.version} + + + commons-logging + commons-logging + + org.glassfish.jersey.core From f9fdc392bc676fa667f34e4e94b851919040ff7d Mon Sep 17 00:00:00 2001 From: orzeh Date: Tue, 28 Mar 2017 23:53:12 +0200 Subject: [PATCH 215/780] Generate OSGi compliant manifest (#797) * Generate OSGi compliant manifest Manifest is generated by the Bundlor plugin according to the template defined in template.mf file. Import package versions are mainly derived from properties defined in pom.xml. Imports of Netty packages are marked as optional. * Export com.github.dockerjava.core package and subpackages --- pom.xml | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ template.mf | 31 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 template.mf diff --git a/pom.xml b/pom.xml index acc3a160c..154153fe5 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,8 @@ 2.19.1 2.19.1 1.8 + 1.1.2.RELEASE + 3.0.0 @@ -275,6 +277,19 @@ + + + eclipse.virgo.build.bundles.release + Eclipse Virgo Build + http://build.eclipse.org/rt/virgo/maven/bundles/release + + + com.springsource.repository.bundles.external + SpringSource Enterprise Bundle Repository - External Bundle Releases + http://repository.springsource.com/maven/bundles/external + + + @@ -301,6 +316,11 @@ org.apache.maven.plugins maven-jar-plugin ${maven-jar-plugin.version} + + + target/classes/META-INF/MANIFEST.MF + + @@ -436,6 +456,37 @@ org.apache.maven.plugins maven-source-plugin + + + org.eclipse.virgo.bundlor + org.eclipse.virgo.bundlor.maven + ${maven-bundlor-plugin.version} + + + bundlor + + bundlor + + + true + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${maven-build-helper-plugin.version} + + + parse-version + + parse-version + + + + diff --git a/template.mf b/template.mf new file mode 100644 index 000000000..35d278889 --- /dev/null +++ b/template.mf @@ -0,0 +1,31 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: com.github.docker-java +Bundle-Version: ${parsedVersion.osgiVersion} +Bundle-Name: ${project.name} +Version-Patterns: + default;pattern="[=.=.=, =.+1.0)", + short;pattern="[=.=,+1.0)" +Import-Template: + com.fasterxml.jackson.*;version="${jackson-jaxrs.version}", + com.google.common.*;version="${guava.version:short}", + io.netty.*;version="${netty.version:default}";resolution:=optional, + javax.ws.rs.*;version="[2.0.0, 2.1.0)", + org.apache.commons.codec.*;version="${commons-codec.version:short}", + org.apache.commons.compress.*;version="${commons-compress.version:short}", + org.apache.commons.io.*;version="${commons-io.version:short}", + org.apache.commons.lang.*;version="${commons-lang.version:short}", + org.apache.http.*;version="[4.4.0, 4.6.0)", + org.bouncycastle.*;version="${bouncycastle.version:short}", + org.glassfish.jersey.*;version="${jersey.version:default}", + org.slf4j.*;version="[1.7.0, 1.8.0)", + org.newsclub.net.unix;version="${junixsocket.version:default}";resolution:=optional +Excluded-Exports: + org.apache.http.impl.io, + org.newsclub.net.unix, + com.github.dockerjava.jaxrs.*, + com.github.dockerjava.netty.* +Excluded-Imports: + javax.annotation, + javax.net.ssl, + edu.umd.cs.findbugs.annotations From 7016a6364e6638b126baa684209246068d57c773 Mon Sep 17 00:00:00 2001 From: nimantha siriwardana Date: Wed, 29 Mar 2017 09:40:50 +0100 Subject: [PATCH 216/780] adding support for unless-stopped restart policy --- .../github/dockerjava/api/model/RestartPolicy.java | 11 +++++++++++ .../api/model/RestartPolicy_ParsingTest.java | 5 +++++ .../api/model/RestartPolicy_SerializingTest.java | 7 +++++++ .../api/model/RestartPolicy_toStringTest.java | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java b/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java index 1f77b8b9d..98e181a1b 100644 --- a/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java +++ b/src/main/java/com/github/dockerjava/api/model/RestartPolicy.java @@ -70,6 +70,13 @@ public static RestartPolicy onFailureRestart(int maximumRetryCount) { return new RestartPolicy(maximumRetryCount, "on-failure"); } + /** + * Restart the container unless it has been stopped + */ + public static RestartPolicy unlessStoppedRestart() { + return new RestartPolicy(0, "unless-stopped"); + } + public Integer getMaximumRetryCount() { return maximumRetryCount; } @@ -99,6 +106,10 @@ public static RestartPolicy parse(String serialized) throws IllegalArgumentExcep return alwaysRestart(); } + if ("unless-stopped".equals(name)) { + return unlessStoppedRestart(); + } + if ("on-failure".equals(name)) { int count = 0; if (parts.length == 2) { diff --git a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_ParsingTest.java b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_ParsingTest.java index 3bc22c00e..85740be61 100644 --- a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_ParsingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_ParsingTest.java @@ -16,6 +16,11 @@ public void alwaysRestart() throws Exception { assertEquals(RestartPolicy.parse("always"), RestartPolicy.alwaysRestart()); } + @Test + public void unlessStoppedRestart() throws Exception { + assertEquals(RestartPolicy.parse("unless-stopped"), RestartPolicy.unlessStoppedRestart()); + } + @Test public void onFailureRestart() throws Exception { assertEquals(RestartPolicy.parse("on-failure"), RestartPolicy.onFailureRestart(0)); diff --git a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_SerializingTest.java b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_SerializingTest.java index 74c97fcf6..06debb34f 100644 --- a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_SerializingTest.java +++ b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_SerializingTest.java @@ -27,6 +27,13 @@ public void alwaysRestart() throws Exception { assertEquals(json, "{\"MaximumRetryCount\":0,\"Name\":\"always\"}"); } + @Test + // --restart unless-stopped + public void unlessStoppedRestart() throws Exception { + String json = objectMapper.writeValueAsString(RestartPolicy.unlessStoppedRestart()); + assertEquals(json, "{\"MaximumRetryCount\":0,\"Name\":\"unless-stopped\"}"); + } + @Test // --restart on-failure public void onFailureRestart() throws Exception { diff --git a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_toStringTest.java b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_toStringTest.java index 69e1e88a2..611343736 100644 --- a/src/test/java/com/github/dockerjava/api/model/RestartPolicy_toStringTest.java +++ b/src/test/java/com/github/dockerjava/api/model/RestartPolicy_toStringTest.java @@ -9,7 +9,7 @@ public class RestartPolicy_toStringTest { @DataProvider(name = "input") public Object[][] restartPolicies() { - return new Object[][] { {"no"}, {"always"}, {"on-failure"}, {"on-failure:2"}}; + return new Object[][] { {"no"}, {"always"}, {"unless-stopped"}, {"on-failure"}, {"on-failure:2"}}; } @Test(dataProvider = "input") From 2d053870d546b43b8f5d18f53e5085702ace097d Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 13 Apr 2017 22:59:40 +0300 Subject: [PATCH 217/780] Responce may contains token. --- .../dockerjava/api/model/AuthResponse.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java index 590fb7fb3..821d4c4ac 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java @@ -3,16 +3,39 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import java.io.Serializable; @JsonIgnoreProperties(ignoreUnknown = true) public class AuthResponse implements Serializable { private static final long serialVersionUID = 1L; + /** + * @since 1.23 + */ @JsonProperty("Status") private String status; + /** + * @since 1.23 + */ + @JsonProperty("IdentityToken") + private String identityToken; + + /** + * @see #status + */ + @Nonnull public String getStatus() { return status; } + + /** + * @see #identityToken + */ + @CheckForNull + public String getIdentityToken() { + return identityToken; + } } From f01072d81b5d06b79ad4425a568e19c89c06a1cf Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 13 Apr 2017 23:03:33 +0300 Subject: [PATCH 218/780] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 114c66147..b0c7f2237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Change Log === ## (dev) 3.1.0 (reserverd for swarm features) +## 3.0.9 +- NettyDockerCmdExecFactory ignores API version +- exclude commons-logging from httpclient since docker-java uses slf4j/logback +- Generate OSGi compliant manifest +- AuthResponse may contains token. + ## 3.0.8 - Use TLSv1.2 by default - Health api From 250a02baa7ae3549f4d4ebc9cd6efdd88d14bfab Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 13 Apr 2017 23:14:27 +0300 Subject: [PATCH 219/780] Fix test. --- .../netty/NettyDockerCmdExecFactoryConfigTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java index d0ddccca8..e36ee6b8b 100644 --- a/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java +++ b/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java @@ -42,7 +42,8 @@ public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception int dockerPort = getFreePort(); NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); - Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder() + Builder configBuilder = new DefaultDockerClientConfig.Builder() + .withDockerTlsVerify(false) .withDockerHost("tcp://localhost:" + dockerPort) .withApiVersion("1.23"); @@ -69,7 +70,9 @@ public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Except int dockerPort = getFreePort(); NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory(); - Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:" + dockerPort); + Builder configBuilder = new DefaultDockerClientConfig.Builder() + .withDockerTlsVerify(false) + .withDockerHost("tcp://localhost:" + dockerPort); DockerClient client = DockerClientBuilder.getInstance(configBuilder) .withDockerCmdExecFactory(factory) From d705bfba9aea65b3556fe057e1f7fedf8622da90 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 13 Apr 2017 23:18:52 +0300 Subject: [PATCH 220/780] [maven-release-plugin] prepare release 3.0.9 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 154153fe5..fd58ad39c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.9-SNAPSHOT + 3.0.9 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.9 From 53ee7e172f85ee994bc70ab5af3719cf1ab992d8 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Thu, 13 Apr 2017 23:19:03 +0300 Subject: [PATCH 221/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fd58ad39c..8933bad62 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.9 + 3.0.10-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.9 + HEAD From dc87e0c592c133acc8ccac87a4cb0941eccdbb0e Mon Sep 17 00:00:00 2001 From: Dmitry Gusev Date: Mon, 24 Apr 2017 01:01:36 +0300 Subject: [PATCH 222/780] Proposed fix for #830 (#832) * Proposed fix for #830 * Simplify the fix for #830 --- .../command/BuildImageResultCallback.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageResultCallback.java b/src/main/java/com/github/dockerjava/core/command/BuildImageResultCallback.java index 1ca276434..e622c4725 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageResultCallback.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageResultCallback.java @@ -5,8 +5,6 @@ import java.util.concurrent.TimeUnit; -import javax.annotation.CheckForNull; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,12 +21,17 @@ public class BuildImageResultCallback extends ResultCallbackTemplate Date: Sun, 23 Apr 2017 23:03:39 +0100 Subject: [PATCH 223/780] Allow an explicit Dockerfile location string to be specified to the build command (#825) * When supplying a TAR stream to the build command, API consumers just want to pass a String location of the Dockerfile within the TAR stream they are supplying * Add netty test for building with an explicitly specified Dockerfile location within a tar --- .../dockerjava/api/command/BuildImageCmd.java | 2 ++ .../dockerjava/core/command/BuildImageCmdImpl.java | 13 ++++++++++++- .../core/command/BuildImageCmdImplTest.java | 14 ++++++++++++++ .../netty/exec/BuildImageCmdExecTest.java | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java index ac98db2f9..0c9b7f5a4 100644 --- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java @@ -117,6 +117,8 @@ public interface BuildImageCmd extends AsyncDockerCmd files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); + File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString()); + String response = dockerfileBuild(new FileInputStream(tarFile), "dockerfileFolder/Dockerfile"); + assertThat(response, containsString("Successfully executed testrun.sh")); + } + @Test public void onBuild() throws Exception { File baseDir = fileFromBuildTestResource("ONBUILD/parent"); @@ -123,6 +132,11 @@ public void addFolder() throws Exception { assertThat(response, containsString("Successfully executed testAddFolder.sh")); } + private String dockerfileBuild(InputStream tarInputStream, String dockerFilePath) throws Exception { + + return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream).withDockerfilePath(dockerFilePath)); + } + private String dockerfileBuild(InputStream tarInputStream) throws Exception { return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream)); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index f567dcfc8..63fcf7ea1 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -88,6 +88,15 @@ public void buildImageFromTar() throws Exception { assertThat(response, containsString("Successfully executed testrun.sh")); } + @Test + public void buildImageFromTarWithDockerfileNotInBaseDirectory() throws Exception { + File baseDir = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); + Collection files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); + File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString()); + String response = dockerfileBuild(new FileInputStream(tarFile), "dockerfileFolder/Dockerfile"); + assertThat(response, containsString("Successfully executed testrun.sh")); + } + @Test public void onBuild() throws Exception { File baseDir = fileFromBuildTestResource("ONBUILD/parent"); @@ -128,6 +137,11 @@ public void addFolder() throws Exception { assertThat(response, containsString("Successfully executed testAddFolder.sh")); } + private String dockerfileBuild(InputStream tarInputStream, String dockerFilePath) throws Exception { + + return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream).withDockerfilePath(dockerFilePath)); + } + private String dockerfileBuild(InputStream tarInputStream) throws Exception { return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream)); From e81067367657c6dac686cd0e613f849685a5c3c3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 24 Apr 2017 01:51:56 +0300 Subject: [PATCH 224/780] Add some coding styles. TODO sync and share eclipse files? --- .gitignore | 3 ++- .idea/codeStyleSettings.xml | 12 ++++++++++++ .idea/encodings.xml | 7 +++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .idea/codeStyleSettings.xml create mode 100644 .idea/encodings.xml diff --git a/.gitignore b/.gitignore index a705c1129..5399371c4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,8 @@ target # Ignore InteliJ Idea project files .idea -.idea/* +!.idea/codeStyleSettings.xml +!.idea/encodings.xml *.iml *.iws *.ipr diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 000000000..6f3c789b4 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..c0bce7084 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 3ad99322f80ecd502cbe2fc68f7185c9d2807a3e Mon Sep 17 00:00:00 2001 From: Jonas Trollvik Date: Thu, 27 Apr 2017 17:22:24 +0200 Subject: [PATCH 225/780] Add db LoggingType Synology uses it's own logging type called db --- src/main/java/com/github/dockerjava/api/model/LogConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/github/dockerjava/api/model/LogConfig.java b/src/main/java/com/github/dockerjava/api/model/LogConfig.java index e2a066101..2a3301287 100644 --- a/src/main/java/com/github/dockerjava/api/model/LogConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/LogConfig.java @@ -79,6 +79,7 @@ public enum LoggingType { GELF("gelf"), FLUENTD("fluentd"), AWSLOGS("awslogs"), + DB("db"), // Synology specific driver SPLUNK("splunk"); private String type; From 460406705daf705ae46467f2ffa6f371aafeed12 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 5 May 2017 05:12:40 +0300 Subject: [PATCH 226/780] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0c7f2237..84f2b27d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Change Log === ## (dev) 3.1.0 (reserverd for swarm features) + +## 3.0.10 +- Custom `db` logging type +- Allow an explicit Dockerfile location string to be specified to theuild command +- Fix image build for docker 17 with 'tagged' word. + ## 3.0.9 - NettyDockerCmdExecFactory ignores API version - exclude commons-logging from httpclient since docker-java uses slf4j/logback From c82b92d38374e242e8130af7282f8cf59c91297d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Warcha=C5=82?= Date: Tue, 15 Nov 2016 13:48:57 +0100 Subject: [PATCH 227/780] Allow multiple tags in build image command Several tags for image can be defined by calling multiple time withTag() method of BuildImageCmd. In Netty implementation, the WebTarget class is modified to support several query parameteres with the same name. Fix #720 --- .../dockerjava/api/command/BuildImageCmd.java | 19 +++++ .../core/command/BuildImageCmdImpl.java | 24 +++++- .../dockerjava/jaxrs/BuildImageCmdExec.java | 9 +- .../github/dockerjava/netty/WebTarget.java | 85 +++++++++++++++++-- .../netty/exec/BuildImageCmdExec.java | 34 +++----- .../core/command/BuildImageCmdImplTest.java | 25 ++++++ .../netty/exec/BuildImageCmdExecTest.java | 25 ++++++ 7 files changed, 189 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java index ac98db2f9..a36b1b17e 100644 --- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java @@ -4,6 +4,7 @@ import java.io.InputStream; import java.net.URI; import java.util.Map; +import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -34,10 +35,21 @@ public interface BuildImageCmd extends AsyncDockerCmd getTags(); + /** * "remote" in API */ @@ -109,8 +121,15 @@ public interface BuildImageCmd extends AsyncDockerCmd)} + */ + @Deprecated BuildImageCmd withTag(String tag); + BuildImageCmd withTags(Set tags); + BuildImageCmd withRemote(URI remote); BuildImageCmd withBaseDirectory(File baseDirectory); diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java index c34b05155..97629568c 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java @@ -8,6 +8,7 @@ import java.net.URI; import java.util.HashMap; import java.util.Map; +import java.util.Set; import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.model.AuthConfigurations; @@ -15,17 +16,20 @@ import com.github.dockerjava.core.dockerfile.Dockerfile; import com.github.dockerjava.core.util.FilePathUtil; +import javax.annotation.CheckForNull; + /** - * * Build an image from Dockerfile. - * */ public class BuildImageCmdImpl extends AbstrAsyncDockerCmd implements BuildImageCmd { private InputStream tarInputStream; + @Deprecated private String tag; + private Set tags; + private Boolean noCache; private Boolean remove = true; @@ -82,11 +86,17 @@ public BuildImageCmdImpl(BuildImageCmd.Exec exec, InputStream tarInputStream) { // getters API + @Deprecated @Override public String getTag() { return tag; } + @CheckForNull + public Set getTags() { + return tags; + } + @Override public URI getRemote() { return remote; @@ -178,6 +188,10 @@ public Long getShmsize() { // setters + /** + * @deprecated use #withTags() + */ + @Deprecated @Override public BuildImageCmdImpl withTag(String tag) { checkNotNull(tag, "Tag is null"); @@ -185,6 +199,12 @@ public BuildImageCmdImpl withTag(String tag) { return this; } + @Override + public BuildImageCmd withTags(Set tags) { + this.tags = tags; + return this; + } + @Override public BuildImageCmd withRemote(URI remote) { this.remote = remote; diff --git a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java index 2a7aea40e..ae2302b0d 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java @@ -1,6 +1,7 @@ package com.github.dockerjava.jaxrs; import static javax.ws.rs.client.Entity.entity; +import static org.apache.commons.lang.StringUtils.isNotBlank; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; @@ -65,9 +66,15 @@ protected AbstractCallbackNotifier callbackNotifier(BuildImag if (dockerFilePath != null && command.getRemote() == null && !"Dockerfile".equals(dockerFilePath)) { webTarget = webTarget.queryParam("dockerfile", dockerFilePath); } - if (command.getTag() != null) { + + if (command.getTags() != null && !command.getTags().isEmpty()) { + for (String t : command.getTags()) { + webTarget = webTarget.queryParam("t", t); + } + } else if (isNotBlank(command.getTag())) { webTarget = webTarget.queryParam("t", command.getTag()); } + if (command.getRemote() != null) { webTarget = webTarget.queryParam("remote", command.getRemote().toString()); } diff --git a/src/main/java/com/github/dockerjava/netty/WebTarget.java b/src/main/java/com/github/dockerjava/netty/WebTarget.java index ef1510f5c..96fb42bec 100644 --- a/src/main/java/com/github/dockerjava/netty/WebTarget.java +++ b/src/main/java/com/github/dockerjava/netty/WebTarget.java @@ -1,22 +1,32 @@ package com.github.dockerjava.netty; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableSet; +import io.netty.handler.codec.http.HttpConstants; import org.apache.commons.lang.StringUtils; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** - * This class is basically a replacement of javax.ws.rs.client.WebTarget to allow simpler migration of JAX-RS code to a netty based + * This class is basically a replacement of {@link javax.ws.rs.client.WebTarget} to allow simpler migration of JAX-RS code to a netty based * implementation. * * @author Marcus Linke */ public class WebTarget { + private static final ObjectMapper MAPPER = new ObjectMapper(); private final ChannelProvider channelProvider; @@ -24,18 +34,26 @@ public class WebTarget { private final ImmutableMap queryParams; + /** + * Multiple values for the same name param. + */ + private final ImmutableMap> queryParamsSet; + private static final String PATH_SEPARATOR = "/"; public WebTarget(ChannelProvider channelProvider) { - this(channelProvider, ImmutableList.of(), ImmutableMap.of()); + this(channelProvider, ImmutableList.of(), ImmutableMap.of(), + ImmutableMap.>of()); } private WebTarget(ChannelProvider channelProvider, ImmutableList path, - ImmutableMap queryParams) { + ImmutableMap queryParams, + ImmutableMap> queryParamsSet) { this.channelProvider = channelProvider; this.path = path; this.queryParams = queryParams; + this.queryParamsSet = queryParamsSet; } public WebTarget path(String... components) { @@ -45,7 +63,7 @@ public WebTarget path(String... components) { newPath.addAll(Arrays.asList(StringUtils.split(component, PATH_SEPARATOR))); } - return new WebTarget(channelProvider, newPath.build(), queryParams); + return new WebTarget(channelProvider, newPath.build(), queryParams, queryParamsSet); } public InvocationBuilder request() { @@ -53,7 +71,13 @@ public InvocationBuilder request() { List params = new ArrayList<>(); for (Map.Entry entry : queryParams.entrySet()) { - params.add(entry.getKey() + "=" + entry.getValue()); + params.add(entry.getKey() + "=" + encodeComponent(entry.getValue(), HttpConstants.DEFAULT_CHARSET)); + } + + for (Map.Entry> entry : queryParamsSet.entrySet()) { + for (String entryValueValue : entry.getValue()) { + params.add(entry.getKey() + "=" + encodeComponent(entryValueValue, HttpConstants.DEFAULT_CHARSET)); + } } if (!params.isEmpty()) { @@ -63,13 +87,25 @@ public InvocationBuilder request() { return new InvocationBuilder(channelProvider, resource); } + /** + * @see io.netty.handler.codec.http.QueryStringEncoder + */ + private static String encodeComponent(String s, Charset charset) { + // TODO: Optimize me. + try { + return URLEncoder.encode(s, charset.name()).replace("+", "%20"); + } catch (UnsupportedEncodingException ignored) { + throw new UnsupportedCharsetException(charset.name()); + } + } + public WebTarget resolveTemplate(String name, Object value) { ImmutableList.Builder newPath = ImmutableList.builder(); for (String component : path) { component = component.replaceAll("\\{" + name + "\\}", value.toString()); newPath.add(component); } - return new WebTarget(channelProvider, newPath.build(), queryParams); + return new WebTarget(channelProvider, newPath.build(), queryParams, queryParamsSet); } public WebTarget queryParam(String name, Object value) { @@ -77,7 +113,32 @@ public WebTarget queryParam(String name, Object value) { if (value != null) { builder.put(name, value.toString()); } - return new WebTarget(channelProvider, path, builder.build()); + return new WebTarget(channelProvider, path, builder.build(), queryParamsSet); + } + + public WebTarget queryParamsSet(String name, Set values) { + ImmutableMap.Builder> builder = ImmutableMap.>builder().putAll(queryParamsSet); + if (values != null) { + ImmutableSet.Builder valueBuilder = ImmutableSet.builder(); + for (Object value : values) { + valueBuilder.add(value.toString()); + } + builder.put(name, valueBuilder.build()); + } + return new WebTarget(channelProvider, path, queryParams, builder.build()); + } + + public WebTarget queryParamsJsonMap(String name, Map values) { + if (values != null && !values.isEmpty()) { + try { + // when param value is JSON string + return queryParam(name, MAPPER.writeValueAsString(values)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + return this; + } } @Override @@ -97,7 +158,14 @@ public boolean equals(Object o) { if (path != null ? !path.equals(webTarget.path) : webTarget.path != null) { return false; } - return queryParams != null ? queryParams.equals(webTarget.queryParams) : webTarget.queryParams == null; + if (queryParams != null ? !queryParams.equals(webTarget.queryParams) : webTarget.queryParams != null) { + return false; + } + if (queryParamsSet != null ? !queryParamsSet.equals(webTarget.queryParamsSet) : webTarget.queryParamsSet != null) { + return false; + } + + return true; } @Override @@ -105,6 +173,7 @@ public int hashCode() { int result = channelProvider != null ? channelProvider.hashCode() : 0; result = 31 * result + (path != null ? path.hashCode() : 0); result = 31 * result + (queryParams != null ? queryParams.hashCode() : 0); + result = 31 * result + (queryParamsSet != null ? queryParamsSet.hashCode() : 0); return result; } } diff --git a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java index 43152570e..bbca686e0 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java @@ -1,6 +1,5 @@ package com.github.dockerjava.netty.exec; -import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,15 +13,12 @@ import com.github.dockerjava.netty.MediaType; import com.github.dockerjava.netty.WebTarget; -import java.io.IOException; -import java.util.Map; +import static org.apache.commons.lang.StringUtils.isNotBlank; public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec implements BuildImageCmd.Exec { private static final Logger LOGGER = LoggerFactory.getLogger(BuildImageCmdExec.class); - private static final ObjectMapper MAPPER = new ObjectMapper(); - public BuildImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { super(baseResource, dockerClientConfig); } @@ -55,9 +51,13 @@ protected Void execute0(BuildImageCmd command, ResultCallback if (dockerFilePath != null && command.getRemote() == null && !"Dockerfile".equals(dockerFilePath)) { webTarget = webTarget.queryParam("dockerfile", dockerFilePath); } - if (command.getTag() != null) { - webTarget = webTarget.queryParam("t", command.getTag()); + + if (command.getTags() != null && !command.getTags().isEmpty()) { + webTarget = webTarget.queryParamsSet("t", command.getTags()); + } else if (isNotBlank(command.getTag())) { + webTarget = webTarget.queryParam("t", command.getTags()); } + if (command.getRemote() != null) { webTarget = webTarget.queryParam("remote", command.getRemote().toString()); } @@ -86,13 +86,17 @@ protected Void execute0(BuildImageCmd command, ResultCallback webTarget = webTarget.queryParam("cpusetcpus", command.getCpusetcpus()); } - webTarget = writeMap(webTarget, "buildargs", command.getBuildArgs()); + if (command.getBuildArgs() != null) { + webTarget = webTarget.queryParamsJsonMap("buildargs", command.getBuildArgs()); + } if (command.getShmsize() != null) { webTarget = webTarget.queryParam("shmsize", command.getShmsize()); } - webTarget = writeMap(webTarget, "labels", command.getLabels()); + if (command.getLabels() != null) { + webTarget = webTarget.queryParamsJsonMap("labels", command.getLabels()); + } LOGGER.trace("POST: {}", webTarget); @@ -106,16 +110,4 @@ protected Void execute0(BuildImageCmd command, ResultCallback return null; } - - private WebTarget writeMap(WebTarget webTarget, String name, Map value) { - if (value != null && !value.isEmpty()) { - try { - return webTarget.queryParam(name, MAPPER.writeValueAsString(value)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } else { - return webTarget; - } - } } diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index cb4c1b2a8..9ba283732 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -7,13 +7,16 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.containsInAnyOrder; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.UUID; import org.apache.commons.io.FileUtils; @@ -274,6 +277,28 @@ public void labels() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void multipleTags() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) { + throw new SkipException("API version should be >= 1.21"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withTag("fallback-when-withTags-not-called") + .withTags(new HashSet<>(Arrays.asList("docker-java-test:tag1", "docker-java-test:tag2"))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2)); + assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index f567dcfc8..55dcf353b 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -7,13 +7,16 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.containsInAnyOrder; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.UUID; import org.apache.commons.io.FileUtils; @@ -279,6 +282,28 @@ public void labels() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void multipleTags() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) { + throw new SkipException("API version should be >= 1.21"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withTag("fallback-when-withTags-not-called") + .withTags(new HashSet<>(Arrays.asList("docker-java-test:tag1", "docker-java-test:tag2"))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2)); + assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); From e5e674a73199633ed05817d4283ec9e160c8ec0d Mon Sep 17 00:00:00 2001 From: kannan-ca Date: Thu, 11 May 2017 17:05:01 -0400 Subject: [PATCH 228/780] Docker API update to 1.25 and support for cache-from command as part of the docker build --- .../dockerjava/api/command/BuildImageCmd.java | 11 +++++++++ .../dockerjava/core/RemoteApiVersion.java | 6 +++++ .../core/command/BuildImageCmdImpl.java | 13 ++++++++++ .../dockerjava/jaxrs/BuildImageCmdExec.java | 6 +++++ .../netty/exec/BuildImageCmdExec.java | 8 ++++++- .../core/command/BuildImageCmdImplTest.java | 24 +++++++++++++++++++ .../netty/exec/BuildImageCmdExecTest.java | 23 ++++++++++++++++++ 7 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java index 2a08f4cf5..59a0d2077 100644 --- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java @@ -50,6 +50,12 @@ public interface BuildImageCmd extends AsyncDockerCmd getTags(); + /** + * "Cache-from" in API + */ + @CheckForNull + Set getCacheFrom(); + /** * "remote" in API */ @@ -130,6 +136,11 @@ public interface BuildImageCmd extends AsyncDockerCmd tags); + /* + * @since {@link RemoteApiVersion#VERSION_1_25} + */ + BuildImageCmd withCacheFrom(Set cacheFrom); + BuildImageCmd withRemote(URI remote); BuildImageCmd withBaseDirectory(File baseDirectory); diff --git a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java index f40b5b4d5..44c4f0237 100644 --- a/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java +++ b/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java @@ -72,6 +72,12 @@ public class RemoteApiVersion implements Serializable { */ public static final RemoteApiVersion VERSION_1_24 = RemoteApiVersion.create(1, 24); + /* + * @see Docker API 1.25 + */ + public static final RemoteApiVersion VERSION_1_25 = RemoteApiVersion.create(1, 25); + + /** * Unknown, docker doesn't reflect reality. I.e. we implemented method, but for javadoc it not clear when it was added. */ diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java index fedd8bf98..cb9e81a39 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java @@ -30,6 +30,8 @@ public class BuildImageCmdImpl extends AbstrAsyncDockerCmd tags; + private Set cacheFrom; + private Boolean noCache; private Boolean remove = true; @@ -99,6 +101,11 @@ public Set getTags() { return tags; } + @CheckForNull + public Set getCacheFrom() { + return cacheFrom; + } + @Override public URI getRemote() { return remote; @@ -209,6 +216,12 @@ public BuildImageCmd withTags(Set tags) { return this; } + @Override + public BuildImageCmd withCacheFrom(Set cacheFrom) { + this.cacheFrom = cacheFrom; + return this; + } + @Override public BuildImageCmd withRemote(URI remote) { this.remote = remote; diff --git a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java index ae2302b0d..7ce132963 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java @@ -75,6 +75,12 @@ protected AbstractCallbackNotifier callbackNotifier(BuildImag webTarget = webTarget.queryParam("t", command.getTag()); } + if (command.getCacheFrom() != null) { + for (String c: command.getCacheFrom()) { + webTarget = webTarget.queryParam("cachefrom", c); + } + } + if (command.getRemote() != null) { webTarget = webTarget.queryParam("remote", command.getRemote().toString()); } diff --git a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java index bbca686e0..321ae63c1 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java @@ -55,7 +55,13 @@ protected Void execute0(BuildImageCmd command, ResultCallback if (command.getTags() != null && !command.getTags().isEmpty()) { webTarget = webTarget.queryParamsSet("t", command.getTags()); } else if (isNotBlank(command.getTag())) { - webTarget = webTarget.queryParam("t", command.getTags()); + webTarget = webTarget.queryParam("t", command.getTag()); + } + + if (command.getCacheFrom() != null) { + for (String c: command.getCacheFrom()) { + webTarget = webTarget.queryParam("cachefrom", c); + } } if (command.getRemote() != null) { diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index a655af126..20ac2b62d 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -312,6 +312,30 @@ public void multipleTags() throws Exception { assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2)); assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); } + + @Test + public void cacheFrom() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_25)) { + throw new SkipException("API version should be >= 1.25"); + } + File baseDir1 = fileFromBuildTestResource("CacheFrom/test1"); + String imageId1 = dockerClient.buildImageCmd(baseDir1) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + InspectImageResponse inspectImageResponse1 = dockerClient.inspectImageCmd(imageId1).exec(); + assertThat(inspectImageResponse1, not(nullValue())); + + File baseDir2 = fileFromBuildTestResource("CacheFrom/test2"); + String imageId2 = dockerClient.buildImageCmd(baseDir2).withCacheFrom(new HashSet<>(Arrays.asList(imageId1))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + InspectImageResponse inspectImageResponse2 = dockerClient.inspectImageCmd(imageId2).exec(); + assertThat(inspectImageResponse2, not(nullValue())); + + // Compare whether the image2's parent layer is from image1 so that cache is used + assertThat(inspectImageResponse2.getParent(), equalTo(inspectImageResponse1.getId())); + + } public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index b5df27d37..54ede31dd 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -318,6 +318,29 @@ public void multipleTags() throws Exception { assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); } + @Test + public void cacheFrom() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_25)) { + throw new SkipException("API version should be >= 1.25"); + } + File baseDir1 = fileFromBuildTestResource("CacheFrom/test1"); + String imageId1 = dockerClient.buildImageCmd(baseDir1) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + InspectImageResponse inspectImageResponse1 = dockerClient.inspectImageCmd(imageId1).exec(); + assertThat(inspectImageResponse1, not(nullValue())); + + File baseDir2 = fileFromBuildTestResource("CacheFrom/test2"); + String imageId2 = dockerClient.buildImageCmd(baseDir2).withCacheFrom(new HashSet<>(Arrays.asList(imageId1))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + InspectImageResponse inspectImageResponse2 = dockerClient.inspectImageCmd(imageId2).exec(); + assertThat(inspectImageResponse2, not(nullValue())); + + // Compare whether the image2's parent layer is from image1 so that cache is used + assertThat(inspectImageResponse2.getParent(), equalTo(inspectImageResponse1.getId())); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); From 05a9a74d55fd321ac2285170a56e330306c3c207 Mon Sep 17 00:00:00 2001 From: kannan-ca Date: Wed, 17 May 2017 10:05:05 -0400 Subject: [PATCH 229/780] Used existing queryParamSet method --- .../com/github/dockerjava/netty/exec/BuildImageCmdExec.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java index 321ae63c1..a99dac833 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java @@ -58,10 +58,8 @@ protected Void execute0(BuildImageCmd command, ResultCallback webTarget = webTarget.queryParam("t", command.getTag()); } - if (command.getCacheFrom() != null) { - for (String c: command.getCacheFrom()) { - webTarget = webTarget.queryParam("cachefrom", c); - } + if (command.getCacheFrom() != null && !command.getCacheFrom().isEmpty()) { + webTarget = webTarget.queryParamsSet("cachefrom", command.getCacheFrom()); } if (command.getRemote() != null) { From 5444f05f88b97c4a2963964eb400678910e92e89 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 May 2017 19:30:07 +0300 Subject: [PATCH 230/780] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84f2b27d9..d2da1378a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Change Log ## 3.0.10 +- Support for cache-from in build image command +- Allow multiple tags in build image command - Custom `db` logging type - Allow an explicit Dockerfile location string to be specified to theuild command - Fix image build for docker 17 with 'tagged' word. From b014f26dce76e67e6c133c36079154a710e3c838 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 May 2017 20:01:38 +0300 Subject: [PATCH 231/780] [maven-release-plugin] prepare release 3.0.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8933bad62..0ba096dc5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.10-SNAPSHOT + 3.0.10 docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - HEAD + 3.0.10 From a14ace4f972a3de4cac3ddc3cb0f7006f629cfdf Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Wed, 17 May 2017 20:01:49 +0300 Subject: [PATCH 232/780] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0ba096dc5..10fad3860 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.github.docker-java docker-java jar - 3.0.10 + 3.0.11-SNAPSHOT docker-java https://github.com/docker-java/docker-java @@ -28,7 +28,7 @@ scm:git:git@github.com:docker-java/docker-java.git git@github.com:docker-java/docker-java.git scm:git:git@github.com:docker-java/docker-java.git - 3.0.10 + HEAD From 342feb6f9cd2d3a7d17cf56b36aff6ad6fa02ad3 Mon Sep 17 00:00:00 2001 From: Ted Xiao Date: Tue, 23 May 2017 14:51:22 +0800 Subject: [PATCH 233/780] ignore application/x-tar --- .../github/dockerjava/jaxrs/filter/SelectiveLoggingFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/github/dockerjava/jaxrs/filter/SelectiveLoggingFilter.java b/src/main/java/com/github/dockerjava/jaxrs/filter/SelectiveLoggingFilter.java index 2251d8fad..36256fca0 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/filter/SelectiveLoggingFilter.java +++ b/src/main/java/com/github/dockerjava/jaxrs/filter/SelectiveLoggingFilter.java @@ -24,6 +24,7 @@ public class SelectiveLoggingFilter extends LoggingFilter { Set s = new HashSet(); s.add(MediaType.APPLICATION_OCTET_STREAM); s.add("application/tar"); + s.add("application/x-tar"); SKIPPED_CONTENT = Collections.unmodifiableSet(s); } From c44eba80e7742195e78351ed1bf35452066ff4f1 Mon Sep 17 00:00:00 2001 From: Ted Xiao Date: Tue, 23 May 2017 21:40:06 +0800 Subject: [PATCH 234/780] allow user to call connectionManager's closeIdleConnections --- .../jaxrs/JerseyDockerCmdExecFactory.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java index 4b7f2f67e..1d9d65f0a 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/jaxrs/JerseyDockerCmdExecFactory.java @@ -9,6 +9,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.ws.rs.client.Client; @@ -266,7 +267,7 @@ private void configureProxy(ClientConfig clientConfig, URI originalUri, String p } 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) { @@ -589,4 +590,14 @@ public JerseyDockerCmdExecFactory withClientRequestFilters(ClientRequestFilter.. return this; } + + /** + * release connections from the pool + * + * @param idleSeconds idle seconds, longer than the configured value will be evicted + */ + public void releaseConnection(long idleSeconds) { + this.connManager.closeExpiredConnections(); + this.connManager.closeIdleConnections(idleSeconds, TimeUnit.SECONDS); + } } From d700d721c13de2fd5b60c4e8db107652aa614843 Mon Sep 17 00:00:00 2001 From: Ted Xiao Date: Thu, 18 May 2017 19:16:16 +0800 Subject: [PATCH 235/780] add labels and attachable properties to network --- .../api/command/CreateNetworkCmd.java | 20 ++++++++++ .../github/dockerjava/api/model/Network.java | 25 +++++++++++++ .../core/command/CreateNetworkCmdImpl.java | 37 +++++++++++++++++++ .../command/CreateContainerCmdImplTest.java | 24 ++++++++++++ .../command/CreateNetworkCmdImplTest.java | 34 +++++++++++++++++ 5 files changed, 140 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java index 39989bd13..298e05aca 100644 --- a/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CreateNetworkCmd.java @@ -36,6 +36,12 @@ public interface CreateNetworkCmd extends SyncDockerCmd { @CheckForNull Boolean getEnableIPv6(); + @CheckForNull + Boolean getAttachable(); + + @CheckForNull + Map getLabels(); + /** The new network's name. Required. */ CreateNetworkCmd withName(@Nonnull String name); @@ -54,6 +60,20 @@ public interface CreateNetworkCmd extends SyncDockerCmd { CreateNetworkCmd withEnableIpv6(boolean enableIpv6); + /** + * If enabled, and the network is in the global scope, non-service containers on worker nodes will be able to connect to the network. + * + * @since {@link RemoteApiVersion#VERSION_1_21} + */ + CreateNetworkCmd withAttachable(Boolean attachable); + + /** + * Add label for network + * + * @since {@link RemoteApiVersion#VERSION_1_24} + */ + CreateNetworkCmd withLabels(Map labels); + interface Exec extends DockerCmdSyncExec { } } diff --git a/src/main/java/com/github/dockerjava/api/model/Network.java b/src/main/java/com/github/dockerjava/api/model/Network.java index c0f9f36eb..2a532f88c 100644 --- a/src/main/java/com/github/dockerjava/api/model/Network.java +++ b/src/main/java/com/github/dockerjava/api/model/Network.java @@ -37,6 +37,12 @@ public class Network implements Serializable { @JsonProperty("Options") private Map options; + @JsonProperty("Attachable") + private Boolean attachable; + + @JsonProperty("Labels") + public Map labels; + public String getId() { return id; } @@ -65,6 +71,14 @@ public Map getOptions() { return options; } + public Boolean isAttachable() { + return attachable; + } + + public Map getLabels() { + return labels; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); @@ -158,6 +172,9 @@ public static class Config { @JsonProperty("Gateway") private String gateway; + @JsonProperty("NetworkID") + private String networkID; + public String getSubnet() { return subnet; } @@ -184,6 +201,14 @@ public Config withGateway(String gateway) { this.gateway = gateway; return this; } + + public String getNetworkID() { + return networkID; + } + + public void setNetworkID(String networkID) { + this.networkID = networkID; + } } } } diff --git a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java index 834aa6905..e6cff4c09 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateNetworkCmdImpl.java @@ -10,6 +10,8 @@ import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.Network.Ipam; +import static com.google.common.base.Preconditions.checkNotNull; + public class CreateNetworkCmdImpl extends AbstrDockerCmd implements CreateNetworkCmd { @@ -34,6 +36,12 @@ public class CreateNetworkCmdImpl extends AbstrDockerCmd labels; + public CreateNetworkCmdImpl(DockerCmdSyncExec execution) { super(execution); } @@ -114,4 +122,33 @@ public CreateNetworkCmd withEnableIpv6(boolean enableIpv6) { this.enableIpv6 = enableIpv6; return this; } + + @Override + public Boolean getAttachable() { + return this.attachable; + } + + /** + * {@inheritDoc} + */ + @Override + public CreateNetworkCmd withAttachable(Boolean attachable) { + this.attachable = attachable; + return this; + } + + @Override + public Map getLabels() { + return labels; + } + + /** + * {@inheritDoc} + */ + @Override + public CreateNetworkCmd withLabels(Map labels) { + checkNotNull(labels, "labels was not specified"); + this.labels = labels; + return this; + } } diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 7c625ea94..53c9d9ad0 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -777,4 +777,28 @@ public void createContainerWithShmPidsLimit() throws DockerException { assertThat(inspectContainerResponse.getHostConfig().getPidsLimit(), is(hostConfig.getPidsLimit())); } + + @Test + public void createContainerWithNetworkID() { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_24)) { + throw new SkipException("API version should be >= 1.24"); + } + String networkName = "net-" + UUID.randomUUID().toString(); + Map labels=new HashMap<>(); + labels.put("com.example.label","test"); + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName) + .withLabels(labels).withAttachable(true).exec(); + String networkId = createNetworkResponse.getId(); + CreateContainerResponse createContainerResponse = dockerClient.createContainerCmd(BUSYBOX_IMAGE).withLabels(labels).withCmd("true").exec(); + String containerId = createContainerResponse.getId(); + dockerClient.connectToNetworkCmd().withContainerId(containerId).withNetworkId(networkId).exec(); + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(containerId).exec(); + ContainerNetwork containerNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get(networkName); + if(containerNetwork==null){ + // swarm node used network id + containerNetwork = inspectContainerResponse.getNetworkSettings().getNetworks().get(networkId); + } + assertThat(containerNetwork, notNullValue()); + } } diff --git a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java index cc70331f2..7dae2e1d6 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateNetworkCmdImplTest.java @@ -4,7 +4,9 @@ import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.model.Network; import com.github.dockerjava.client.AbstractDockerClientTest; +import com.github.dockerjava.core.RemoteApiVersion; import org.testng.ITestResult; +import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; @@ -12,6 +14,10 @@ import org.testng.annotations.Test; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import static com.github.dockerjava.utils.TestUtils.getVersion; @Test(groups = "integration") public class CreateNetworkCmdImplTest extends AbstractDockerClientTest { @@ -64,4 +70,32 @@ public void createNetworkWithIpamConfig() throws DockerException { assertEquals(network.getDriver(), "bridge"); assertEquals("10.67.79.0/24", network.getIpam().getConfig().iterator().next().getSubnet()); } + + @Test + public void createAttachableNetwork() throws DockerException { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_24)) { + throw new SkipException("API version should be >= 1.24"); + } + String networkName = "createAttachableNetwork"; + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).withAttachable(true).exec(); + assertNotNull(createNetworkResponse.getId()); + Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); + assertTrue(network.isAttachable()); + } + + @Test + public void createNetworkWithLabel() throws DockerException { + final RemoteApiVersion apiVersion = getVersion(dockerClient); + if (!apiVersion.isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) { + throw new SkipException("API version should be >= 1.21"); + } + String networkName = "createNetworkWithLabel"; + Map labels=new HashMap<>(); + labels.put("com.example.usage","test"); + CreateNetworkResponse createNetworkResponse = dockerClient.createNetworkCmd().withName(networkName).withLabels(labels).exec(); + assertNotNull(createNetworkResponse.getId()); + Network network = dockerClient.inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); + assertEquals(network.getLabels(), labels); + } } From a9b78cc4f5ec45c0bdeec2e68136f8a59b96b1c3 Mon Sep 17 00:00:00 2001 From: Ted Xiao Date: Tue, 23 May 2017 18:14:36 +0800 Subject: [PATCH 236/780] clean tmp file after upload --- .idea/codeStyleSettings.xml | 1 + .../CopyArchiveToContainerCmdImpl.java | 30 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 6f3c789b4..9e5672189 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -5,6 +5,7 @@