Skip to content

Commit eeeeaa5

Browse files
committed
Merge branch '2.2.x'
Closes gh-19416
2 parents 93d9147 + 8b4c6c2 commit eeeeaa5

File tree

7 files changed

+61
-203
lines changed

7 files changed

+61
-203
lines changed

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/pom.xml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@
3030
<artifactId>spring-boot-starter-undertow</artifactId>
3131
</dependency>
3232
<dependency>
33-
<groupId>com.github.docker-java</groupId>
34-
<artifactId>docker-java</artifactId>
35-
<version>3.1.2</version>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-test</artifactId>
3635
<scope>test</scope>
3736
<exclusions>
3837
<exclusion>
@@ -54,9 +53,23 @@
5453
<artifactId>jakarta.ws.rs-api</artifactId>
5554
</dependency>
5655
<dependency>
57-
<groupId>org.springframework.boot</groupId>
58-
<artifactId>spring-boot-starter-test</artifactId>
56+
<groupId>org.testcontainers</groupId>
57+
<artifactId>testcontainers</artifactId>
5958
<scope>test</scope>
59+
<exclusions>
60+
<exclusion>
61+
<groupId>javax.annotation</groupId>
62+
<artifactId>javax.annotation-api</artifactId>
63+
</exclusion>
64+
<exclusion>
65+
<groupId>javax.xml.bind</groupId>
66+
<artifactId>jaxb-api</artifactId>
67+
</exclusion>
68+
<exclusion>
69+
<groupId>org.hamcrest</groupId>
70+
<artifactId>hamcrest-core</artifactId>
71+
</exclusion>
72+
</exclusions>
6073
</dependency>
6174
</dependencies>
6275
<profiles>

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/main/java/org/springframework/boot/launchscript/LaunchVerificationController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class LaunchVerificationController {
2424

2525
@RequestMapping("/")
2626
public String verifyLaunch() {
27-
return "Launched";
27+
return "Launched\n";
2828
}
2929

3030
}

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java

Lines changed: 32 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -17,38 +17,19 @@
1717
package org.springframework.boot.launchscript;
1818

1919
import java.io.File;
20-
import java.io.FileInputStream;
21-
import java.io.InputStream;
20+
import java.time.Duration;
2221
import java.util.ArrayList;
23-
import java.util.Arrays;
24-
import java.util.Collections;
25-
import java.util.HashSet;
2622
import java.util.List;
27-
import java.util.Locale;
28-
import java.util.concurrent.TimeUnit;
2923
import java.util.regex.Pattern;
3024

31-
import javax.ws.rs.client.Entity;
32-
import javax.ws.rs.client.WebTarget;
33-
34-
import com.github.dockerjava.api.DockerClient;
35-
import com.github.dockerjava.api.command.DockerCmd;
36-
import com.github.dockerjava.api.exception.DockerClientException;
37-
import com.github.dockerjava.api.model.BuildResponseItem;
38-
import com.github.dockerjava.api.model.Frame;
39-
import com.github.dockerjava.core.DefaultDockerClientConfig;
40-
import com.github.dockerjava.core.DockerClientBuilder;
41-
import com.github.dockerjava.core.DockerClientConfig;
42-
import com.github.dockerjava.core.command.AttachContainerResultCallback;
43-
import com.github.dockerjava.core.command.BuildImageResultCallback;
44-
import com.github.dockerjava.core.command.WaitContainerResultCallback;
45-
import com.github.dockerjava.core.util.CompressArchiveUtil;
46-
import com.github.dockerjava.jaxrs.AbstrSyncDockerCmdExec;
47-
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
4825
import org.assertj.core.api.Condition;
4926
import org.junit.jupiter.api.Assumptions;
5027
import org.junit.jupiter.params.ParameterizedTest;
5128
import org.junit.jupiter.params.provider.MethodSource;
29+
import org.testcontainers.containers.GenericContainer;
30+
import org.testcontainers.containers.output.ToStringConsumer;
31+
import org.testcontainers.images.builder.ImageFromDockerfile;
32+
import org.testcontainers.utility.MountableFile;
5233

5334
import org.springframework.boot.ansi.AnsiColor;
5435

@@ -63,8 +44,6 @@
6344
*/
6445
class SysVinitLaunchScriptIT {
6546

66-
private final SpringBootDockerCmdExecFactory commandExecFactory = new SpringBootDockerCmdExecFactory();
67-
6847
private static final char ESC = 27;
6948

7049
@ParameterizedTest(name = "{0} {1}")
@@ -313,126 +292,15 @@ private void doLaunch(String os, String version, String script) throws Exception
313292
}
314293

315294
private String doTest(String os, String version, String script) throws Exception {
316-
DockerClient docker = createClient();
317-
String imageId = buildImage(os, version, docker);
318-
String container = createContainer(docker, imageId, script);
319-
try {
320-
copyFilesToContainer(docker, container, script);
321-
docker.startContainerCmd(container).exec();
322-
StringBuilder output = new StringBuilder();
323-
AttachContainerResultCallback resultCallback = docker.attachContainerCmd(container).withStdOut(true)
324-
.withStdErr(true).withFollowStream(true).withLogs(true).exec(new AttachContainerResultCallback() {
325-
326-
@Override
327-
public void onNext(Frame item) {
328-
output.append(new String(item.getPayload()));
329-
super.onNext(item);
330-
}
331-
332-
});
333-
resultCallback.awaitCompletion(60, TimeUnit.SECONDS);
334-
WaitContainerResultCallback waitContainerCallback = new WaitContainerResultCallback();
335-
docker.waitContainerCmd(container).exec(waitContainerCallback);
336-
waitContainerCallback.awaitCompletion(60, TimeUnit.SECONDS);
337-
return output.toString();
338-
}
339-
finally {
340-
try {
341-
docker.removeContainerCmd(container).exec();
342-
}
343-
catch (Exception ex) {
344-
// Continue
295+
ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false);
296+
try (LaunchScriptTestContainer container = new LaunchScriptTestContainer(os, version, script)) {
297+
container.withLogConsumer(consumer);
298+
container.start();
299+
while (container.isRunning()) {
300+
Thread.sleep(100);
345301
}
346302
}
347-
}
348-
349-
private DockerClient createClient() {
350-
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().withApiVersion("1.19")
351-
.build();
352-
return DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(this.commandExecFactory).build();
353-
}
354-
355-
private String buildImage(String os, String version, DockerClient docker) {
356-
String dockerfile = "src/test/resources/conf/" + os + "/" + version + "/Dockerfile";
357-
String tag = "spring-boot-it/" + os.toLowerCase(Locale.ENGLISH) + ":" + version;
358-
BuildImageResultCallback resultCallback = new BuildImageResultCallback() {
359-
360-
private List<BuildResponseItem> items = new ArrayList<>();
361-
362-
@Override
363-
public void onNext(BuildResponseItem item) {
364-
super.onNext(item);
365-
this.items.add(item);
366-
}
367-
368-
@Override
369-
public String awaitImageId() {
370-
try {
371-
awaitCompletion();
372-
}
373-
catch (InterruptedException ex) {
374-
throw new DockerClientException("Interrupted while waiting for image id", ex);
375-
}
376-
return getImageId();
377-
}
378-
379-
@SuppressWarnings("deprecation")
380-
private String getImageId() {
381-
if (this.items.isEmpty()) {
382-
throw new DockerClientException("Could not build image");
383-
}
384-
String imageId = extractImageId();
385-
if (imageId == null) {
386-
throw new DockerClientException(
387-
"Could not build image: " + this.items.get(this.items.size() - 1).getError());
388-
}
389-
return imageId;
390-
}
391-
392-
private String extractImageId() {
393-
Collections.reverse(this.items);
394-
for (BuildResponseItem item : this.items) {
395-
if (item.isErrorIndicated() || item.getStream() == null) {
396-
return null;
397-
}
398-
if (item.getStream().contains("Successfully built")) {
399-
return item.getStream().replace("Successfully built", "").trim();
400-
}
401-
}
402-
return null;
403-
}
404-
405-
};
406-
docker.buildImageCmd(new File(dockerfile)).withTags(new HashSet<>(Arrays.asList(tag))).exec(resultCallback);
407-
String imageId = resultCallback.awaitImageId();
408-
return imageId;
409-
}
410-
411-
private String createContainer(DockerClient docker, String imageId, String testScript) {
412-
return docker.createContainerCmd(imageId).withTty(false)
413-
.withCmd("/bin/bash", "-c", "chmod +x " + testScript + " && ./" + testScript).exec().getId();
414-
}
415-
416-
private void copyFilesToContainer(DockerClient docker, final String container, String script) {
417-
copyToContainer(docker, container, findApplication());
418-
copyToContainer(docker, container, new File("src/test/resources/scripts/test-functions.sh"));
419-
copyToContainer(docker, container, new File("src/test/resources/scripts/" + script));
420-
}
421-
422-
private void copyToContainer(DockerClient docker, final String container, final File file) {
423-
this.commandExecFactory.createCopyToContainerCmdExec().exec(new CopyToContainerCmd(container, file));
424-
}
425-
426-
private File findApplication() {
427-
File targetDir = new File("target");
428-
for (File file : targetDir.listFiles()) {
429-
if (file.getName().startsWith("spring-boot-launch-script-tests") && file.getName().endsWith(".jar")
430-
&& !file.getName().endsWith("-sources.jar")) {
431-
return file;
432-
}
433-
}
434-
throw new IllegalStateException(
435-
"Could not find test application in target directory. Have you built it (mvn package)?");
303+
return consumer.toUtf8String();
436304
}
437305

438306
private Condition<String> coloredString(AnsiColor color, String string) {
@@ -460,59 +328,30 @@ private String extract(String label, String output) {
460328
throw new IllegalArgumentException("Failed to extract " + label + " from output: " + output);
461329
}
462330

463-
private static final class CopyToContainerCmdExec extends AbstrSyncDockerCmdExec<CopyToContainerCmd, Void> {
331+
private static final class LaunchScriptTestContainer extends GenericContainer<LaunchScriptTestContainer> {
464332

465-
private CopyToContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) {
466-
super(baseResource, dockerClientConfig);
333+
private LaunchScriptTestContainer(String os, String version, String testScript) {
334+
super(new ImageFromDockerfile("spring-boot-launch-script/" + os.toLowerCase() + "-" + version)
335+
.withFileFromFile("Dockerfile",
336+
new File("src/test/resources/conf/" + os + "/" + version + "/Dockerfile"))
337+
.withFileFromFile("spring-boot-launch-script-tests.jar", findApplication())
338+
.withFileFromFile("test-functions.sh", new File("src/test/resources/scripts/test-functions.sh")));
339+
withCopyFileToContainer(MountableFile.forHostPath("src/test/resources/scripts/" + testScript),
340+
"/" + testScript);
341+
withCommand("/bin/bash", "-c", "chmod +x " + testScript + " && ./" + testScript);
342+
withStartupTimeout(Duration.ofMinutes(5));
467343
}
468344

469-
@Override
470-
protected Void execute(CopyToContainerCmd command) {
471-
try (InputStream streamToUpload = new FileInputStream(
472-
CompressArchiveUtil.archiveTARFiles(command.getFile().getParentFile(),
473-
Arrays.asList(command.getFile()), command.getFile().getName()))) {
474-
WebTarget webResource = getBaseResource().path("/containers/{id}/archive").resolveTemplate("id",
475-
command.getContainer());
476-
webResource.queryParam("path", ".").queryParam("noOverwriteDirNonDir", false).request()
477-
.put(Entity.entity(streamToUpload, "application/x-tar")).close();
478-
return null;
479-
}
480-
catch (Exception ex) {
481-
throw new RuntimeException(ex);
345+
private static File findApplication() {
346+
File targetDir = new File("target");
347+
for (File file : targetDir.listFiles()) {
348+
if (file.getName().startsWith("spring-boot-launch-script-tests") && file.getName().endsWith(".jar")
349+
&& !file.getName().endsWith("-sources.jar")) {
350+
return file;
351+
}
482352
}
483-
}
484-
485-
}
486-
487-
private static final class CopyToContainerCmd implements DockerCmd<Void> {
488-
489-
private final String container;
490-
491-
private final File file;
492-
493-
private CopyToContainerCmd(String container, File file) {
494-
this.container = container;
495-
this.file = file;
496-
}
497-
498-
String getContainer() {
499-
return this.container;
500-
}
501-
502-
File getFile() {
503-
return this.file;
504-
}
505-
506-
@Override
507-
public void close() {
508-
}
509-
510-
}
511-
512-
private static final class SpringBootDockerCmdExecFactory extends JerseyDockerCmdExecFactory {
513-
514-
private CopyToContainerCmdExec createCopyToContainerCmdExec() {
515-
return new CopyToContainerCmdExec(getBaseResource(), getDockerClientConfig());
353+
throw new IllegalStateException(
354+
"Could not find test application in target directory. Have you built it (mvn package)?");
516355
}
517356

518357
}

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/CentOS/6.9-a23bced6/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ RUN yum install -y wget && \
77
https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-linux.x86_64.rpm && \
88
yum --nogpg localinstall -y jdk.rpm && \
99
rm -f jdk.rpm
10+
ADD spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
11+
ADD test-functions.sh /test-functions.sh

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/Ubuntu/trusty-20160914/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ RUN apt-get update && \
66
curl -L https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u202-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u202b08.tar.gz | tar zx --strip-components=1
77
ENV JAVA_HOME /opt/openjdk
88
ENV PATH $JAVA_HOME/bin:$PATH
9+
ADD spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
10+
ADD test-functions.sh /test-functions.sh

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/Ubuntu/xenial-20160914/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ RUN apt-get update && \
66
curl -L https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u202-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u202b08.tar.gz | tar zx --strip-components=1
77
ENV JAVA_HOME /opt/openjdk
88
ENV PATH $JAVA_HOME/bin:$PATH
9+
ADD spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
10+
ADD test-functions.sh /test-functions.sh

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/test-functions.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
install_service() {
22
mkdir /test-service
3-
mv /spring-boot-launch-script-tests-*.jar /test-service/spring-boot-app.jar
3+
mv /spring-boot-launch-script-tests.jar /test-service/spring-boot-app.jar
44
chmod +x /test-service/spring-boot-app.jar
55
ln -s /test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
66
}
77

88
install_double_link_service() {
99
mkdir /test-service
10-
mv /spring-boot-launch-script-tests-*.jar /test-service/
11-
chmod +x /test-service/spring-boot-launch-script-tests-*.jar
12-
ln -s /test-service/spring-boot-launch-script-tests-*.jar /test-service/spring-boot-app.jar
10+
mv /spring-boot-launch-script-tests.jar /test-service/
11+
chmod +x /test-service/spring-boot-launch-script-tests.jar
12+
ln -s /test-service/spring-boot-launch-script-tests.jar /test-service/spring-boot-app.jar
1313
ln -s /test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
1414
}
1515

0 commit comments

Comments
 (0)