Add option to use configured Docker host in builder

This commit adds support for a `docker.bindHostToBuilder` option in
the Maven and Gradle image building goal and task.

Fixes gh-29384
This commit is contained in:
Scott Frederick
2022-03-11 15:27:22 -06:00
parent 93622d18eb
commit 7ad538cd84
24 changed files with 621 additions and 236 deletions

View File

@@ -36,6 +36,8 @@ import org.springframework.boot.buildpack.platform.docker.DockerApi;
import org.springframework.boot.buildpack.platform.docker.DockerApi.ContainerApi;
import org.springframework.boot.buildpack.platform.docker.DockerApi.ImageApi;
import org.springframework.boot.buildpack.platform.docker.DockerApi.VolumeApi;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
import org.springframework.boot.buildpack.platform.docker.type.Binding;
import org.springframework.boot.buildpack.platform.docker.type.ContainerConfig;
import org.springframework.boot.buildpack.platform.docker.type.ContainerContent;
@@ -212,6 +214,28 @@ class LifecycleTests {
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
}
@Test
void executeWithDockerHostAndRemoteAddressExecutesPhases() throws Exception {
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
BuildRequest request = getTestRequest();
createLifecycle(request, ResolvedDockerHost.from(new DockerHost("tcp://192.168.1.2:2376"))).execute();
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-inherit-remote.json"));
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
}
@Test
void executeWithDockerHostAndLocalAddressExecutesPhases() throws Exception {
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
BuildRequest request = getTestRequest();
createLifecycle(request, ResolvedDockerHost.from(new DockerHost("/var/alt.sock"))).execute();
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-inherit-local.json"));
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
}
private DockerApi mockDockerApi() {
DockerApi docker = mock(DockerApi.class);
ImageApi imageApi = mock(ImageApi.class);
@@ -243,8 +267,13 @@ class LifecycleTests {
return createLifecycle(getTestRequest(), builder);
}
private Lifecycle createLifecycle(BuildRequest request, ResolvedDockerHost dockerHost) throws IOException {
EphemeralBuilder builder = mockEphemeralBuilder();
return new TestLifecycle(BuildLog.to(this.out), this.docker, dockerHost, request, builder);
}
private Lifecycle createLifecycle(BuildRequest request, EphemeralBuilder ephemeralBuilder) {
return new TestLifecycle(BuildLog.to(this.out), this.docker, request, ephemeralBuilder);
return new TestLifecycle(BuildLog.to(this.out), this.docker, null, request, ephemeralBuilder);
}
private EphemeralBuilder mockEphemeralBuilder() throws IOException {
@@ -296,8 +325,9 @@ class LifecycleTests {
static class TestLifecycle extends Lifecycle {
TestLifecycle(BuildLog log, DockerApi docker, BuildRequest request, EphemeralBuilder builder) {
super(log, docker, request, builder);
TestLifecycle(BuildLog log, DockerApi docker, ResolvedDockerHost dockerHost, BuildRequest request,
EphemeralBuilder builder) {
super(log, docker, dockerHost, request, builder);
}
@Override

View File

@@ -60,13 +60,12 @@ class PhaseTests {
}
@Test
void applyWhenWithDaemonAccessUpdatesConfigurationWithRootUserAndDomainSocketBinding() {
void applyWhenWithDaemonAccessUpdatesConfigurationWithRootUser() {
Phase phase = new Phase("test", false);
phase.withDaemonAccess();
Update update = mock(Update.class);
phase.apply(update);
then(update).should().withUser("root");
then(update).should().withBinding(Binding.from("/var/run/docker.sock", "/var/run/docker.sock"));
then(update).should().withCommand("/cnb/lifecycle/test", NO_ARGS);
then(update).should().withLabel("author", "spring-boot");
then(update).shouldHaveNoMoreInteractions();

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2012-2022 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.configuration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.TempDir;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ResolvedDockerHost}.
*
* @author Scott Frederick
*/
class ResolvedDockerHostTests {
private final Map<String, String> environment = new LinkedHashMap<>();
@Test
@DisabledOnOs(OS.WINDOWS)
void resolveWhenDockerHostIsNullReturnsLinuxDefault() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get, null);
assertThat(dockerHost.getAddress()).isEqualTo("/var/run/docker.sock");
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
@EnabledOnOs(OS.WINDOWS)
void resolveWhenDockerHostIsNullReturnsWindowsDefault() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get, null);
assertThat(dockerHost.getAddress()).isEqualTo("//./pipe/docker_engine");
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
@DisabledOnOs(OS.WINDOWS)
void resolveWhenDockerHostAddressIsNullReturnsLinuxDefault() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get, new DockerHost(null));
assertThat(dockerHost.getAddress()).isEqualTo("/var/run/docker.sock");
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenDockerHostAddressIsLocalReturnsAddress(@TempDir Path tempDir) throws IOException {
String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString();
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost(socketFilePath, false, null));
assertThat(dockerHost.isLocalFileReference()).isTrue();
assertThat(dockerHost.isRemote()).isFalse();
assertThat(dockerHost.getAddress()).isEqualTo(socketFilePath);
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenDockerHostAddressIsLocalWithSchemeReturnsAddress(@TempDir Path tempDir) throws IOException {
String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString();
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("unix://" + socketFilePath, false, null));
assertThat(dockerHost.isLocalFileReference()).isTrue();
assertThat(dockerHost.isRemote()).isFalse();
assertThat(dockerHost.getAddress()).isEqualTo(socketFilePath);
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenDockerHostAddressIsHttpReturnsAddress() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("http://docker.example.com", false, null));
assertThat(dockerHost.isLocalFileReference()).isFalse();
assertThat(dockerHost.isRemote()).isTrue();
assertThat(dockerHost.getAddress()).isEqualTo("http://docker.example.com");
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenDockerHostAddressIsHttpsReturnsAddress() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("https://docker.example.com", true, "/cert-path"));
assertThat(dockerHost.isLocalFileReference()).isFalse();
assertThat(dockerHost.isRemote()).isTrue();
assertThat(dockerHost.getAddress()).isEqualTo("https://docker.example.com");
assertThat(dockerHost.isSecure()).isTrue();
assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path");
}
@Test
void resolveWhenDockerHostAddressIsTcpReturnsAddress() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("tcp://192.168.99.100:2376", true, "/cert-path"));
assertThat(dockerHost.isLocalFileReference()).isFalse();
assertThat(dockerHost.isRemote()).isTrue();
assertThat(dockerHost.getAddress()).isEqualTo("tcp://192.168.99.100:2376");
assertThat(dockerHost.isSecure()).isTrue();
assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path");
}
@Test
void resolveWhenEnvironmentAddressIsLocalReturnsAddress(@TempDir Path tempDir) throws IOException {
String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString();
this.environment.put("DOCKER_HOST", socketFilePath);
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("/unused", true, "/unused"));
assertThat(dockerHost.isLocalFileReference()).isTrue();
assertThat(dockerHost.isRemote()).isFalse();
assertThat(dockerHost.getAddress()).isEqualTo(socketFilePath);
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenEnvironmentAddressIsLocalWithSchemeReturnsAddress(@TempDir Path tempDir) throws IOException {
String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString();
this.environment.put("DOCKER_HOST", "unix://" + socketFilePath);
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("/unused", true, "/unused"));
assertThat(dockerHost.isLocalFileReference()).isTrue();
assertThat(dockerHost.isRemote()).isFalse();
assertThat(dockerHost.getAddress()).isEqualTo(socketFilePath);
assertThat(dockerHost.isSecure()).isFalse();
assertThat(dockerHost.getCertificatePath()).isNull();
}
@Test
void resolveWhenEnvironmentAddressIsTcpReturnsAddress() {
this.environment.put("DOCKER_HOST", "tcp://192.168.99.100:2376");
this.environment.put("DOCKER_TLS_VERIFY", "1");
this.environment.put("DOCKER_CERT_PATH", "/cert-path");
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get,
new DockerHost("tcp://1.1.1.1", false, "/unused"));
assertThat(dockerHost.isLocalFileReference()).isFalse();
assertThat(dockerHost.isRemote()).isTrue();
assertThat(dockerHost.getAddress()).isEqualTo("tcp://192.168.99.100:2376");
assertThat(dockerHost.isSecure()).isTrue();
assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2022 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.
@@ -19,12 +19,12 @@ package org.springframework.boot.buildpack.platform.docker.transport;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -37,31 +37,21 @@ class HttpTransportTests {
@Test
void createWhenDockerHostVariableIsAddressReturnsRemote() {
Map<String, String> environment = Collections.singletonMap("DOCKER_HOST", "tcp://192.168.1.0");
HttpTransport transport = HttpTransport.create(environment::get);
HttpTransport transport = HttpTransport.create(new DockerHost("tcp://192.168.1.0"));
assertThat(transport).isInstanceOf(RemoteHttpClientTransport.class);
}
@Test
void createWhenDockerHostVariableIsFileReturnsLocal(@TempDir Path tempDir) throws IOException {
String dummySocketFilePath = Files.createTempFile(tempDir, "http-transport", null).toAbsolutePath().toString();
Map<String, String> environment = Collections.singletonMap("DOCKER_HOST", dummySocketFilePath);
HttpTransport transport = HttpTransport.create(environment::get);
HttpTransport transport = HttpTransport.create(new DockerHost(dummySocketFilePath));
assertThat(transport).isInstanceOf(LocalHttpClientTransport.class);
}
@Test
void createWhenDockerHostVariableIsUnixSchemePrefixedFileReturnsLocal(@TempDir Path tempDir) throws IOException {
String dummySocketFilePath = "unix://"
+ Files.createTempFile(tempDir, "http-transport", null).toAbsolutePath().toString();
Map<String, String> environment = Collections.singletonMap("DOCKER_HOST", dummySocketFilePath);
HttpTransport transport = HttpTransport.create(environment::get);
assertThat(transport).isInstanceOf(LocalHttpClientTransport.class);
}
@Test
void createWhenDoesNotHaveDockerHostVariableReturnsLocal() {
HttpTransport transport = HttpTransport.create((name) -> null);
String dummySocketFilePath = "unix://" + Files.createTempFile(tempDir, "http-transport", null).toAbsolutePath();
HttpTransport transport = HttpTransport.create(new DockerHost(dummySocketFilePath));
assertThat(transport).isInstanceOf(LocalHttpClientTransport.class);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2012-2022 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.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LocalHttpClientTransport}
*
* @author Scott Frederick
*/
class LocalHttpClientTransportTests {
@Test
void createWhenDockerHostIsFileReturnsTransport(@TempDir Path tempDir) throws IOException {
String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString();
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost(socketFilePath));
LocalHttpClientTransport transport = LocalHttpClientTransport.create(dockerHost);
assertThat(transport).isNotNull();
}
@Test
void createWhenDockerHostIsFileThatDoesNotExistReturnsTransport(@TempDir Path tempDir) {
String socketFilePath = Paths.get(tempDir.toString(), "dummy").toAbsolutePath().toString();
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost(socketFilePath));
LocalHttpClientTransport transport = LocalHttpClientTransport.create(dockerHost);
assertThat(transport).isNotNull();
}
@Test
void createWhenDockerHostIsAddressReturnsTransport() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost("tcp://192.168.1.2:2376"));
LocalHttpClientTransport transport = LocalHttpClientTransport.create(dockerHost);
assertThat(transport).isNotNull();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2022 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.
@@ -16,21 +16,15 @@
package org.springframework.boot.buildpack.platform.docker.transport;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
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.junit.jupiter.api.io.TempDir;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
import org.springframework.boot.buildpack.platform.docker.ssl.SslContextFactory;
import static org.assertj.core.api.Assertions.assertThat;
@@ -46,99 +40,56 @@ import static org.mockito.Mockito.mock;
*/
class RemoteHttpClientTransportTests {
private final Map<String, String> environment = new LinkedHashMap<>();
private final DockerConfiguration dockerConfiguration = new DockerConfiguration();
@Test
void createIfPossibleWhenDockerHostIsNotSetReturnsNull() {
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
new DockerHost(null, false, null));
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(null);
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost);
assertThat(transport).isNull();
}
@Test
void createIfPossibleWithoutDockerConfigurationReturnsNull() {
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get, null);
void createIfPossibleWhenDockerHostIsDefaultReturnsNull() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost(null));
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost);
assertThat(transport).isNull();
}
@Test
void createIfPossibleWhenDockerHostInEnvironmentIsFileReturnsNull(@TempDir Path tempDir) throws IOException {
String dummySocketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath()
.toString();
this.environment.put("DOCKER_HOST", dummySocketFilePath);
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get, null);
void createIfPossibleWhenDockerHostIsFileReturnsNull() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost("unix:///var/run/socket.sock"));
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost);
assertThat(transport).isNull();
}
@Test
void createIfPossibleWhenDockerHostInConfigurationIsFileReturnsNull(@TempDir Path tempDir) throws IOException {
String dummySocketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath()
.toString();
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
new DockerHost(dummySocketFilePath, false, null));
assertThat(transport).isNull();
}
@Test
void createIfPossibleWhenDockerHostInEnvironmentIsAddressReturnsTransport() {
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get, null);
void createIfPossibleWhenDockerHostIsAddressReturnsTransport() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost("tcp://192.168.1.2:2376"));
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost);
assertThat(transport).isNotNull();
}
@Test
void createIfPossibleWhenDockerHostInConfigurationIsAddressReturnsTransport() {
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
new DockerHost("tcp://192.168.1.2:2376", false, null));
assertThat(transport).isNotNull();
}
@Test
void createIfPossibleWhenTlsVerifyInEnvironmentWithMissingCertPathThrowsException() {
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, null))
.withMessageContaining("Docker host TLS verification requires trust material");
}
@Test
void createIfPossibleWhenTlsVerifyInConfigurationWithMissingCertPathThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> RemoteHttpClientTransport.createIfPossible(this.environment::get,
new DockerHost("tcp://192.168.1.2:2376", true, null)))
.withMessageContaining("Docker host TLS verification requires trust material");
}
@Test
void createIfPossibleWhenNoTlsVerifyUsesHttp() {
this.environment.put("DOCKER_HOST", "tcp://192.168.1.2:2376");
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get, null);
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost("tcp://192.168.1.2:2376"));
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost);
assertThat(transport.getHost()).satisfies(hostOf("http", "192.168.1.2", 2376));
}
@Test
void createIfPossibleWhenTlsVerifyInEnvironmentUsesHttps() 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");
void createIfPossibleWhenTlsVerifyUsesHttps() throws Exception {
SslContextFactory sslContextFactory = mock(SslContextFactory.class);
given(sslContextFactory.forDirectory("/test-cert-path")).willReturn(SSLContext.getDefault());
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
this.dockerConfiguration.getHost(), sslContextFactory);
ResolvedDockerHost dockerHost = ResolvedDockerHost
.from(new DockerHost("tcp://192.168.1.2:2376", true, "/test-cert-path"));
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(dockerHost, sslContextFactory);
assertThat(transport.getHost()).satisfies(hostOf("https", "192.168.1.2", 2376));
}
@Test
void createIfPossibleWhenTlsVerifyInConfigurationUsesHttps() throws Exception {
SslContextFactory sslContextFactory = mock(SslContextFactory.class);
given(sslContextFactory.forDirectory("/test-cert-path")).willReturn(SSLContext.getDefault());
RemoteHttpClientTransport transport = RemoteHttpClientTransport.createIfPossible(this.environment::get,
this.dockerConfiguration.withHost("tcp://192.168.1.2:2376", true, "/test-cert-path").getHost(),
sslContextFactory);
assertThat(transport.getHost()).satisfies(hostOf("https", "192.168.1.2", 2376));
void createIfPossibleWhenTlsVerifyWithMissingCertPathThrowsException() {
ResolvedDockerHost dockerHost = ResolvedDockerHost.from(new DockerHost("tcp://192.168.1.2:2376", true, null));
assertThatIllegalArgumentException().isThrownBy(() -> RemoteHttpClientTransport.createIfPossible(dockerHost))
.withMessageContaining("Docker host TLS verification requires trust material");
}
private Consumer<HttpHost> hostOf(String scheme, String hostName, int port) {

View File

@@ -0,0 +1,36 @@
{
"User": "root",
"Image": "pack.local/ephemeral-builder",
"Cmd": [
"/cnb/lifecycle/creator",
"-app",
"/workspace",
"-platform",
"/platform",
"-run-image",
"docker.io/cloudfoundry/run:latest",
"-layers",
"/layers",
"-cache-dir",
"/cache",
"-launch-cache",
"/launch-cache",
"-daemon",
"docker.io/library/my-application:latest"
],
"Env": [
"CNB_PLATFORM_API=0.8"
],
"Labels": {
"author": "spring-boot"
},
"HostConfig": {
"Binds": [
"/var/alt.sock:/var/run/docker.sock",
"pack-layers-aaaaaaaaaa:/layers",
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
]
}
}

View File

@@ -0,0 +1,36 @@
{
"User": "root",
"Image": "pack.local/ephemeral-builder",
"Cmd": [
"/cnb/lifecycle/creator",
"-app",
"/workspace",
"-platform",
"/platform",
"-run-image",
"docker.io/cloudfoundry/run:latest",
"-layers",
"/layers",
"-cache-dir",
"/cache",
"-launch-cache",
"/launch-cache",
"-daemon",
"docker.io/library/my-application:latest"
],
"Env": [
"DOCKER_HOST=tcp://192.168.1.2:2376",
"CNB_PLATFORM_API=0.8"
],
"Labels": {
"author": "spring-boot"
},
"HostConfig": {
"Binds": [
"pack-layers-aaaaaaaaaa:/layers",
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
]
}
}