From 20cabcdc050f4759e46921ff00cdcf820ae9d0a1 Mon Sep 17 00:00:00 2001 From: Alexander Kampmann Date: Tue, 28 Oct 2014 13:43:15 +0100 Subject: [PATCH 1/5] support for unix sockets --- pom.xml | 25 +- .../dockerjava/jaxrs/ApacheUnixSocket.java | 327 ++++++++++++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 83 ++++- .../jaxrs/UnixConnectionSocketFactory.java | 85 +++++ .../dockerjava/api/model/PortsTest.java | 74 ++-- .../dockerjava/core/UnixSocketTest.java | 17 + 6 files changed, 553 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/jaxrs/ApacheUnixSocket.java create mode 100644 src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java create mode 100644 src/test/java/com/github/dockerjava/core/UnixSocketTest.java diff --git a/pom.xml b/pom.xml index 72e9dfd0f..302eb7a36 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,13 @@ + + + jcenter + http://jcenter.bintray.com + + + UTF-8 UTF-8 @@ -61,9 +68,9 @@ 2.6 1.7.5 1.3.9 - 0.3 18.0 1.51 + 2014-09-26T18-52-33 1.0.1 @@ -93,12 +100,23 @@ + + org.glassfish.jersey.connectors + jersey-apache-connector + ${jersey.version} + org.glassfish.jersey.core jersey-client ${jersey.version} + + de.gesellix + unix-socket-factory + ${unix-socket-factory.version} + + org.apache.commons commons-compress @@ -120,11 +138,6 @@ ${commons-io.version} - - com.github.jnr - jnr-unixsocket - ${jnr.unixsocket.version} - org.slf4j diff --git a/src/main/java/com/github/dockerjava/jaxrs/ApacheUnixSocket.java b/src/main/java/com/github/dockerjava/jaxrs/ApacheUnixSocket.java new file mode 100644 index 000000000..a4adb1bb7 --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/ApacheUnixSocket.java @@ -0,0 +1,327 @@ +package com.github.dockerjava.jaxrs; +/* + * Copyright (c) 2014 Spotify AB. + * + * 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. + */ + + + +import com.google.common.collect.Queues; + +import org.newsclub.net.unix.AFUNIXSocket; + +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.nio.channels.SocketChannel; +import java.util.Queue; + +/** + * Provides a socket that wraps an org.newsclub.net.unix.AFUNIXSocket and delays setting options + * until the socket is connected. This is necessary because the Apache HTTP client attempts to + * set options prior to connecting the socket, which doesn't work for Unix sockets since options + * are being set on the underlying file descriptor. Until the socket is connected, the file + * descriptor doesn't exist. + * + * This class also noop's any calls to setReuseAddress, which is called by the Apache client but + * isn't supported by AFUnixSocket. + */ +public class ApacheUnixSocket extends Socket { + + private final AFUNIXSocket inner; + + private final Queue optionsToSet = Queues.newArrayDeque(); + + public ApacheUnixSocket() throws IOException { + this.inner = AFUNIXSocket.newInstance(); + } + + @Override + public void connect(final SocketAddress endpoint) throws IOException { + inner.connect(endpoint); + setAllSocketOptions(); + } + + @Override + public void connect(final SocketAddress endpoint, final int timeout) throws IOException { + inner.connect(endpoint, timeout); + setAllSocketOptions(); + } + + @Override + public void bind(final SocketAddress bindpoint) throws IOException { + inner.bind(bindpoint); + setAllSocketOptions(); + } + + @Override + public InetAddress getInetAddress() { + return inner.getInetAddress(); + } + + @Override + public InetAddress getLocalAddress() { + return inner.getLocalAddress(); + } + + @Override + public int getPort() { + return inner.getPort(); + } + + @Override + public int getLocalPort() { + return inner.getLocalPort(); + } + + @Override + public SocketAddress getRemoteSocketAddress() { + return inner.getRemoteSocketAddress(); + } + + @Override + public SocketAddress getLocalSocketAddress() { + return inner.getLocalSocketAddress(); + } + + @Override + public SocketChannel getChannel() { + return inner.getChannel(); + } + + @Override + public InputStream getInputStream() throws IOException { + return inner.getInputStream(); + } + + @Override + public OutputStream getOutputStream() throws IOException { + return inner.getOutputStream(); + } + + private void setSocketOption(final SocketOptionSetter s) throws SocketException { + if (inner.isConnected()) { + s.run(); + } else { + if (!optionsToSet.offer(s)) { + throw new SocketException("Failed to queue option"); + } + } + } + + private void setAllSocketOptions() throws SocketException { + for (SocketOptionSetter s : optionsToSet) { + s.run(); + } + } + + @Override + public void setTcpNoDelay(final boolean on) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setTcpNoDelay(on); + } + }); + } + + @Override + public boolean getTcpNoDelay() throws SocketException { + return inner.getTcpNoDelay(); + } + + @Override + public void setSoLinger(final boolean on, final int linger) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setSoLinger(on, linger); + } + }); + } + + @Override + public int getSoLinger() throws SocketException { + return inner.getSoLinger(); + } + + @Override + public void sendUrgentData(final int data) throws IOException { + inner.sendUrgentData(data); + } + + @Override + public void setOOBInline(final boolean on) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setOOBInline(on); + } + }); + } + + @Override + public boolean getOOBInline() throws SocketException { + return inner.getOOBInline(); + } + + @Override + public synchronized void setSoTimeout(final int timeout) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setSoTimeout(timeout); + } + }); + } + + @Override + public synchronized int getSoTimeout() throws SocketException { + return inner.getSoTimeout(); + } + + @Override + public synchronized void setSendBufferSize(final int size) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setSendBufferSize(size); + } + }); + } + + @Override + public synchronized int getSendBufferSize() throws SocketException { + return inner.getSendBufferSize(); + } + + @Override + public synchronized void setReceiveBufferSize(final int size) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setReceiveBufferSize(size); + } + }); + } + + @Override + public synchronized int getReceiveBufferSize() throws SocketException { + return inner.getReceiveBufferSize(); + } + + @Override + public void setKeepAlive(final boolean on) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setKeepAlive(on); + } + }); + } + + @Override + public boolean getKeepAlive() throws SocketException { + return inner.getKeepAlive(); + } + + @Override + public void setTrafficClass(final int tc) throws SocketException { + setSocketOption(new SocketOptionSetter() { + @Override + public void run() throws SocketException { + inner.setTrafficClass(tc); + } + }); + } + + @Override + public int getTrafficClass() throws SocketException { + return inner.getTrafficClass(); + } + + @Override + public void setReuseAddress(final boolean on) throws SocketException { + // not supported: Apache client tries to set it, but we want to just ignore it + } + + @Override + public boolean getReuseAddress() throws SocketException { + return inner.getReuseAddress(); + } + + @Override + public synchronized void close() throws IOException { + inner.close(); + } + + @Override + public void shutdownInput() throws IOException { + inner.shutdownInput(); + } + + @Override + public void shutdownOutput() throws IOException { + inner.shutdownOutput(); + } + + @Override + public String toString() { + return inner.toString(); + } + + @Override + public boolean isConnected() { + return inner.isConnected(); + } + + @Override + public boolean isBound() { + return inner.isBound(); + } + + @Override + public boolean isClosed() { + return inner.isClosed(); + } + + @Override + public boolean isInputShutdown() { + return inner.isInputShutdown(); + } + + @Override + public boolean isOutputShutdown() { + return inner.isOutputShutdown(); + } + + @Override + public void setPerformancePreferences(final int connectionTime, final int latency, + final int bandwidth) { + inner.setPerformancePreferences(connectionTime, latency, bandwidth); + } + + interface SocketOptionSetter { + void run() throws SocketException; + } +} diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 862824fcc..f9033a487 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -1,28 +1,69 @@ package com.github.dockerjava.jaxrs; +import java.io.IOException; +import java.net.URI; +import java.rmi.registry.Registry; +import java.security.KeyStore; +import java.security.Security; +import java.util.logging.Logger; + +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; + +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.SslConfigurator; +import org.glassfish.jersey.apache.connector.ApacheClientProperties; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; + import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import com.github.dockerjava.api.DockerClientException; -import com.github.dockerjava.api.command.*; +import com.github.dockerjava.api.command.AttachContainerCmd; +import com.github.dockerjava.api.command.AuthCmd; +import com.github.dockerjava.api.command.BuildImageCmd; +import com.github.dockerjava.api.command.CommitCmd; +import com.github.dockerjava.api.command.ContainerDiffCmd; +import com.github.dockerjava.api.command.CopyFileFromContainerCmd; +import com.github.dockerjava.api.command.CreateContainerCmd; +import com.github.dockerjava.api.command.CreateImageCmd; +import com.github.dockerjava.api.command.DockerCmdExecFactory; +import com.github.dockerjava.api.command.EventsCmd; +import com.github.dockerjava.api.command.InfoCmd; +import com.github.dockerjava.api.command.InspectContainerCmd; +import com.github.dockerjava.api.command.InspectImageCmd; +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.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.RestartContainerCmd; +import com.github.dockerjava.api.command.SearchImagesCmd; +import com.github.dockerjava.api.command.StartContainerCmd; +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.core.CertificateUtils; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.jaxrs.util.JsonClientFilter; import com.github.dockerjava.jaxrs.util.ResponseStatusExceptionFilter; import com.github.dockerjava.jaxrs.util.SelectiveLoggingFilter; import com.google.common.base.Preconditions; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.glassfish.jersey.CommonProperties; -import org.glassfish.jersey.SslConfigurator; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; - -import javax.net.ssl.SSLContext; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; -import java.io.IOException; -import java.security.KeyStore; -import java.security.Security; -import java.util.logging.Logger; public class DockerCmdExecFactoryImpl implements DockerCmdExecFactory { @@ -50,6 +91,9 @@ public void init(DockerClientConfig dockerClientConfig) { clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout); } + clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, + new PoolingHttpClientConnectionManager(getSchemeRegistry(dockerClientConfig.getUri()))); + ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); String dockerCertPath = dockerClientConfig.getDockerCertPath(); @@ -101,6 +145,15 @@ public void init(DockerClientConfig dockerClientConfig) { } + private org.apache.http.config.Registry getSchemeRegistry(final URI originalUri) { + return RegistryBuilder + .create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .register("unix", new UnixConnectionSocketFactory(originalUri)) + .build(); + } + protected WebTarget getBaseResource() { Preconditions.checkNotNull(baseResource, "Factory not initialized. You probably forgot to call init()!"); return baseResource; diff --git a/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java b/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java new file mode 100644 index 000000000..4b6cfbba3 --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/UnixConnectionSocketFactory.java @@ -0,0 +1,85 @@ +package com.github.dockerjava.jaxrs; +/* + * Copyright (c) 2014 Spotify AB. + * + * 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. + */ + + + +import org.apache.http.HttpHost; +import org.apache.http.annotation.Immutable; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.protocol.HttpContext; +import org.newsclub.net.unix.AFUNIXSocketAddress; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.net.URI; + +/** + * Provides a ConnectionSocketFactory for connecting Apache HTTP clients to Unix sockets. + */ +@Immutable +public class UnixConnectionSocketFactory implements ConnectionSocketFactory { + + private File socketFile; + + public UnixConnectionSocketFactory(final URI socketUri) { + super(); + + final String filename = socketUri.toString() + .replaceAll("^unix:///", "unix://localhost/") + .replaceAll("^unix://localhost", ""); + + this.socketFile = new File(filename); + } + + public static URI sanitizeUri(final URI uri) { + if (uri.getScheme().equals("unix")) { + return URI.create("unix://localhost:80"); + } else { + return uri; + } + } + + @Override + public Socket createSocket(final HttpContext context) throws IOException { + return new ApacheUnixSocket(); + } + + @Override + public Socket connectSocket(final int connectTimeout, + final Socket socket, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException { + try { + socket.connect(new AFUNIXSocketAddress(socketFile), connectTimeout); + } catch (SocketTimeoutException e) { + throw new ConnectTimeoutException(e, null, remoteAddress.getAddress()); + } + + return socket; + } +} diff --git a/src/test/java/com/github/dockerjava/api/model/PortsTest.java b/src/test/java/com/github/dockerjava/api/model/PortsTest.java index 6a6c5e44e..f60be4354 100644 --- a/src/test/java/com/github/dockerjava/api/model/PortsTest.java +++ b/src/test/java/com/github/dockerjava/api/model/PortsTest.java @@ -1,37 +1,37 @@ -package com.github.dockerjava.api.model; - -import static org.testng.Assert.assertEquals; - -import java.util.Map; - -import org.testng.annotations.Test; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.dockerjava.api.model.Ports.Binding; - -public class PortsTest { - private final ObjectMapper objectMapper = new ObjectMapper(); - private final String jsonWithDoubleBindingForOnePort = - "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}"; - - @Test - public void deserializingPortWithMultipleBindings() throws Exception { - Ports ports = objectMapper.readValue(jsonWithDoubleBindingForOnePort, Ports.class); - Map map = ports.getBindings(); - assertEquals(map.size(), 1); - - 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)); - } - - @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)); - assertEquals(objectMapper.writeValueAsString(ports), jsonWithDoubleBindingForOnePort); - } - -} +package com.github.dockerjava.api.model; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Ports.Binding; + +public class PortsTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + private final String jsonWithDoubleBindingForOnePort = + "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}"; + + @Test + public void deserializingPortWithMultipleBindings() throws Exception { + Ports ports = objectMapper.readValue(jsonWithDoubleBindingForOnePort, Ports.class); + Map map = ports.getBindings(); + assertEquals(map.size(), 1); + + 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)); + } + + @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)); + assertEquals(objectMapper.writeValueAsString(ports), jsonWithDoubleBindingForOnePort); + } + +} diff --git a/src/test/java/com/github/dockerjava/core/UnixSocketTest.java b/src/test/java/com/github/dockerjava/core/UnixSocketTest.java new file mode 100644 index 000000000..31a07d368 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/UnixSocketTest.java @@ -0,0 +1,17 @@ +package com.github.dockerjava.core; + +import org.testng.annotations.Test; + +import com.github.dockerjava.api.DockerClient; + +public class UnixSocketTest { + + @Test + public void testUnixSocket() { + DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder() + .withUri("unix://localhost/var/run/docker.sock") + .build(); + DockerClient docker = DockerClientBuilder.getInstance(config).build(); + docker.pingCmd(); + } +} From 5f1737b6f2260ca9042c3377cdeecbee0594063d Mon Sep 17 00:00:00 2001 From: Alexander Kampmann Date: Tue, 28 Oct 2014 17:37:29 +0100 Subject: [PATCH 2/5] fixed remaining problems --- .../dockerjava/core/DockerClientConfig.java | 8 +- .../jaxrs/DockerCmdExecFactoryImpl.java | 12 +- .../dockerjava/core/UnixSocketTest.java | 104 +++++++++++++++++- 3 files changed, 113 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index c12585a54..941577eb9 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -36,7 +36,7 @@ public class DockerClientConfig { .put(DOCKER_CERT_PATH_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY) .build(); private static final String DOCKER_IO_PROPERTIES_PROPERTY = "docker.io.properties"; - private final URI uri; + private URI uri; private final String version, username, password, email, dockerCertPath; private final Integer readTimeout; private final boolean loggingFilterEnabled; @@ -176,7 +176,11 @@ public URI getUri() { return uri; } - public String getVersion() { + public void setUri(URI uri) { + this.uri = uri; + } + + public String getVersion() { return version; } diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index f9033a487..20eb16855 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URI; -import java.rmi.registry.Registry; import java.security.KeyStore; import java.security.Security; import java.util.logging.Logger; @@ -21,6 +20,7 @@ import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.SslConfigurator; 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; @@ -76,6 +76,7 @@ public void init(DockerClientConfig dockerClientConfig) { Preconditions.checkNotNull(dockerClientConfig, "config was not specified"); ClientConfig clientConfig = new ClientConfig(); + clientConfig.connectorProvider(new ApacheConnectorProvider()); clientConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); clientConfig.register(ResponseStatusExceptionFilter.class); @@ -91,8 +92,9 @@ public void init(DockerClientConfig dockerClientConfig) { clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout); } - clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, - new PoolingHttpClientConnectionManager(getSchemeRegistry(dockerClientConfig.getUri()))); + URI originalUri = dockerClientConfig.getUri(); + clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, + new PoolingHttpClientConnectionManager(getSchemeRegistry(originalUri))); ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); @@ -135,6 +137,10 @@ public void init(DockerClientConfig dockerClientConfig) { client = clientBuilder.build(); + if (originalUri.getScheme().equals("unix")) { + dockerClientConfig.setUri(UnixConnectionSocketFactory.sanitizeUri(originalUri)); + } + WebTarget webResource = client.target(dockerClientConfig.getUri()); if (dockerClientConfig.getVersion() == null || dockerClientConfig.getVersion().isEmpty()) { diff --git a/src/test/java/com/github/dockerjava/core/UnixSocketTest.java b/src/test/java/com/github/dockerjava/core/UnixSocketTest.java index 31a07d368..dca0c85f3 100644 --- a/src/test/java/com/github/dockerjava/core/UnixSocketTest.java +++ b/src/test/java/com/github/dockerjava/core/UnixSocketTest.java @@ -1,17 +1,109 @@ package com.github.dockerjava.core; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.LineIterator; +import org.testng.Assert; import org.testng.annotations.Test; import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +@Test(groups = "unix") public class UnixSocketTest { @Test - public void testUnixSocket() { - DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder() - .withUri("unix://localhost/var/run/docker.sock") - .build(); - DockerClient docker = DockerClientBuilder.getInstance(config).build(); - docker.pingCmd(); + public void testUnixSocketPing() { + DockerClientConfig config = DockerClientConfig + .createDefaultConfigBuilder() + .withVersion("1.14") + .withUri("unix://localhost/var/run/docker.sock").build(); + DockerClient docker = DockerClientBuilder.getInstance(config) + .build(); + docker.pingCmd(); + } + + @Test + public void testUnixSocketCat() throws IOException { + String image = "test"; + String containerId = null; + + DockerClientConfig config = DockerClientConfig + .createDefaultConfigBuilder() + .withVersion("1.14") + .withUri("unix://localhost/var/run/docker.sock").build(); + DockerClient docker = DockerClientBuilder.getInstance(config).build(); + try { + + // construct a tar archive + ByteArrayOutputStream os = new ByteArrayOutputStream(); + String text = "Hello Docker!\n"; + TarArchiveOutputStream tarStream = new TarArchiveOutputStream(os); + // add some files + putToArchive(tarStream, "Dockerfile", + "FROM busybox\nADD testdata /testdata\n".getBytes()); + putToArchive(tarStream, "testdata/hello1", text.getBytes()); + tarStream.close(); + + ByteArrayInputStream tarIn = new ByteArrayInputStream(os.toByteArray()); + + InputStream in = docker.buildImageCmd(tarIn).withTag(image).exec(); + readStream(System.out, in); + + CreateContainerResponse resp = docker.createContainerCmd("test") + .withCmd("cat", "hello1") + .withWorkingDir("/testdata") + .exec(); + containerId = resp.getId(); + Assert.assertEquals(null, resp.getWarnings()); + + docker.startContainerCmd(resp.getId()).exec(); + + int ex = docker.waitContainerCmd(resp.getId()).exec(); + Assert.assertEquals(ex, 0); + + StringBuilder sb = new StringBuilder(); + InputStream stream = docker.logContainerCmd(resp.getId()) + .withStdErr() + .withStdOut() + .exec(); + readStream(sb, stream); + assertThat(sb.toString(), endsWith(text)); + } finally { + if(null != containerId) { + docker.removeContainerCmd(containerId).exec(); + } + docker.removeImageCmd(image).exec(); + + } + } + + private void readStream(Appendable sb, InputStream stream) + throws IOException { + LineIterator itr = IOUtils.lineIterator( + stream, "UTF-8"); + + while(itr.hasNext()) { + sb.append(itr.next()); + sb.append("\n"); + } + } + + private void putToArchive(TarArchiveOutputStream tarStream, String name, + byte[] content) throws IOException { + TarArchiveEntry dockerfile = new TarArchiveEntry(name); + dockerfile.setSize(content.length); + tarStream.putArchiveEntry(dockerfile); + tarStream.write(content); + tarStream.closeArchiveEntry(); } } From 2692d12f70b7ccfa465eaebf078072fd6ad789f4 Mon Sep 17 00:00:00 2001 From: Alexander Kampmann Date: Thu, 30 Oct 2014 15:08:13 +0100 Subject: [PATCH 3/5] fixed non-closed streams --- .../dockerjava/api/command/EventCallback.java | 1 + .../dockerjava/jaxrs/ContainerDiffCmdExec.java | 3 ++- .../github/dockerjava/jaxrs/EventsCmdExec.java | 2 +- .../dockerjava/jaxrs/PullImageCmdExec.java | 3 ++- .../jaxrs/RemoveContainerCmdExec.java | 4 ++-- .../dockerjava/jaxrs/RemoveImageCmdExec.java | 2 +- .../util/ResponseStatusExceptionFilter.java | 5 ++++- .../client/AbstractDockerClientTest.java | 1 + .../CopyFileFromContainerCmdImplTest.java | 18 ++++++++++++++++-- .../core/command/EventsCmdImplTest.java | 16 ++++++++++++++-- .../core/command/PullImageCmdImplTest.java | 4 +++- .../core/command/PushImageCmdImplTest.java | 1 - 12 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/command/EventCallback.java b/src/main/java/com/github/dockerjava/api/command/EventCallback.java index 45ac34dc8..17f796aaa 100644 --- a/src/main/java/com/github/dockerjava/api/command/EventCallback.java +++ b/src/main/java/com/github/dockerjava/api/command/EventCallback.java @@ -9,4 +9,5 @@ public interface EventCallback { public void onEvent(Event event); public void onException(Throwable throwable); public void onCompletion(int numEvents); + public boolean isReceiving(); } diff --git a/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java index 0a657ed90..2b7059b33 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java @@ -26,7 +26,8 @@ protected List execute(ContainerDiffCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/changes").resolveTemplate("id", command.getContainerId()); LOGGER.trace("GET: {}", webResource); - return webResource.request().accept(MediaType.APPLICATION_JSON).get(new GenericType>() { + return webResource.request().accept(MediaType.APPLICATION_JSON) + .get(new GenericType>() { }); } diff --git a/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java index 545d7db98..ffd757e93 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java @@ -67,7 +67,7 @@ public Void call() throws Exception { response = webTarget.request().get(Response.class); InputStream inputStream = response.readEntity(InputStream.class); JsonParser jp = JSON_FACTORY.createParser(inputStream); - while (jp.nextToken() != JsonToken.END_OBJECT && !jp.isClosed()) { + while (jp.nextToken() != JsonToken.END_OBJECT && !jp.isClosed() && eventCallback.isReceiving()) { eventCallback.onEvent(OBJECT_MAPPER.readValue(jp, Event.class)); numEvents++; } diff --git a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java index 4ac190be4..42352170c 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java @@ -31,7 +31,8 @@ protected InputStream execute(PullImageCmd command) { LOGGER.trace("POST: {}", webResource); return webResource.request() .accept(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .post(entity(Response.class, MediaType.APPLICATION_JSON)).readEntity(InputStream.class); + .post(entity(Response.class, MediaType.APPLICATION_JSON)) + .readEntity(InputStream.class); } } diff --git a/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java index 7f45bdda2..7a479ce2f 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java @@ -23,8 +23,8 @@ protected Void execute(RemoveContainerCmd command) { .queryParam("force", command.hasForceEnabled() ? "1" : "0"); LOGGER.trace("DELETE: {}", webResource); - String response = webResource.request().accept(MediaType.APPLICATION_JSON).delete(String.class); - LOGGER.trace("Response: {}", response); + /*String response = */webResource.request().accept(MediaType.APPLICATION_JSON).delete().close(); +// LOGGER.trace("Response: {}", response); return null; } diff --git a/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java index 54fb327b4..6bfeecd71 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java @@ -23,7 +23,7 @@ protected Void execute(RemoveImageCmd command) { .queryParam("noprune", command.hasNoPruneEnabled() ? "1" : "0"); LOGGER.trace("DELETE: {}", webResource); - webResource.request().delete(Response.class); + webResource.request().delete().close(); return null; } diff --git a/src/main/java/com/github/dockerjava/jaxrs/util/ResponseStatusExceptionFilter.java b/src/main/java/com/github/dockerjava/jaxrs/util/ResponseStatusExceptionFilter.java index 61d97f93b..0e474df59 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/util/ResponseStatusExceptionFilter.java +++ b/src/main/java/com/github/dockerjava/jaxrs/util/ResponseStatusExceptionFilter.java @@ -2,6 +2,7 @@ import java.io.EOFException; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import javax.ws.rs.client.ClientRequestContext; @@ -63,7 +64,9 @@ public String getBodyAsMessage(ClientResponseContext responseContext) if (contentLength != -1) { byte[] buffer = new byte[contentLength]; try { - IOUtils.readFully(responseContext.getEntityStream(), buffer); + InputStream entityStream = responseContext.getEntityStream(); + IOUtils.readFully(entityStream, buffer); + entityStream.close(); } catch (EOFException e) { return null; diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index 385508b68..ed066b5fb 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -95,6 +95,7 @@ protected String asString(InputStream response) { logwriter.write(line + (itr.hasNext() ? "\n" : "")); //LOG.info("line: "+line); } + response.close(); return logwriter.toString(); } catch (IOException e) { 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 945b61983..a4d81e4e3 100644 --- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java @@ -4,6 +4,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.client.AbstractDockerClientTest; +import org.apache.commons.io.IOUtils; import org.testng.ITestResult; import org.testng.annotations.*; @@ -49,8 +50,21 @@ public void copyFromContainer() throws Exception { dockerClient.startContainerCmd(container.getId()).exec(); - InputStream response = dockerClient.copyFileFromContainerCmd(container.getId(), "/test").exec(); - assertTrue(response.available() > 0, "The file was not copied from the container."); + InputStream response = null; + try { + response = dockerClient.copyFileFromContainerCmd(container.getId(), "/test").exec(); + boolean condition = response.available() > 0; + + // read the stream fully. Otherwise, the underlying stream will not be closed. + for(String line:IOUtils.readLines(response)) { + assertThat("", null != line); + } + + assertTrue(condition, "The file was not copied from the container."); + } finally { + System.out.println("Close copyFromContainer stream."); + response.close(); + } } @Test 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 6935227bc..8c068b6df 100644 --- a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java @@ -19,6 +19,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; @Test(groups = "integration") public class EventsCmdImplTest extends AbstractDockerClientTest { @@ -78,7 +79,7 @@ public void testEventStreaming() throws InterruptedException, IOException { TimeUnit.SECONDS.sleep(1); CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS); - EventCallback eventCallback = new EventCallbackTest(countDownLatch); + EventCallbackTest eventCallback = new EventCallbackTest(countDownLatch); EventsCmd eventsCmd = dockerClient.eventsCmd(eventCallback).withSince(getEpochTime()); ExecutorService executorService = eventsCmd.exec(); @@ -87,6 +88,7 @@ public void testEventStreaming() throws InterruptedException, IOException { boolean zeroCount = countDownLatch.await(5, TimeUnit.SECONDS); executorService.shutdown(); + eventCallback.close(); assertTrue(zeroCount, "Expected 4 events, [create, start, die, stop]"); } @@ -105,12 +107,17 @@ private int generateEvents() { private class EventCallbackTest implements EventCallback { private final CountDownLatch countDownLatch; + private final AtomicBoolean isReceiving = new AtomicBoolean(true); public EventCallbackTest(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } - @Override + public void close() { + isReceiving.set(false); + } + + @Override public void onEvent(Event event) { LOG.info("Received event #{}: {}", countDownLatch.getCount(), event); countDownLatch.countDown(); @@ -125,5 +132,10 @@ public void onException(Throwable throwable) { public void onCompletion(int numEvents) { LOG.info("Number of events received: {}", numEvents); } + + @Override + public boolean isReceiving() { + return isReceiving.get(); + } } } diff --git a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java index 84af9e72d..7f0e146c1 100644 --- a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java @@ -97,7 +97,9 @@ public void testPullImage() throws DockerException, IOException { public void testPullNonExistingImage() throws DockerException, IOException { // does not throw an exception - dockerClient.pullImageCmd("nonexisting/foo").exec(); + InputStream is = dockerClient.pullImageCmd("nonexisting/foo").exec(); + // stream needs to be fully read in order to close the underlying connection + this.asString(is); try { dockerClient.pullImageCmd("non-existing/foo").exec(); 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 b12ac4ec2..ecafbb78e 100644 --- a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java @@ -77,6 +77,5 @@ public void pushExistentImage() throws Exception { assertThat(asString(dockerClient.pushImageCmd(username + "/xxx").exec()), containsString("error")); } - } From 92949e0e4eff8b36abf3e3c5fb945c4c08729f37 Mon Sep 17 00:00:00 2001 From: Alexander Kampmann Date: Fri, 7 Nov 2014 15:11:56 +0100 Subject: [PATCH 4/5] added config options for connection pool size --- .../dockerjava/core/DockerClientConfig.java | 43 +++++++++++++++++-- .../jaxrs/DockerCmdExecFactoryImpl.java | 5 ++- .../core/DockerClientConfigTest.java | 2 +- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index 941577eb9..0fa66eca7 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -22,6 +22,10 @@ public class DockerClientConfig { // this is really confusing, as there are two ways to spell it private static final String DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY = "docker.io.enableLoggingFilter"; private static final String DOCKER_IO_DOCKER_CERT_PATH_PROPERTY = "docker.io.dockerCertPath"; + // connection pooling properties + private static final String DOCKER_IO_MAX_PER_ROUTE_PROPERTY = "docker.io.perRouteConnections"; + private static final String DOCKER_IO_MAX_TOTAL_PROPERTY = "docker.io.totalConnections"; + /** * A map from the environment name to the interval name. */ @@ -40,8 +44,13 @@ public class DockerClientConfig { private final String version, username, password, email, dockerCertPath; private final Integer readTimeout; private final boolean loggingFilterEnabled; + + private final int maxTotalConnections; + private final int maxPerRouteConnections; - DockerClientConfig(URI uri, String version, String username, String password, String email, String dockerCertPath, Integer readTimeout, boolean loggingFilterEnabled) { + DockerClientConfig(URI uri, String version, String username, String password, String email, + String dockerCertPath, Integer readTimeout, boolean loggingFilterEnabled, + int maxTotalConns, int maxPerRouteConns) { this.uri = uri; this.version = version; this.username = username; @@ -50,6 +59,9 @@ public class DockerClientConfig { this.dockerCertPath = dockerCertPath; this.readTimeout = readTimeout; this.loggingFilterEnabled = loggingFilterEnabled; + + this.maxTotalConnections = maxTotalConns; + this.maxPerRouteConnections = maxPerRouteConns; } private static Properties loadIncludedDockerProperties(Properties systemProperties) { @@ -258,7 +270,7 @@ public String toString() { public static class DockerClientConfigBuilder { private URI uri; private String version, username, password, email, dockerCertPath; - private Integer readTimeout; + private Integer readTimeout, maxTotalConnections, maxPerRouteConnections; private boolean loggingFilterEnabled; /** @@ -275,7 +287,10 @@ public DockerClientConfigBuilder withProperties(Properties p) { .withEmail(p.getProperty(DOCKER_IO_EMAIL_PROPERTY)) .withReadTimeout(Integer.valueOf(p.getProperty(DOCKER_IO_READ_TIMEOUT_PROPERTY, "0"))) .withLoggingFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, "true"))) - .withDockerCertPath(p.getProperty(DOCKER_IO_DOCKER_CERT_PATH_PROPERTY)); + .withDockerCertPath(p.getProperty(DOCKER_IO_DOCKER_CERT_PATH_PROPERTY)) + .withMaxPerRouteConnections(Integer.valueOf(p.getProperty(DOCKER_IO_MAX_PER_ROUTE_PROPERTY, "2"))) + .withMaxTotalConnections(Integer.valueOf(p.getProperty(DOCKER_IO_MAX_TOTAL_PROPERTY, "20"))) + ; } public final DockerClientConfigBuilder withUri(String uri) { @@ -308,6 +323,16 @@ public final DockerClientConfigBuilder withReadTimeout(Integer readTimeout) { this.readTimeout = readTimeout; return this; } + + public final DockerClientConfigBuilder withMaxTotalConnections(Integer maxTotalConnections) { + this.maxTotalConnections = maxTotalConnections; + return this; + } + + public final DockerClientConfigBuilder withMaxPerRouteConnections(Integer maxPerRouteConnections) { + this.maxPerRouteConnections = maxPerRouteConnections; + return this; + } public final DockerClientConfigBuilder withLoggingFilter(boolean loggingFilterEnabled) { this.loggingFilterEnabled = loggingFilterEnabled; @@ -328,8 +353,18 @@ public DockerClientConfig build() { email, dockerCertPath, readTimeout, - loggingFilterEnabled + loggingFilterEnabled, + maxTotalConnections, + maxPerRouteConnections ); } } + + public int getMaxTotalConnections() { + return maxTotalConnections; + } + + public int getMaxPerRoutConnections() { + return maxPerRouteConnections; + } } diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 20eb16855..dae172e34 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -93,8 +93,11 @@ public void init(DockerClientConfig dockerClientConfig) { } URI originalUri = dockerClientConfig.getUri(); + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(getSchemeRegistry(originalUri)); + connManager.setMaxTotal(dockerClientConfig.getMaxTotalConnections()); + connManager.setDefaultMaxPerRoute(dockerClientConfig.getMaxPerRoutConnections()); clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, - new PoolingHttpClientConnectionManager(getSchemeRegistry(originalUri))); + connManager); ClientBuilder clientBuilder = ClientBuilder.newBuilder().withConfig(clientConfig); diff --git a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java index b0747e68e..366cca319 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java @@ -15,7 +15,7 @@ public class DockerClientConfigTest { public static final DockerClientConfig EXAMPLE_CONFIG = newExampleConfig(); private static DockerClientConfig newExampleConfig() { - return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "flim", 877, false); + return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "flim", 877, false, 20, 2); } @Test From 8f740dd387085f3d6bf4fa89f3c54ddb3f74770c Mon Sep 17 00:00:00 2001 From: Alexander Kampmann Date: Wed, 19 Nov 2014 12:37:03 +0100 Subject: [PATCH 5/5] removed a test which accesses unix sockets hard-coded --- .../dockerjava/core/UnixSocketTest.java | 109 ------------------ 1 file changed, 109 deletions(-) delete mode 100644 src/test/java/com/github/dockerjava/core/UnixSocketTest.java diff --git a/src/test/java/com/github/dockerjava/core/UnixSocketTest.java b/src/test/java/com/github/dockerjava/core/UnixSocketTest.java deleted file mode 100644 index dca0c85f3..000000000 --- a/src/test/java/com/github/dockerjava/core/UnixSocketTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.github.dockerjava.core; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.endsWith; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.LineIterator; -import org.testng.Assert; -import org.testng.annotations.Test; - -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.command.CreateContainerResponse; - -@Test(groups = "unix") -public class UnixSocketTest { - - @Test - public void testUnixSocketPing() { - DockerClientConfig config = DockerClientConfig - .createDefaultConfigBuilder() - .withVersion("1.14") - .withUri("unix://localhost/var/run/docker.sock").build(); - DockerClient docker = DockerClientBuilder.getInstance(config) - .build(); - docker.pingCmd(); - } - - @Test - public void testUnixSocketCat() throws IOException { - String image = "test"; - String containerId = null; - - DockerClientConfig config = DockerClientConfig - .createDefaultConfigBuilder() - .withVersion("1.14") - .withUri("unix://localhost/var/run/docker.sock").build(); - DockerClient docker = DockerClientBuilder.getInstance(config).build(); - try { - - // construct a tar archive - ByteArrayOutputStream os = new ByteArrayOutputStream(); - String text = "Hello Docker!\n"; - TarArchiveOutputStream tarStream = new TarArchiveOutputStream(os); - // add some files - putToArchive(tarStream, "Dockerfile", - "FROM busybox\nADD testdata /testdata\n".getBytes()); - putToArchive(tarStream, "testdata/hello1", text.getBytes()); - tarStream.close(); - - ByteArrayInputStream tarIn = new ByteArrayInputStream(os.toByteArray()); - - InputStream in = docker.buildImageCmd(tarIn).withTag(image).exec(); - readStream(System.out, in); - - CreateContainerResponse resp = docker.createContainerCmd("test") - .withCmd("cat", "hello1") - .withWorkingDir("/testdata") - .exec(); - containerId = resp.getId(); - Assert.assertEquals(null, resp.getWarnings()); - - docker.startContainerCmd(resp.getId()).exec(); - - int ex = docker.waitContainerCmd(resp.getId()).exec(); - Assert.assertEquals(ex, 0); - - StringBuilder sb = new StringBuilder(); - InputStream stream = docker.logContainerCmd(resp.getId()) - .withStdErr() - .withStdOut() - .exec(); - readStream(sb, stream); - assertThat(sb.toString(), endsWith(text)); - } finally { - if(null != containerId) { - docker.removeContainerCmd(containerId).exec(); - } - docker.removeImageCmd(image).exec(); - - } - } - - private void readStream(Appendable sb, InputStream stream) - throws IOException { - LineIterator itr = IOUtils.lineIterator( - stream, "UTF-8"); - - while(itr.hasNext()) { - sb.append(itr.next()); - sb.append("\n"); - } - } - - private void putToArchive(TarArchiveOutputStream tarStream, String name, - byte[] content) throws IOException { - TarArchiveEntry dockerfile = new TarArchiveEntry(name); - dockerfile.setSize(content.length); - tarStream.putArchiveEntry(dockerfile); - tarStream.write(content); - tarStream.closeArchiveEntry(); - } -}