Restructure and polish docker code
Restructure and polish docker code to fix a package tangle and provide better separation of concerns.pull/20756/head
parent
5d8d0bb159
commit
4dad56a491
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
/**
|
||||
* A {@code DockerHttpClientConnection} that determines an appropriate connection to a
|
||||
* Docker host by detecting whether a remote Docker host is configured or if a default
|
||||
* local connection should be used.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public final class DelegatingDockerHttpClientConnection implements DockerHttpClientConnection {
|
||||
|
||||
private static final RemoteEnvironmentDockerHttpClientConnection REMOTE_FACTORY = new RemoteEnvironmentDockerHttpClientConnection();
|
||||
|
||||
private static final LocalDockerHttpClientConnection LOCAL_FACTORY = new LocalDockerHttpClientConnection();
|
||||
|
||||
private final DockerHttpClientConnection delegate;
|
||||
|
||||
private DelegatingDockerHttpClientConnection(DockerHttpClientConnection delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpHost} describing the Docker host connection.
|
||||
* @return the {@code HttpHost}
|
||||
*/
|
||||
public HttpHost getHttpHost() {
|
||||
return this.delegate.getHttpHost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpClient} that can be used to communicate with the Docker host.
|
||||
* @return the {@code HttpClient}
|
||||
*/
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
return this.delegate.getHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link DockerHttpClientConnection} by detecting the connection
|
||||
* configuration.
|
||||
* @return the {@code DockerHttpClientConnection}
|
||||
*/
|
||||
public static DockerHttpClientConnection create() {
|
||||
if (REMOTE_FACTORY.accept()) {
|
||||
return new DelegatingDockerHttpClientConnection(REMOTE_FACTORY);
|
||||
}
|
||||
if (LOCAL_FACTORY.accept()) {
|
||||
return new DelegatingDockerHttpClientConnection(LOCAL_FACTORY);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import com.sun.jna.Platform;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.socket.DomainSocket;
|
||||
import org.springframework.boot.buildpack.platform.socket.NamedPipeSocket;
|
||||
|
||||
/**
|
||||
* {@link ConnectionSocketFactory} that connects to the Docker domain socket or named
|
||||
* pipe.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class LocalDockerConnectionSocketFactory implements ConnectionSocketFactory {
|
||||
|
||||
private static final String DOMAIN_SOCKET_PATH = "/var/run/docker.sock";
|
||||
|
||||
private static final String WINDOWS_NAMED_PIPE_PATH = "//./pipe/docker_engine";
|
||||
|
||||
@Override
|
||||
public Socket createSocket(HttpContext context) throws IOException {
|
||||
if (Platform.isWindows()) {
|
||||
return NamedPipeSocket.get(WINDOWS_NAMED_PIPE_PATH);
|
||||
}
|
||||
return DomainSocket.get(DOMAIN_SOCKET_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket connectSocket(int connectTimeout, Socket sock, HttpHost host, InetSocketAddress remoteAddress,
|
||||
InetSocketAddress localAddress, HttpContext context) throws IOException {
|
||||
return sock;
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.apache.http.conn.DnsResolver;
|
||||
|
||||
/**
|
||||
* {@link DnsResolver} used by the {@link LocalDockerHttpClientConnectionManager} to
|
||||
* ensure only the loopback address is used.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class LocalDockerDnsResolver implements DnsResolver {
|
||||
|
||||
private static final InetAddress[] LOOPBACK = new InetAddress[] { InetAddress.getLoopbackAddress() };
|
||||
|
||||
@Override
|
||||
public InetAddress[] resolve(String host) throws UnknownHostException {
|
||||
return LOOPBACK;
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link DockerHttpClientConnection} that describes a connection to a local Docker
|
||||
* host.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class LocalDockerHttpClientConnection implements DockerHttpClientConnection {
|
||||
|
||||
private HttpHost httpHost;
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
/**
|
||||
* Indicate that this factory can be used as a default.
|
||||
* @return {@code true} always
|
||||
*/
|
||||
public boolean accept() {
|
||||
this.httpHost = HttpHost.create("docker://localhost");
|
||||
|
||||
HttpClientBuilder builder = HttpClients.custom();
|
||||
builder.setConnectionManager(new LocalDockerHttpClientConnectionManager());
|
||||
builder.setSchemePortResolver(new LocalDockerSchemePortResolver());
|
||||
this.httpClient = builder.build();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpHost} describing a local Docker host connection.
|
||||
* @return the {@code HttpHost}
|
||||
*/
|
||||
@Override
|
||||
public HttpHost getHttpHost() {
|
||||
Assert.state(this.httpHost != null, "DockerHttpClientConnection was not properly initialized");
|
||||
return this.httpHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpClient} that can be used to communicate with a local Docker host.
|
||||
* @return the {@code HttpClient}
|
||||
*/
|
||||
@Override
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
Assert.state(this.httpClient != null, "DockerHttpClientConnection was not properly initialized");
|
||||
return this.httpClient;
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||
|
||||
/**
|
||||
* {@link HttpClientConnectionManager} for Docker.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class LocalDockerHttpClientConnectionManager extends BasicHttpClientConnectionManager {
|
||||
|
||||
LocalDockerHttpClientConnectionManager() {
|
||||
super(getRegistry(), null, null, new LocalDockerDnsResolver());
|
||||
}
|
||||
|
||||
private static Registry<ConnectionSocketFactory> getRegistry() {
|
||||
RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.create();
|
||||
builder.register("docker", new LocalDockerConnectionSocketFactory());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.conn.SchemePortResolver;
|
||||
import org.apache.http.conn.UnsupportedSchemeException;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
/**
|
||||
* {@link SchemePortResolver} for Docker.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class LocalDockerSchemePortResolver implements SchemePortResolver {
|
||||
|
||||
private static final int DEFAULT_DOCKER_PORT = 2376;
|
||||
|
||||
@Override
|
||||
public int resolve(HttpHost host) throws UnsupportedSchemeException {
|
||||
Args.notNull(host, "HTTP host");
|
||||
String name = host.getSchemeName();
|
||||
if ("docker".equals(name)) {
|
||||
return DEFAULT_DOCKER_PORT;
|
||||
}
|
||||
throw new UnsupportedSchemeException(name + " protocol is not supported");
|
||||
}
|
||||
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.ssl.SslContextFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link DockerHttpClientConnection} that describes a connection to a remote Docker
|
||||
* host specified by environment variables.
|
||||
*
|
||||
* This implementation looks for the following environment variables:
|
||||
*
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>{@code DOCKER_HOST} - the URL to a Docker daemon host, such as
|
||||
* {@code tcp://localhost:2376}</li>
|
||||
* <li>{@code DOCKER_TLS_VERIFY} - set to {@code 1} to enable secure connection to the
|
||||
* Docker host via TLS (optional)</li>
|
||||
* <li>{@code DOCKER_CERT_PATH} - the path to certificate and key files needed for TLS
|
||||
* verification (required if {@code DOCKER_TLS_VERIFY=1})</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class RemoteEnvironmentDockerHttpClientConnection implements DockerHttpClientConnection {
|
||||
|
||||
private static final String DOCKER_HOST_KEY = "DOCKER_HOST";
|
||||
|
||||
private static final String DOCKER_TLS_VERIFY_KEY = "DOCKER_TLS_VERIFY";
|
||||
|
||||
private static final String DOCKER_CERT_PATH_KEY = "DOCKER_CERT_PATH";
|
||||
|
||||
private final EnvironmentAccessor environment;
|
||||
|
||||
private final SslContextFactory sslContextFactory;
|
||||
|
||||
private HttpHost httpHost;
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
RemoteEnvironmentDockerHttpClientConnection() {
|
||||
this.environment = new SystemEnvironmentAccessor();
|
||||
this.sslContextFactory = new SslContextFactory();
|
||||
}
|
||||
|
||||
RemoteEnvironmentDockerHttpClientConnection(EnvironmentAccessor environmentAccessor,
|
||||
SslContextFactory sslContextFactory) {
|
||||
this.environment = environmentAccessor;
|
||||
this.sslContextFactory = sslContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this factory can create be used to create a connection.
|
||||
* @return {@code true} if the environment variable {@code DOCKER_HOST} is set,
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean accept() {
|
||||
if (this.environment.getProperty("DOCKER_HOST") != null) {
|
||||
initHttpHost();
|
||||
initHttpClient();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpHost} from the Docker host specified in the environment.
|
||||
* @return the {@code HttpHost}
|
||||
*/
|
||||
@Override
|
||||
public HttpHost getHttpHost() {
|
||||
Assert.state(this.httpHost != null, "DockerHttpClientConnection was not properly initialized");
|
||||
return this.httpHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an {@link HttpClient} from the Docker connection information specified in the
|
||||
* environment.
|
||||
* @return the {@code HttpClient}
|
||||
*/
|
||||
@Override
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
Assert.state(this.httpClient != null, "DockerHttpClientConnection was not properly initialized");
|
||||
return this.httpClient;
|
||||
}
|
||||
|
||||
private void initHttpHost() {
|
||||
String dockerHost = this.environment.getProperty(DOCKER_HOST_KEY);
|
||||
Assert.hasText(dockerHost, "DOCKER_HOST must be set");
|
||||
|
||||
this.httpHost = HttpHost.create(dockerHost);
|
||||
if ("tcp".equals(this.httpHost.getSchemeName())) {
|
||||
String scheme = (isSecure()) ? "https" : "http";
|
||||
this.httpHost = new HttpHost(this.httpHost.getHostName(), this.httpHost.getPort(), scheme);
|
||||
}
|
||||
}
|
||||
|
||||
private void initHttpClient() {
|
||||
HttpClientBuilder builder = HttpClients.custom();
|
||||
|
||||
if (isSecure()) {
|
||||
String certPath = this.environment.getProperty(DOCKER_CERT_PATH_KEY);
|
||||
Assert.hasText(certPath, DOCKER_TLS_VERIFY_KEY + " requires trust material location to be specified with "
|
||||
+ DOCKER_CERT_PATH_KEY);
|
||||
|
||||
SSLContext sslContext = this.sslContextFactory.forPath(certPath);
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||
|
||||
builder.setSSLSocketFactory(sslSocketFactory).setSSLContext(sslContext);
|
||||
}
|
||||
|
||||
this.httpClient = builder.build();
|
||||
}
|
||||
|
||||
private boolean isSecure() {
|
||||
String tlsVerify = this.environment.getProperty(DOCKER_TLS_VERIFY_KEY);
|
||||
if (tlsVerify != null) {
|
||||
try {
|
||||
return Integer.parseInt(tlsVerify) == 1;
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
interface EnvironmentAccessor {
|
||||
|
||||
String getProperty(String key);
|
||||
|
||||
}
|
||||
|
||||
public static class SystemEnvironmentAccessor implements EnvironmentAccessor {
|
||||
|
||||
public String getProperty(String key) {
|
||||
return System.getenv(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
6
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerException.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java
6
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerException.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java
2
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/Errors.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/Errors.java
2
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/Errors.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/Errors.java
50
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/HttpClientHttp.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java
50
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/HttpClientHttp.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java
38
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/Http.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpTransport.java
38
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/Http.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpTransport.java
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.transport;
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import com.sun.jna.Platform;
|
||||
import org.apache.http.HttpHost;
|
||||
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.SchemePortResolver;
|
||||
import org.apache.http.conn.UnsupportedSchemeException;
|
||||
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.BasicHttpClientConnectionManager;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.socket.DomainSocket;
|
||||
import org.springframework.boot.buildpack.platform.socket.NamedPipeSocket;
|
||||
|
||||
/**
|
||||
* {@link HttpClientTransport} that talks to local Docker.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
final class LocalHttpClientTransport extends HttpClientTransport {
|
||||
|
||||
private static final HttpHost LOCAL_DOCKER_HOST = HttpHost.create("docker://localhost");
|
||||
|
||||
private LocalHttpClientTransport(CloseableHttpClient client) {
|
||||
super(client, LOCAL_DOCKER_HOST);
|
||||
}
|
||||
|
||||
static LocalHttpClientTransport create() {
|
||||
HttpClientBuilder builder = HttpClients.custom();
|
||||
builder.setConnectionManager(new LocalConnectionManager());
|
||||
builder.setSchemePortResolver(new LocalSchemePortResolver());
|
||||
return new LocalHttpClientTransport(builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link HttpClientConnectionManager} for local Docker.
|
||||
*/
|
||||
private static class LocalConnectionManager extends BasicHttpClientConnectionManager {
|
||||
|
||||
LocalConnectionManager() {
|
||||
super(getRegistry(), null, null, new LocalDnsResolver());
|
||||
}
|
||||
|
||||
private static Registry<ConnectionSocketFactory> getRegistry() {
|
||||
RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.create();
|
||||
builder.register("docker", new LocalConnectionSocketFactory());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link DnsResolver} used by the {@link LocalDockerHttpClientConnectionManager} to
|
||||
* ensure only the loopback address is used.
|
||||
*/
|
||||
private static class LocalDnsResolver implements DnsResolver {
|
||||
|
||||
private static final InetAddress[] LOOPBACK = new InetAddress[] { InetAddress.getLoopbackAddress() };
|
||||
|
||||
@Override
|
||||
public InetAddress[] resolve(String host) throws UnknownHostException {
|
||||
return LOOPBACK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ConnectionSocketFactory} that connects to the local Docker domain socket or
|
||||
* named pipe.
|
||||
*/
|
||||
private static class LocalConnectionSocketFactory implements ConnectionSocketFactory {
|
||||
|
||||
private static final String DOMAIN_SOCKET_PATH = "/var/run/docker.sock";
|
||||
|
||||
private static final String WINDOWS_NAMED_PIPE_PATH = "//./pipe/docker_engine";
|
||||
|
||||
@Override
|
||||
public Socket createSocket(HttpContext context) throws IOException {
|
||||
if (Platform.isWindows()) {
|
||||
return NamedPipeSocket.get(WINDOWS_NAMED_PIPE_PATH);
|
||||
}
|
||||
return DomainSocket.get(DOMAIN_SOCKET_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket connectSocket(int connectTimeout, Socket sock, HttpHost host, InetSocketAddress remoteAddress,
|
||||
InetSocketAddress localAddress, HttpContext context) throws IOException {
|
||||
return sock;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link SchemePortResolver} for local Docker.
|
||||
*/
|
||||
private static class LocalSchemePortResolver implements SchemePortResolver {
|
||||
|
||||
private static final int DEFAULT_DOCKER_PORT = 2376;
|
||||
|
||||
@Override
|
||||
public int resolve(HttpHost host) throws UnsupportedSchemeException {
|
||||
Args.notNull(host, "HTTP host");
|
||||
String name = host.getSchemeName();
|
||||
if ("docker".equals(name)) {
|
||||
return DEFAULT_DOCKER_PORT;
|
||||
}
|
||||
throw new UnsupportedSchemeException(name + " protocol is not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.transport;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.ssl.SslContextFactory;
|
||||
import org.springframework.boot.buildpack.platform.system.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link HttpClientTransport} that talks to a remote Docker.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
final class RemoteHttpClientTransport extends HttpClientTransport {
|
||||
|
||||
private static final String DOCKER_HOST = "DOCKER_HOST";
|
||||
|
||||
private static final String DOCKER_TLS_VERIFY = "DOCKER_TLS_VERIFY";
|
||||
|
||||
private static final String DOCKER_CERT_PATH = "DOCKER_CERT_PATH";
|
||||
|
||||
private RemoteHttpClientTransport(CloseableHttpClient client, HttpHost host) {
|
||||
super(client, host);
|
||||
}
|
||||
|
||||
static RemoteHttpClientTransport createIfPossible(Environment environment) {
|
||||
return createIfPossible(environment, new SslContextFactory());
|
||||
}
|
||||
|
||||
static RemoteHttpClientTransport createIfPossible(Environment environment, SslContextFactory sslContextFactory) {
|
||||
String host = environment.get(DOCKER_HOST);
|
||||
return (host != null) ? create(environment, sslContextFactory, HttpHost.create(host)) : null;
|
||||
}
|
||||
|
||||
private static RemoteHttpClientTransport create(Environment environment, SslContextFactory sslContextFactory,
|
||||
HttpHost tcpHost) {
|
||||
HttpClientBuilder builder = HttpClients.custom();
|
||||
boolean secure = isSecure(environment);
|
||||
if (secure) {
|
||||
builder.setSSLSocketFactory(getSecureConnectionSocketFactory(environment, sslContextFactory));
|
||||
}
|
||||
String scheme = secure ? "https" : "http";
|
||||
HttpHost httpHost = new HttpHost(tcpHost.getHostName(), tcpHost.getPort(), scheme);
|
||||
return new RemoteHttpClientTransport(builder.build(), httpHost);
|
||||
}
|
||||
|
||||
private static LayeredConnectionSocketFactory getSecureConnectionSocketFactory(Environment environment,
|
||||
SslContextFactory sslContextFactory) {
|
||||
String directory = environment.get(DOCKER_CERT_PATH);
|
||||
Assert.hasText(directory,
|
||||
() -> DOCKER_TLS_VERIFY + " requires trust material location to be specified with " + DOCKER_CERT_PATH);
|
||||
SSLContext sslContext = sslContextFactory.forDirectory(directory);
|
||||
return new SSLConnectionSocketFactory(sslContext);
|
||||
}
|
||||
|
||||
private static boolean isSecure(Environment environment) {
|
||||
String secure = environment.get(DOCKER_TLS_VERIFY);
|
||||
try {
|
||||
return (secure != null) && (Integer.parseInt(secure) == 1);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Docker transport classes providing HTTP operations on a local or remote engine.
|
||||
*/
|
||||
package org.springframework.boot.buildpack.platform.docker.transport;
|
26
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/httpclient/DockerHttpClientConnection.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/system/Environment.java
26
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/httpclient/DockerHttpClientConnection.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/system/Environment.java
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* System abstractions.
|
||||
*/
|
||||
package org.springframework.boot.buildpack.platform.system;
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.httpclient;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.httpclient.RemoteEnvironmentDockerHttpClientConnection.EnvironmentAccessor;
|
||||
import org.springframework.boot.buildpack.platform.docker.ssl.SslContextFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link RemoteEnvironmentDockerHttpClientConnection}.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class RemoteEnvironmentDockerHttpClientConnectionTests {
|
||||
|
||||
private EnvironmentAccessor environment;
|
||||
|
||||
private RemoteEnvironmentDockerHttpClientConnection connection;
|
||||
|
||||
private SslContextFactory sslContextFactory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.environment = mock(EnvironmentAccessor.class);
|
||||
this.sslContextFactory = mock(SslContextFactory.class);
|
||||
this.connection = new RemoteEnvironmentDockerHttpClientConnection(this.environment, this.sslContextFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void notAcceptedWhenDockerHostNotSet() {
|
||||
assertThat(this.connection.accept()).isFalse();
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.connection.getHttpHost());
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.connection.getHttpClient());
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptedWhenDockerHostIsSet() {
|
||||
given(this.environment.getProperty("DOCKER_HOST")).willReturn("tcp://192.168.1.2:2376");
|
||||
assertThat(this.connection.accept()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidTlsConfigurationThrowsException() {
|
||||
given(this.environment.getProperty("DOCKER_HOST")).willReturn("tcp://192.168.1.2:2376");
|
||||
given(this.environment.getProperty("DOCKER_TLS_VERIFY")).willReturn("1");
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.connection.accept())
|
||||
.withMessageContaining("DOCKER_CERT_PATH");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostProtocolIsHttpWhenNotSecure() {
|
||||
given(this.environment.getProperty("DOCKER_HOST")).willReturn("tcp://192.168.1.2:2376");
|
||||
assertThat(this.connection.accept()).isTrue();
|
||||
HttpHost host = this.connection.getHttpHost();
|
||||
assertThat(host).isNotNull();
|
||||
assertThat(host.getSchemeName()).isEqualTo("http");
|
||||
assertThat(host.getHostName()).isEqualTo("192.168.1.2");
|
||||
assertThat(host.getPort()).isEqualTo(2376);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostProtocolIsHttpsWhenSecure() throws NoSuchAlgorithmException {
|
||||
given(this.environment.getProperty("DOCKER_HOST")).willReturn("tcp://192.168.1.2:2376");
|
||||
given(this.environment.getProperty("DOCKER_TLS_VERIFY")).willReturn("1");
|
||||
given(this.environment.getProperty("DOCKER_CERT_PATH")).willReturn("/test-cert-path");
|
||||
given(this.sslContextFactory.forPath("/test-cert-path")).willReturn(SSLContext.getDefault());
|
||||
assertThat(this.connection.accept()).isTrue();
|
||||
HttpHost host = this.connection.getHttpHost();
|
||||
assertThat(host).isNotNull();
|
||||
assertThat(host.getSchemeName()).isEqualTo("https");
|
||||
assertThat(host.getHostName()).isEqualTo("192.168.1.2");
|
||||
assertThat(host.getPort()).isEqualTo(2376);
|
||||
}
|
||||
|
||||
}
|
19
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerExceptionTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineExceptionTests.java
19
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerExceptionTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineExceptionTests.java
4
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/ErrorsTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/ErrorsTests.java
4
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/ErrorsTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/ErrorsTests.java
42
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/HttpClientHttpTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java
42
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/HttpClientHttpTests.java → spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.transport;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HttpTransport}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class HttpTransportTests {
|
||||
|
||||
@Test
|
||||
void createWhenHasDockerHostVariableReturnsRemote() {
|
||||
Map<String, String> environment = Collections.singletonMap("DOCKER_HOST", "192.168.1.0");
|
||||
HttpTransport transport = HttpTransport.create(environment::get);
|
||||
assertThat(transport).isInstanceOf(RemoteHttpClientTransport.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenDoesNotHaveDockerHostVariableReturnsLocal() {
|
||||
HttpTransport transport = HttpTransport.create((name) -> null);
|
||||
assertThat(transport).isInstanceOf(LocalHttpClientTransport.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.boot.buildpack.platform.docker.transport;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.ssl.SslContextFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link RemoteHttpClientTransport}
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class RemoteHttpClientTransportTests {
|
||||
|
||||
private Map<String, String> environment = new LinkedHashMap<>();
|
||||
|
||||
@Test
|
||||
void createIfPossibleWhenDockerHostIsNotSetReturnsNull() {
|
||||
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get);
|
||||
assertThat(transport).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createIfPossibleWhenDockerHostIsSetReturnsTransport() {
|
||||
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
|
||||
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get);
|
||||
assertThat(transport).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createIfPossibleWhenTlsVerifyWithMissingCertPathThrowsException() {
|
||||
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
|
||||
this.environment.put("DOCKER_TLS_VERIFY", "1");
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> RemoteHttpClientTransport.createIfPossible(this.environment::get))
|
||||
.withMessageContaining("DOCKER_CERT_PATH");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createIfPossibleWhenNoTlsVerifyUsesHttp() {
|
||||
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
|
||||
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get);
|
||||
assertThat(transport.getHost()).satisfies(hostOf("http", "192.168.1.2", 2376));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createIfPossibleWhenTlsVerifyUsesHttps() throws Exception {
|
||||
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
|
||||
this.environment.put("DOCKER_TLS_VERIFY", "1");
|
||||
this.environment.put("DOCKER_CERT_PATH", "/test-cert-path");
|
||||
SslContextFactory sslContextFactory = mock(SslContextFactory.class);
|
||||
given(sslContextFactory.forDirectory("/test-cert-path")).willReturn(SSLContext.getDefault());
|
||||
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
|
||||
sslContextFactory);
|
||||
assertThat(transport.getHost()).satisfies(hostOf("https", "192.168.1.2", 2376));
|
||||
}
|
||||
|
||||
private Consumer<HttpHost> hostOf(String scheme, String hostName, int port) {
|
||||
return (host) -> {
|
||||
assertThat(host).isNotNull();
|
||||
assertThat(host.getSchemeName()).isEqualTo(scheme);
|
||||
assertThat(host.getHostName()).isEqualTo(hostName);
|
||||
assertThat(host.getPort()).isEqualTo(port);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue