Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
f75c73eb
Commit
f75c73eb
authored
Dec 20, 2019
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use Testcontainers in the launch script integration tests
Closes gh-19366
parent
3e48e36e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
47 additions
and
204 deletions
+47
-204
pom.xml
...integration-tests/spring-boot-launch-script-tests/pom.xml
+4
-5
LaunchVerificationController.java
...ework/boot/launchscript/LaunchVerificationController.java
+1
-1
SysVinitLaunchScriptIT.java
...ngframework/boot/launchscript/SysVinitLaunchScriptIT.java
+32
-194
Dockerfile
...ts/src/test/resources/conf/CentOS/6.9-a23bced6/Dockerfile
+2
-0
Dockerfile
...src/test/resources/conf/Ubuntu/trusty-20160914/Dockerfile
+2
-0
Dockerfile
...src/test/resources/conf/Ubuntu/xenial-20160914/Dockerfile
+2
-0
test-functions.sh
...script-tests/src/test/resources/scripts/test-functions.sh
+4
-4
No files found.
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/pom.xml
View file @
f75c73eb
...
@@ -30,14 +30,13 @@
...
@@ -30,14 +30,13 @@
<artifactId>
spring-boot-starter-undertow
</artifactId>
<artifactId>
spring-boot-starter-undertow
</artifactId>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.github.docker-java
</groupId>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
docker-java
</artifactId>
<artifactId>
spring-boot-starter-test
</artifactId>
<version>
3.1.2
</version>
<scope>
test
</scope>
<scope>
test
</scope>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
org.
springframework.boot
</groupId>
<groupId>
org.
testcontainers
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<artifactId>
testcontainers
</artifactId>
<scope>
test
</scope>
<scope>
test
</scope>
</dependency>
</dependency>
</dependencies>
</dependencies>
...
...
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/main/java/org/springframework/boot/launchscript/LaunchVerificationController.java
View file @
f75c73eb
...
@@ -24,7 +24,7 @@ public class LaunchVerificationController {
...
@@ -24,7 +24,7 @@ public class LaunchVerificationController {
@RequestMapping
(
"/"
)
@RequestMapping
(
"/"
)
public
String
verifyLaunch
()
{
public
String
verifyLaunch
()
{
return
"Launched"
;
return
"Launched
\n
"
;
}
}
}
}
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java
View file @
f75c73eb
...
@@ -17,39 +17,20 @@
...
@@ -17,39 +17,20 @@
package
org
.
springframework
.
boot
.
launchscript
;
package
org
.
springframework
.
boot
.
launchscript
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.time.Duration
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.concurrent.TimeUnit
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
javax.ws.rs.client.Entity
;
import
javax.ws.rs.client.WebTarget
;
import
com.github.dockerjava.api.DockerClient
;
import
com.github.dockerjava.api.command.DockerCmd
;
import
com.github.dockerjava.api.exception.DockerClientException
;
import
com.github.dockerjava.api.model.BuildResponseItem
;
import
com.github.dockerjava.api.model.Frame
;
import
com.github.dockerjava.core.DefaultDockerClientConfig
;
import
com.github.dockerjava.core.DockerClientBuilder
;
import
com.github.dockerjava.core.DockerClientConfig
;
import
com.github.dockerjava.core.command.AttachContainerResultCallback
;
import
com.github.dockerjava.core.command.BuildImageResultCallback
;
import
com.github.dockerjava.core.command.WaitContainerResultCallback
;
import
com.github.dockerjava.core.util.CompressArchiveUtil
;
import
com.github.dockerjava.jaxrs.AbstrSyncDockerCmdExec
;
import
com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory
;
import
org.assertj.core.api.Condition
;
import
org.assertj.core.api.Condition
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
import
org.junit.runners.Parameterized
;
import
org.junit.runners.Parameterized.Parameters
;
import
org.junit.runners.Parameterized.Parameters
;
import
org.testcontainers.containers.GenericContainer
;
import
org.testcontainers.containers.output.ToStringConsumer
;
import
org.testcontainers.images.builder.ImageFromDockerfile
;
import
org.testcontainers.utility.MountableFile
;
import
org.springframework.boot.ansi.AnsiColor
;
import
org.springframework.boot.ansi.AnsiColor
;
...
@@ -68,8 +49,6 @@ import static org.junit.Assume.assumeThat;
...
@@ -68,8 +49,6 @@ import static org.junit.Assume.assumeThat;
@RunWith
(
Parameterized
.
class
)
@RunWith
(
Parameterized
.
class
)
public
class
SysVinitLaunchScriptIT
{
public
class
SysVinitLaunchScriptIT
{
private
final
SpringBootDockerCmdExecFactory
commandExecFactory
=
new
SpringBootDockerCmdExecFactory
();
private
static
final
char
ESC
=
27
;
private
static
final
char
ESC
=
27
;
private
final
String
os
;
private
final
String
os
;
...
@@ -270,126 +249,15 @@ public class SysVinitLaunchScriptIT {
...
@@ -270,126 +249,15 @@ public class SysVinitLaunchScriptIT {
}
}
private
String
doTest
(
String
script
)
throws
Exception
{
private
String
doTest
(
String
script
)
throws
Exception
{
DockerClient
docker
=
createClient
();
ToStringConsumer
consumer
=
new
ToStringConsumer
().
withRemoveAnsiCodes
(
false
);
String
imageId
=
buildImage
(
docker
);
try
(
LaunchScriptTestContainer
container
=
new
LaunchScriptTestContainer
(
this
.
os
,
this
.
version
,
script
))
{
String
container
=
createContainer
(
docker
,
imageId
,
script
);
container
.
withLogConsumer
(
consumer
);
try
{
container
.
start
();
copyFilesToContainer
(
docker
,
container
,
script
);
while
(
container
.
isRunning
())
{
docker
.
startContainerCmd
(
container
).
exec
();
Thread
.
sleep
(
100
);
StringBuilder
output
=
new
StringBuilder
();
AttachContainerResultCallback
resultCallback
=
docker
.
attachContainerCmd
(
container
).
withStdOut
(
true
)
.
withStdErr
(
true
).
withFollowStream
(
true
).
withLogs
(
true
).
exec
(
new
AttachContainerResultCallback
()
{
@Override
public
void
onNext
(
Frame
item
)
{
output
.
append
(
new
String
(
item
.
getPayload
()));
super
.
onNext
(
item
);
}
});
resultCallback
.
awaitCompletion
(
60
,
TimeUnit
.
SECONDS
);
WaitContainerResultCallback
waitContainerCallback
=
new
WaitContainerResultCallback
();
docker
.
waitContainerCmd
(
container
).
exec
(
waitContainerCallback
);
waitContainerCallback
.
awaitCompletion
(
60
,
TimeUnit
.
SECONDS
);
return
output
.
toString
();
}
finally
{
try
{
docker
.
removeContainerCmd
(
container
).
exec
();
}
catch
(
Exception
ex
)
{
// Continue
}
}
}
private
DockerClient
createClient
()
{
DockerClientConfig
config
=
DefaultDockerClientConfig
.
createDefaultConfigBuilder
().
withApiVersion
(
"1.19"
)
.
build
();
return
DockerClientBuilder
.
getInstance
(
config
).
withDockerCmdExecFactory
(
this
.
commandExecFactory
).
build
();
}
private
String
buildImage
(
DockerClient
docker
)
{
String
dockerfile
=
"src/test/resources/conf/"
+
this
.
os
+
"/"
+
this
.
version
+
"/Dockerfile"
;
String
tag
=
"spring-boot-it/"
+
this
.
os
.
toLowerCase
(
Locale
.
ENGLISH
)
+
":"
+
this
.
version
;
BuildImageResultCallback
resultCallback
=
new
BuildImageResultCallback
()
{
private
List
<
BuildResponseItem
>
items
=
new
ArrayList
<>();
@Override
public
void
onNext
(
BuildResponseItem
item
)
{
super
.
onNext
(
item
);
this
.
items
.
add
(
item
);
}
@Override
public
String
awaitImageId
()
{
try
{
awaitCompletion
();
}
catch
(
InterruptedException
ex
)
{
throw
new
DockerClientException
(
"Interrupted while waiting for image id"
,
ex
);
}
return
getImageId
();
}
@SuppressWarnings
(
"deprecation"
)
private
String
getImageId
()
{
if
(
this
.
items
.
isEmpty
())
{
throw
new
DockerClientException
(
"Could not build image"
);
}
String
imageId
=
extractImageId
();
if
(
imageId
==
null
)
{
throw
new
DockerClientException
(
"Could not build image: "
+
this
.
items
.
get
(
this
.
items
.
size
()
-
1
).
getError
());
}
return
imageId
;
}
private
String
extractImageId
()
{
Collections
.
reverse
(
this
.
items
);
for
(
BuildResponseItem
item
:
this
.
items
)
{
if
(
item
.
isErrorIndicated
()
||
item
.
getStream
()
==
null
)
{
return
null
;
}
if
(
item
.
getStream
().
contains
(
"Successfully built"
))
{
return
item
.
getStream
().
replace
(
"Successfully built"
,
""
).
trim
();
}
}
return
null
;
}
};
docker
.
buildImageCmd
(
new
File
(
dockerfile
)).
withTags
(
new
HashSet
<>(
Arrays
.
asList
(
tag
))).
exec
(
resultCallback
);
String
imageId
=
resultCallback
.
awaitImageId
();
return
imageId
;
}
private
String
createContainer
(
DockerClient
docker
,
String
imageId
,
String
testScript
)
{
return
docker
.
createContainerCmd
(
imageId
).
withTty
(
false
)
.
withCmd
(
"/bin/bash"
,
"-c"
,
"chmod +x "
+
testScript
+
" && ./"
+
testScript
).
exec
().
getId
();
}
private
void
copyFilesToContainer
(
DockerClient
docker
,
final
String
container
,
String
script
)
{
copyToContainer
(
docker
,
container
,
findApplication
());
copyToContainer
(
docker
,
container
,
new
File
(
"src/test/resources/scripts/test-functions.sh"
));
copyToContainer
(
docker
,
container
,
new
File
(
"src/test/resources/scripts/"
+
script
));
}
private
void
copyToContainer
(
DockerClient
docker
,
final
String
container
,
final
File
file
)
{
this
.
commandExecFactory
.
createCopyToContainerCmdExec
().
exec
(
new
CopyToContainerCmd
(
container
,
file
));
}
private
File
findApplication
()
{
File
targetDir
=
new
File
(
"target"
);
for
(
File
file
:
targetDir
.
listFiles
())
{
if
(
file
.
getName
().
startsWith
(
"spring-boot-launch-script-tests"
)
&&
file
.
getName
().
endsWith
(
".jar"
)
&&
!
file
.
getName
().
endsWith
(
"-sources.jar"
))
{
return
file
;
}
}
}
}
throw
new
IllegalStateException
(
return
consumer
.
toUtf8String
();
"Could not find test application in target directory. Have you built it (mvn package)?"
);
}
}
private
Condition
<
String
>
coloredString
(
AnsiColor
color
,
String
string
)
{
private
Condition
<
String
>
coloredString
(
AnsiColor
color
,
String
string
)
{
...
@@ -417,60 +285,30 @@ public class SysVinitLaunchScriptIT {
...
@@ -417,60 +285,30 @@ public class SysVinitLaunchScriptIT {
throw
new
IllegalArgumentException
(
"Failed to extract "
+
label
+
" from output: "
+
output
);
throw
new
IllegalArgumentException
(
"Failed to extract "
+
label
+
" from output: "
+
output
);
}
}
private
static
final
class
CopyToContainerCmdExec
extends
AbstrSyncDockerCmdExec
<
CopyToContainerCmd
,
Void
>
{
private
static
final
class
LaunchScriptTestContainer
extends
GenericContainer
<
LaunchScriptTestContainer
>
{
private
CopyToContainerCmdExec
(
WebTarget
baseResource
,
DockerClientConfig
dockerClientConfig
)
{
private
LaunchScriptTestContainer
(
String
os
,
String
version
,
String
testScript
)
{
super
(
baseResource
,
dockerClientConfig
);
super
(
new
ImageFromDockerfile
(
"spring-boot-launch-script/"
+
os
.
toLowerCase
()
+
"-"
+
version
)
.
withFileFromFile
(
"Dockerfile"
,
new
File
(
"src/test/resources/conf/"
+
os
+
"/"
+
version
+
"/Dockerfile"
))
.
withFileFromFile
(
"spring-boot-launch-script-tests.jar"
,
findApplication
())
.
withFileFromFile
(
"test-functions.sh"
,
new
File
(
"src/test/resources/scripts/test-functions.sh"
)));
withCopyFileToContainer
(
MountableFile
.
forHostPath
(
"src/test/resources/scripts/"
+
testScript
),
"/"
+
testScript
);
withCommand
(
"/bin/bash"
,
"-c"
,
"chmod +x "
+
testScript
+
" && ./"
+
testScript
);
withStartupTimeout
(
Duration
.
ofMinutes
(
5
));
}
}
@Override
private
static
File
findApplication
()
{
protected
Void
execute
(
CopyToContainerCmd
command
)
{
File
targetDir
=
new
File
(
"target"
);
try
(
InputStream
streamToUpload
=
new
FileInputStream
(
for
(
File
file
:
targetDir
.
listFiles
())
{
CompressArchiveUtil
.
archiveTARFiles
(
command
.
getFile
().
getParentFile
(),
if
(
file
.
getName
().
startsWith
(
"spring-boot-launch-script-tests"
)
&&
file
.
getName
().
endsWith
(
".jar"
)
Arrays
.
asList
(
command
.
getFile
()),
command
.
getFile
().
getName
())))
{
&&
!
file
.
getName
().
endsWith
(
"-sources.jar"
))
{
WebTarget
webResource
=
getBaseResource
().
path
(
"/containers/{id}/archive"
).
resolveTemplate
(
"id"
,
return
file
;
command
.
getContainer
());
}
webResource
.
queryParam
(
"path"
,
"."
).
queryParam
(
"noOverwriteDirNonDir"
,
false
).
request
()
.
put
(
Entity
.
entity
(
streamToUpload
,
"application/x-tar"
)).
close
();
return
null
;
}
catch
(
Exception
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
}
throw
new
IllegalStateException
(
"Could not find test application in target directory. Have you built it (mvn package)?"
);
}
private
static
final
class
CopyToContainerCmd
implements
DockerCmd
<
Void
>
{
private
final
String
container
;
private
final
File
file
;
private
CopyToContainerCmd
(
String
container
,
File
file
)
{
this
.
container
=
container
;
this
.
file
=
file
;
}
public
String
getContainer
()
{
return
this
.
container
;
}
public
File
getFile
()
{
return
this
.
file
;
}
@Override
public
void
close
()
{
}
}
private
static
final
class
SpringBootDockerCmdExecFactory
extends
JerseyDockerCmdExecFactory
{
private
CopyToContainerCmdExec
createCopyToContainerCmdExec
()
{
return
new
CopyToContainerCmdExec
(
getBaseResource
(),
getDockerClientConfig
());
}
}
}
}
...
...
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/CentOS/6.9-a23bced6/Dockerfile
View file @
f75c73eb
...
@@ -7,3 +7,5 @@ RUN yum install -y wget && \
...
@@ -7,3 +7,5 @@ RUN yum install -y wget && \
https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-linux.x86_64.rpm
&&
\
https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-linux.x86_64.rpm
&&
\
yum
--nogpg
localinstall
-y
jdk.rpm
&&
\
yum
--nogpg
localinstall
-y
jdk.rpm
&&
\
rm
-f
jdk.rpm
rm
-f
jdk.rpm
ADD
spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
ADD
test-functions.sh /test-functions.sh
\ No newline at end of file
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/Ubuntu/trusty-20160914/Dockerfile
View file @
f75c73eb
...
@@ -6,3 +6,5 @@ RUN apt-get update && \
...
@@ -6,3 +6,5 @@ RUN apt-get update && \
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
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
ENV
JAVA_HOME /opt/openjdk
ENV
JAVA_HOME /opt/openjdk
ENV
PATH $JAVA_HOME/bin:$PATH
ENV
PATH $JAVA_HOME/bin:$PATH
ADD
spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
ADD
test-functions.sh /test-functions.sh
\ No newline at end of file
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/conf/Ubuntu/xenial-20160914/Dockerfile
View file @
f75c73eb
...
@@ -6,3 +6,5 @@ RUN apt-get update && \
...
@@ -6,3 +6,5 @@ RUN apt-get update && \
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
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
ENV
JAVA_HOME /opt/openjdk
ENV
JAVA_HOME /opt/openjdk
ENV
PATH $JAVA_HOME/bin:$PATH
ENV
PATH $JAVA_HOME/bin:$PATH
ADD
spring-boot-launch-script-tests.jar /spring-boot-launch-script-tests.jar
ADD
test-functions.sh /test-functions.sh
\ No newline at end of file
spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/test-functions.sh
View file @
f75c73eb
install_service
()
{
install_service
()
{
mkdir
/test-service
mkdir
/test-service
mv
/spring-boot-launch-script-tests
-
*
.jar /test-service/spring-boot-app.jar
mv
/spring-boot-launch-script-tests.jar /test-service/spring-boot-app.jar
chmod
+x /test-service/spring-boot-app.jar
chmod
+x /test-service/spring-boot-app.jar
ln
-s
/test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
ln
-s
/test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
}
}
install_double_link_service
()
{
install_double_link_service
()
{
mkdir
/test-service
mkdir
/test-service
mv
/spring-boot-launch-script-tests
-
*
.jar /test-service/
mv
/spring-boot-launch-script-tests.jar /test-service/
chmod
+x /test-service/spring-boot-launch-script-tests
-
*
.jar
chmod
+x /test-service/spring-boot-launch-script-tests.jar
ln
-s
/test-service/spring-boot-launch-script-tests
-
*
.jar /test-service/spring-boot-app.jar
ln
-s
/test-service/spring-boot-launch-script-tests.jar /test-service/spring-boot-app.jar
ln
-s
/test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
ln
-s
/test-service/spring-boot-app.jar /etc/init.d/spring-boot-app
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment