Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for communication to docker hosts using UNIX domain sockets #179

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@
<version>4.3.6</version>
</dependency>

<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId>
<version>0.8</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/org/jolokia/docker/maven/AbstractDockerMojo.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.jolokia.docker.maven;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import org.apache.maven.plugin.*;
Expand Down Expand Up @@ -248,11 +248,14 @@ private DockerAccess createDockerAccess(String baseUrl) throws MojoExecutionExce

// Registry for managed containers
private void setDockerHostAddressProperty(String dockerUrl) throws MojoFailureException {
final String host;
try {
project.getProperties().setProperty("docker.host.address", new URL(dockerUrl).getHost());
} catch (MalformedURLException e) {
throw new MojoFailureException("Cannot parse " + dockerUrl + " as URL: " + e.getMessage(),e);
host = new URI(dockerUrl).getHost();
} catch (URISyntaxException e) {
throw new MojoFailureException("Cannot parse " + dockerUrl + " as URI: " + e.getMessage(), e);
}

project.getProperties().setProperty("docker.host.address", host == null ? "" : host);
}

// =================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public class DockerAccessWithHttpClient implements DockerAccess {
*/
public DockerAccessWithHttpClient(String apiVersion, String baseUrl, String certPath, Logger log) throws IOException {
this.log = log;
this.delegate = new ApacheHttpDelegate(isSSL(baseUrl) ? certPath : null);
this.urlBuilder = new UrlBuilder(baseUrl, apiVersion);
this.delegate = ApacheHttpDelegate.create(baseUrl, isSSL(baseUrl) ? certPath : null);
this.urlBuilder = delegate.createUrlBuilder(baseUrl, apiVersion);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.jolokia.docker.maven.access.KeyStoreUtil;
import org.jolokia.docker.maven.access.UrlBuilder;
import org.jolokia.docker.maven.access.http.unix.ApacheUnixSocketHttpDelegate;

public class ApacheHttpDelegate {

Expand All @@ -39,8 +41,24 @@ public class ApacheHttpDelegate {

private final CloseableHttpClient httpClient;

public ApacheHttpDelegate(String certPath) throws IOException {
this.httpClient = createHttpClient(certPath);
public static ApacheHttpDelegate create(String baseUrl, String certPath) throws IOException {
if (ApacheUnixSocketHttpDelegate.isSchemeSupported(baseUrl)) {
return new ApacheUnixSocketHttpDelegate();
}

return new ApacheHttpDelegate(certPath);
}

protected ApacheHttpDelegate(CloseableHttpClient httpClient) {
this.httpClient = httpClient;
}

private ApacheHttpDelegate(String certPath) throws IOException {
this(createHttpClient(certPath));
}

public UrlBuilder createUrlBuilder(String baseUrl, String apiVersion) {
return new UrlBuilder(baseUrl, apiVersion);
}

public Result delete(String url, int statusCode, int... additional) throws IOException, HttpRequestException {
Expand Down Expand Up @@ -78,7 +96,7 @@ private HttpUriRequest addDefaultHeaders(HttpUriRequest req) {
return req;
}

private CloseableHttpClient createHttpClient(String certPath) throws IOException {
private static CloseableHttpClient createHttpClient(String certPath) throws IOException {
HttpClientBuilder builder = HttpClients.custom();
PoolingHttpClientConnectionManager manager = getPoolingConnectionFactory(certPath);
manager.setDefaultMaxPerRoute(10);
Expand All @@ -89,13 +107,13 @@ private CloseableHttpClient createHttpClient(String certPath) throws IOException
return builder.build();
}

private PoolingHttpClientConnectionManager getPoolingConnectionFactory(String certPath) throws IOException {
private static PoolingHttpClientConnectionManager getPoolingConnectionFactory(String certPath) throws IOException {
return certPath != null ?
new PoolingHttpClientConnectionManager(getSslFactoryRegistry(certPath)) :
new PoolingHttpClientConnectionManager();
}

private Registry<ConnectionSocketFactory> getSslFactoryRegistry(String certPath) throws IOException {
private static Registry<ConnectionSocketFactory> getSslFactoryRegistry(String certPath) throws IOException {
try
{
KeyStore keyStore = KeyStoreUtil.createDockerKeyStore(certPath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.jolokia.docker.maven.access.http.unix;

import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;

import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.jolokia.docker.maven.access.UrlBuilder;
import org.jolokia.docker.maven.access.http.ApacheHttpDelegate;

public class ApacheUnixSocketHttpDelegate extends ApacheHttpDelegate {

private static final String UNIX_SOKKET_URI_SCHEME = "unix";

/**
* @see <a href="http://tools.ietf.org/html/rfc3986#section-2.2">RFC 3986 -
* Uniform Resource Identifier (URI): Generic Syntax - 2.2 Reserved
* Characters</a>
*/
private static final String RESERVED_URI_CHARS = ":/?#[]@!$&'()/*+,;=";
private static final String HEX_CHARS = "0123456789ABCDEF";

public ApacheUnixSocketHttpDelegate() {
super(createHttpClient());
}

public static boolean isSchemeSupported(String baseUrl) {
return baseUrl.startsWith(UNIX_SOKKET_URI_SCHEME + "://");
}

@Override
public UrlBuilder createUrlBuilder(String baseUrl, String apiVersion) {
final String unixSocketPath = extractUnixSocketPath(baseUrl);
if (unixSocketPath == null) {
throw new IllegalArgumentException("Unsupported Base URL: " + baseUrl);
}

return new UrlBuilder(buildPseudoHostUrl(unixSocketPath), apiVersion);
}

private static CloseableHttpClient createHttpClient() {
final HttpClientBuilder httpBuilder = HttpClients.custom();
final Registry<ConnectionSocketFactory> registry = buildRegistry();
final DnsResolver dnsResolver = nullDnsResolver();
final HttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry, dnsResolver);
httpBuilder.setConnectionManager(manager);
return httpBuilder.build();
}

private static Registry<ConnectionSocketFactory> buildRegistry() {
final RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.create();
registryBuilder.register(UNIX_SOKKET_URI_SCHEME, new UnixConnectionSocketFactory());
return registryBuilder.build();
}

private static DnsResolver nullDnsResolver() {
return new DnsResolver() {
@Override
public InetAddress[] resolve(final String host) throws UnknownHostException {
return new InetAddress[] {null};
}
};
}

private static String extractUnixSocketPath(String baseUrl) {
final URI uri = URI.create(baseUrl);
final String path = uri.getPath();
if (!UNIX_SOKKET_URI_SCHEME.equals(uri.getScheme()) || uri.getHost() != null || path == null) {
return null;
}

return path;
}

/**
* Creates a new URL using the {@value #UNIX_SOKKET_URI_SCHEME} scheme and
* the given path as the host component.
*
* @param unixSocketPath path to the UNIX Domain Socket file
*
* @return a URL that carries {@code unixSocketPath} in its host component
*/
private static String buildPseudoHostUrl(String unixSocketPath) {
return UNIX_SOKKET_URI_SCHEME + "://" + encodeUriPart(unixSocketPath) + ":1";
}

private static String encodeUriPart(String part) {
StringBuilder buf = null;

final int length = part.length();
for (int i = 0; i < length; ++i) {
final char c = part.charAt(i);

if (RESERVED_URI_CHARS.indexOf(c) >= 0) {
if (buf == null) {
buf = new StringBuilder(length * 4 / 3 + 1);
buf.append(part, 0, i);
}

buf.append('%');
buf.append(HEX_CHARS.charAt(c / 16));
buf.append(HEX_CHARS.charAt(c % 16));
} else if (buf != null) {
buf.append(c);
}
}

return buf == null ? part : buf.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.jolokia.docker.maven.access.http.unix;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

import jnr.unixsocket.UnixSocketAddress;

import org.apache.http.HttpHost;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.protocol.HttpContext;

final class UnixConnectionSocketFactory implements ConnectionSocketFactory {

@Override
public Socket createSocket(HttpContext context) throws IOException {
return new UnixSocket();
}

@Override
public Socket connectSocket(int connectTimeout, Socket sock, HttpHost host, InetSocketAddress remoteAddress,
InetSocketAddress localAddress, HttpContext context)
throws IOException {
sock.connect(new UnixSocketAddress(new File(host.getHostName())), connectTimeout);
return sock;
}
}
Loading