Skip to content

Commit 17de77f

Browse files
authored
Convert Wildfly tests to run in Docker (#53159)
Backport of #53126. Convert the Wildfly tests to run using Docker Compose. This drastically simplifies the build setup, and will hopefully make the tests more resilient.
1 parent c2a2fcb commit 17de77f

10 files changed

+210
-297
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ subprojects {
116116
':distribution:tools:launchers',
117117
':distribution:tools:plugin-cli',
118118
':qa:os',
119+
':qa:wildfly',
119120
':x-pack:plugin:autoscaling',
120121
':x-pack:plugin:enrich',
121122
':x-pack:plugin:logstash'

qa/wildfly/build.gradle

Lines changed: 26 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
import org.elasticsearch.gradle.LoggedExec
2-
import org.elasticsearch.gradle.VersionProperties
3-
import org.apache.tools.ant.taskdefs.condition.Os
4-
import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask
5-
6-
import java.nio.charset.StandardCharsets
7-
import java.nio.file.Files
8-
import java.util.stream.Stream
9-
101
/*
112
* Licensed to Elasticsearch under one or more contributor
123
* license agreements. See the NOTICE file distributed with
@@ -26,33 +17,14 @@ import java.util.stream.Stream
2617
* under the License.
2718
*/
2819

20+
import org.elasticsearch.gradle.VersionProperties
21+
2922
apply plugin: 'war'
30-
apply plugin: 'elasticsearch.testclusters'
3123
apply plugin: 'elasticsearch.build'
32-
apply plugin: 'elasticsearch.rest-test'
24+
apply plugin: 'elasticsearch.test.fixtures'
25+
apply plugin: 'elasticsearch.distribution-download'
3326

34-
final String wildflyVersion = '11.0.0.Final'
35-
final String wildflyDir = "${buildDir}/wildfly"
36-
final String wildflyInstall = "${buildDir}/wildfly/wildfly-${wildflyVersion}"
37-
int managementPort
38-
39-
repositories {
40-
// the Wildfly distribution is not available via a repository, so we fake an Ivy repository on top of the download site
41-
ivy {
42-
name "wildfly"
43-
url "https://download.jboss.org"
44-
metadataSources {
45-
artifact()
46-
}
47-
patternLayout {
48-
artifact 'wildfly/[revision]/[module]-[revision].[ext]'
49-
}
50-
}
51-
}
52-
53-
configurations {
54-
wildfly
55-
}
27+
testFixtures.useFixture()
5628

5729
dependencies {
5830
providedCompile 'javax.enterprise:cdi-api:1.2'
@@ -72,164 +44,42 @@ dependencies {
7244
compile "com.fasterxml.jackson.module:jackson-module-jaxb-annotations:${versions.jackson}"
7345
compile "org.apache.logging.log4j:log4j-api:${versions.log4j}"
7446
compile "org.apache.logging.log4j:log4j-core:${versions.log4j}"
75-
compile project(path: ':client:transport', configuration: 'runtime')
76-
wildfly "org.jboss:wildfly:${wildflyVersion}@zip"
47+
compile project(path: ':client:rest-high-level')
7748
testCompile project(':test:framework')
7849
}
7950

80-
task unzipWildfly(type: Sync) {
81-
into wildflyDir
82-
from { zipTree(configurations.wildfly.singleFile) }
51+
war {
52+
archiveName 'example-app.war'
8353
}
8454

85-
task deploy(type: Copy) {
86-
dependsOn unzipWildfly, war
87-
from war
88-
into "${wildflyInstall}/standalone/deployments"
89-
}
90-
91-
task writeElasticsearchProperties(type: DefaultTestClustersTask) {
92-
onlyIf { !Os.isFamily(Os.FAMILY_WINDOWS) }
93-
useCluster testClusters.integTest
94-
dependsOn deploy
95-
doLast {
96-
final File elasticsearchProperties = file("${wildflyInstall}/standalone/configuration/elasticsearch.properties")
97-
elasticsearchProperties.write(
98-
[
99-
"transport.uri=${-> testClusters.integTest.getAllTransportPortURI().get(0)}",
100-
"cluster.name=integTest"
101-
].join("\n"))
55+
elasticsearch_distributions {
56+
docker {
57+
type = 'docker'
58+
flavor = System.getProperty('tests.distribution', 'default')
59+
version = VersionProperties.getElasticsearch()
60+
failIfUnavailable = false // This ensures we skip this testing if Docker is unavailable
10261
}
10362
}
10463

105-
// the default configuration ships with IPv6 disabled but our cluster could be bound to IPv6 if the host supports it
106-
task enableIPv6 {
107-
dependsOn unzipWildfly
108-
doLast {
109-
final File standaloneConf = file("${wildflyInstall}/bin/standalone.conf")
110-
final List<String> lines =
111-
Files.readAllLines(standaloneConf.toPath())
112-
.collect { line -> line.replace("-Djava.net.preferIPv4Stack=true", "-Djava.net.preferIPv4Stack=false") }
113-
standaloneConf.write(lines.join("\n"))
114-
}
64+
preProcessFixture {
65+
dependsOn war, elasticsearch_distributions.docker
11566
}
11667

117-
task startWildfly {
118-
dependsOn enableIPv6, writeElasticsearchProperties
119-
doLast {
120-
// we skip these tests on Windows so we do no need to worry about compatibility here
121-
final ProcessBuilder wildfly = new ProcessBuilder(
122-
"${wildflyInstall}/bin/standalone.sh",
123-
"-Djboss.http.port=0",
124-
"-Djboss.https.port=0",
125-
"-Djboss.management.http.port=0")
126-
final Process process = wildfly.start()
127-
new BufferedReader(new InputStreamReader(process.getInputStream())).withReader { br ->
128-
String line
129-
int httpPort = 0
130-
while ((line = br.readLine()) != null) {
131-
logger.info(line)
132-
if (line.matches('.*Undertow HTTP listener default listening on .*:\\d+$')) {
133-
assert httpPort == 0
134-
final int index = line.lastIndexOf(":")
135-
assert index >= 0
136-
httpPort = Integer.parseInt(line.substring(index + 1))
137-
// set this system property so the test runner knows the port Wildfly is listening for HTTP requests on
138-
integTestRunner.systemProperty("tests.jboss.root", "http://localhost:$httpPort/wildfly-$version/transport")
139-
} else if (line.matches('.*Http management interface listening on http://.*:\\d+/management$')) {
140-
assert managementPort == 0
141-
final int colonIndex = line.lastIndexOf(":")
142-
assert colonIndex >= 0
143-
final int slashIndex = line.lastIndexOf("/")
144-
assert slashIndex >= 0
145-
managementPort = Integer.parseInt(line.substring(colonIndex + 1, slashIndex))
146-
147-
/*
148-
* As soon as we know the management port, we fork a process that will ensure the Wildfly process is killed if we
149-
* teardown abnormally. We skip these tests on Windows so we do not need to worry about CLI compatibility here.
150-
*/
151-
final File script = new File(project.buildDir, "wildfly/wildfly.killer.sh")
152-
script.setText(
153-
["function shutdown {",
154-
" ${wildflyInstall}/bin/jboss-cli.sh --controller=localhost:${-> managementPort} --connect command=shutdown",
155-
"}",
156-
"trap shutdown EXIT",
157-
// will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
158-
"read line\n"].join('\n'), 'UTF-8')
159-
final ProcessBuilder killer = new ProcessBuilder("bash", script.absolutePath)
160-
killer.start()
161-
162-
} else if (line.matches(".*WildFly Full \\d+\\.\\d+\\.\\d+\\.Final \\(WildFly Core \\d+\\.\\d+\\.\\d+\\.Final\\) started.*")) {
163-
break
164-
}
165-
}
166-
167-
if (httpPort == 0 || managementPort == 0) {
168-
String portType = httpPort == 0 ? "http" : "management"
169-
throw new GradleException("Failed to find ${portType} port in wildfly log")
170-
}
171-
}
68+
dockerCompose {
69+
if ('default'.equalsIgnoreCase(System.getProperty('tests.distribution', 'default'))) {
70+
useComposeFiles = ['docker-compose.yml']
71+
} else {
72+
useComposeFiles = ['docker-compose-oss.yml']
17273
}
17374
}
17475

175-
task configureTransportClient(type: LoggedExec) {
176-
dependsOn startWildfly
177-
// we skip these tests on Windows so we do not need to worry about compatibility here
178-
commandLine "${wildflyInstall}/bin/jboss-cli.sh",
179-
"--controller=localhost:${-> managementPort}",
180-
"--connect",
181-
"--command=/system-property=elasticsearch.properties:add(value=\${jboss.server.config.dir}/elasticsearch.properties)"
182-
}
183-
184-
task stopWildfly(type: LoggedExec) {
185-
// we skip these tests on Windows so we do not need to worry about CLI compatibility here
186-
commandLine "${wildflyInstall}/bin/jboss-cli.sh", "--controller=localhost:${-> managementPort}", "--connect", "command=shutdown"
187-
}
188-
189-
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
190-
integTestRunner.dependsOn(configureTransportClient)
191-
final TaskExecutionAdapter logDumpListener = new TaskExecutionAdapter() {
192-
@Override
193-
void afterExecute(final Task task, final TaskState state) {
194-
if (task != startWildfly && task != integTestRunner) {
195-
// we might have been called from a parallel, unrelated task
196-
return
197-
}
198-
if (state.failure != null) {
199-
final File logFile = new File(wildflyInstall, "standalone/log/server.log")
200-
println("\nWildfly server log (from ${logFile}):")
201-
println('-----------------------------------------')
202-
final Stream<String> stream = Files.lines(logFile.toPath(), StandardCharsets.UTF_8)
203-
try {
204-
for (String line : stream) {
205-
println(line)
206-
}
207-
} finally {
208-
stream.close()
209-
}
210-
println('=========================================')
211-
}
212-
}
213-
}
214-
startWildfly.doFirst {
215-
project.gradle.addListener(logDumpListener)
216-
}
217-
integTestRunner.doFirst {
218-
project.gradle.addListener(logDumpListener)
219-
}
220-
integTestRunner.doLast {
221-
project.gradle.removeListener(logDumpListener)
222-
}
223-
startWildfly.doLast {
224-
project.gradle.removeListener(logDumpListener)
225-
}
226-
integTestRunner.finalizedBy(stopWildfly)
227-
} else {
228-
integTest.enabled = false
229-
testingConventions.enabled = false
76+
task integTest(type: Test) {
77+
outputs.doNotCacheIf('Build cache is disabled for Docker tests') { true }
78+
maxParallelForks = '1'
79+
include '**/*IT.class'
23080
}
23181

232-
check.dependsOn(integTest)
82+
check.dependsOn integTest
23383

23484
test.enabled = false
23585

qa/wildfly/docker-compose-oss.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
version: '3.7'
2+
services:
3+
4+
wildfly:
5+
image: jboss/wildfly:18.0.1.Final
6+
environment:
7+
JAVA_OPTS: -Delasticsearch.uri=elasticsearch:9200 -Djboss.http.port=8080 -Djava.net.preferIPv4Stack=true
8+
volumes:
9+
- ./build/distributions/example-app.war:/opt/jboss/wildfly/standalone/deployments/example-app.war
10+
ports:
11+
- "8080"
12+
healthcheck:
13+
start_period: 5s
14+
test: ["CMD", "grep", "Admin console listening on", "/opt/jboss/wildfly/standalone/log/server.log"]
15+
interval: 2s
16+
timeout: 1s
17+
retries: 5
18+
19+
elasticsearch:
20+
image: elasticsearch-oss:test
21+
environment:
22+
discovery.type: single-node
23+
ulimits:
24+
memlock:
25+
soft: -1
26+
hard: -1
27+
nofile:
28+
soft: 65536
29+
hard: 65536
30+
healthcheck:
31+
start_period: 15s
32+
test: ["CMD", "curl", "-f", "-k", "http://localhost:9200"]
33+
interval: 10s
34+
timeout: 2s
35+
retries: 5

qa/wildfly/docker-compose.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
version: '3.7'
2+
services:
3+
4+
wildfly:
5+
image: jboss/wildfly:18.0.1.Final
6+
environment:
7+
JAVA_OPTS: -Delasticsearch.uri=elasticsearch:9200 -Djboss.http.port=8080 -Djava.net.preferIPv4Stack=true
8+
volumes:
9+
- ./build/distributions/example-app.war:/opt/jboss/wildfly/standalone/deployments/example-app.war
10+
ports:
11+
- "8080"
12+
healthcheck:
13+
start_period: 5s
14+
test: ["CMD", "grep", "Admin console listening on", "/opt/jboss/wildfly/standalone/log/server.log"]
15+
interval: 2s
16+
timeout: 1s
17+
retries: 5
18+
19+
elasticsearch:
20+
image: elasticsearch:test
21+
environment:
22+
discovery.type: single-node
23+
ulimits:
24+
memlock:
25+
soft: -1
26+
hard: -1
27+
nofile:
28+
soft: 65536
29+
hard: 65536
30+
healthcheck:
31+
start_period: 15s
32+
test: ["CMD", "curl", "-f", "-k", "http://localhost:9200"]
33+
interval: 10s
34+
timeout: 2s
35+
retries: 5

qa/wildfly/src/main/java/org/elasticsearch/wildfly/transport/TransportClientActivator.java renamed to qa/wildfly/src/main/java/org/elasticsearch/wildfly/transport/RestHighLevelClientActivator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
import java.util.Set;
2727

2828
@ApplicationPath("/transport")
29-
public class TransportClientActivator extends Application {
29+
public class RestHighLevelClientActivator extends Application {
3030

3131
@Override
3232
public Set<Class<?>> getClasses() {
33-
return Collections.singleton(TransportClientEmployeeResource.class);
33+
return Collections.singleton(RestHighLevelClientEmployeeResource.class);
3434
}
3535

3636
}

qa/wildfly/src/main/java/org/elasticsearch/wildfly/transport/TransportClientEmployeeResource.java renamed to qa/wildfly/src/main/java/org/elasticsearch/wildfly/transport/RestHighLevelClientEmployeeResource.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
package org.elasticsearch.wildfly.transport;
2121

22+
import org.elasticsearch.action.get.GetRequest;
2223
import org.elasticsearch.action.get.GetResponse;
24+
import org.elasticsearch.action.index.IndexRequest;
2325
import org.elasticsearch.action.index.IndexResponse;
24-
import org.elasticsearch.client.transport.TransportClient;
26+
import org.elasticsearch.client.RequestOptions;
27+
import org.elasticsearch.client.RestHighLevelClient;
2528
import org.elasticsearch.common.xcontent.XContentBuilder;
2629
import org.elasticsearch.wildfly.model.Employee;
2730

@@ -33,7 +36,6 @@
3336
import javax.ws.rs.Produces;
3437
import javax.ws.rs.core.MediaType;
3538
import javax.ws.rs.core.Response;
36-
3739
import java.io.IOException;
3840
import java.net.URI;
3941
import java.net.URISyntaxException;
@@ -44,25 +46,26 @@
4446
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
4547

4648
@Path("/employees")
47-
public class TransportClientEmployeeResource {
49+
public class RestHighLevelClientEmployeeResource {
4850

4951
@Inject
50-
private TransportClient client;
52+
private RestHighLevelClient client;
5153

5254
@GET
5355
@Path("/{id}")
5456
@Produces(MediaType.APPLICATION_JSON)
55-
public Response getEmployeeById(final @PathParam("id") Long id) {
57+
public Response getEmployeeById(final @PathParam("id") Long id) throws IOException {
5658
Objects.requireNonNull(id);
57-
final GetResponse response = client.prepareGet("megacorp", "employee", Long.toString(id)).get();
59+
final GetResponse response = client.get(new GetRequest("megacorp", Long.toString(id)), RequestOptions.DEFAULT);
5860
if (response.isExists()) {
5961
final Map<String, Object> source = response.getSource();
6062
final Employee employee = new Employee();
6163
employee.setFirstName((String) source.get("first_name"));
6264
employee.setLastName((String) source.get("last_name"));
6365
employee.setAge((Integer) source.get("age"));
6466
employee.setAbout((String) source.get("about"));
65-
@SuppressWarnings("unchecked") final List<String> interests = (List<String>) source.get("interests");
67+
@SuppressWarnings("unchecked")
68+
final List<String> interests = (List<String>) source.get("interests");
6669
employee.setInterests(interests);
6770
return Response.ok(employee).build();
6871
} else {
@@ -94,7 +97,10 @@ public Response putEmployeeById(final @PathParam("id") Long id, final Employee e
9497
}
9598
}
9699
builder.endObject();
97-
final IndexResponse response = client.prepareIndex("megacorp", "employee", Long.toString(id)).setSource(builder).get();
100+
final IndexRequest request = new IndexRequest("megacorp");
101+
request.id(Long.toString(id));
102+
request.source(builder);
103+
final IndexResponse response = client.index(request, RequestOptions.DEFAULT);
98104
if (response.status().getStatus() == 201) {
99105
return Response.created(new URI("/employees/" + id)).build();
100106
} else {

0 commit comments

Comments
 (0)