Skip to content

Convert Wildfly tests to run in Docker #53159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ subprojects {
':distribution:tools:launchers',
':distribution:tools:plugin-cli',
':qa:os',
':qa:wildfly',
':x-pack:plugin:autoscaling',
':x-pack:plugin:enrich'
]
Expand Down
202 changes: 26 additions & 176 deletions qa/wildfly/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.VersionProperties
import org.apache.tools.ant.taskdefs.condition.Os
import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask

import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.stream.Stream

/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
Expand All @@ -26,33 +17,14 @@ import java.util.stream.Stream
* under the License.
*/

import org.elasticsearch.gradle.VersionProperties

apply plugin: 'war'
apply plugin: 'elasticsearch.testclusters'
apply plugin: 'elasticsearch.build'
apply plugin: 'elasticsearch.rest-test'
apply plugin: 'elasticsearch.test.fixtures'
apply plugin: 'elasticsearch.distribution-download'

final String wildflyVersion = '11.0.0.Final'
final String wildflyDir = "${buildDir}/wildfly"
final String wildflyInstall = "${buildDir}/wildfly/wildfly-${wildflyVersion}"
int managementPort

repositories {
// the Wildfly distribution is not available via a repository, so we fake an Ivy repository on top of the download site
ivy {
name "wildfly"
url "https://download.jboss.org"
metadataSources {
artifact()
}
patternLayout {
artifact 'wildfly/[revision]/[module]-[revision].[ext]'
}
}
}

configurations {
wildfly
}
testFixtures.useFixture()

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

task unzipWildfly(type: Sync) {
into wildflyDir
from { zipTree(configurations.wildfly.singleFile) }
war {
archiveName 'example-app.war'
}

task deploy(type: Copy) {
dependsOn unzipWildfly, war
from war
into "${wildflyInstall}/standalone/deployments"
}

task writeElasticsearchProperties(type: DefaultTestClustersTask) {
onlyIf { !Os.isFamily(Os.FAMILY_WINDOWS) }
useCluster testClusters.integTest
dependsOn deploy
doLast {
final File elasticsearchProperties = file("${wildflyInstall}/standalone/configuration/elasticsearch.properties")
elasticsearchProperties.write(
[
"transport.uri=${-> testClusters.integTest.getAllTransportPortURI().get(0)}",
"cluster.name=integTest"
].join("\n"))
elasticsearch_distributions {
docker {
type = 'docker'
flavor = System.getProperty('tests.distribution', 'default')
version = VersionProperties.getElasticsearch()
failIfUnavailable = false // This ensures we skip this testing if Docker is unavailable
}
}

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

task startWildfly {
dependsOn enableIPv6, writeElasticsearchProperties
doLast {
// we skip these tests on Windows so we do no need to worry about compatibility here
final ProcessBuilder wildfly = new ProcessBuilder(
"${wildflyInstall}/bin/standalone.sh",
"-Djboss.http.port=0",
"-Djboss.https.port=0",
"-Djboss.management.http.port=0")
final Process process = wildfly.start()
new BufferedReader(new InputStreamReader(process.getInputStream())).withReader { br ->
String line
int httpPort = 0
while ((line = br.readLine()) != null) {
logger.info(line)
if (line.matches('.*Undertow HTTP listener default listening on .*:\\d+$')) {
assert httpPort == 0
final int index = line.lastIndexOf(":")
assert index >= 0
httpPort = Integer.parseInt(line.substring(index + 1))
// set this system property so the test runner knows the port Wildfly is listening for HTTP requests on
integTestRunner.systemProperty("tests.jboss.root", "http://localhost:$httpPort/wildfly-$version/transport")
} else if (line.matches('.*Http management interface listening on http://.*:\\d+/management$')) {
assert managementPort == 0
final int colonIndex = line.lastIndexOf(":")
assert colonIndex >= 0
final int slashIndex = line.lastIndexOf("/")
assert slashIndex >= 0
managementPort = Integer.parseInt(line.substring(colonIndex + 1, slashIndex))

/*
* As soon as we know the management port, we fork a process that will ensure the Wildfly process is killed if we
* teardown abnormally. We skip these tests on Windows so we do not need to worry about CLI compatibility here.
*/
final File script = new File(project.buildDir, "wildfly/wildfly.killer.sh")
script.setText(
["function shutdown {",
" ${wildflyInstall}/bin/jboss-cli.sh --controller=localhost:${-> managementPort} --connect command=shutdown",
"}",
"trap shutdown EXIT",
// will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
"read line\n"].join('\n'), 'UTF-8')
final ProcessBuilder killer = new ProcessBuilder("bash", script.absolutePath)
killer.start()

} else if (line.matches(".*WildFly Full \\d+\\.\\d+\\.\\d+\\.Final \\(WildFly Core \\d+\\.\\d+\\.\\d+\\.Final\\) started.*")) {
break
}
}

if (httpPort == 0 || managementPort == 0) {
String portType = httpPort == 0 ? "http" : "management"
throw new GradleException("Failed to find ${portType} port in wildfly log")
}
}
dockerCompose {
if ('default'.equalsIgnoreCase(System.getProperty('tests.distribution', 'default'))) {
useComposeFiles = ['docker-compose.yml']
} else {
useComposeFiles = ['docker-compose-oss.yml']
}
}

task configureTransportClient(type: LoggedExec) {
dependsOn startWildfly
// we skip these tests on Windows so we do not need to worry about compatibility here
commandLine "${wildflyInstall}/bin/jboss-cli.sh",
"--controller=localhost:${-> managementPort}",
"--connect",
"--command=/system-property=elasticsearch.properties:add(value=\${jboss.server.config.dir}/elasticsearch.properties)"
}

task stopWildfly(type: LoggedExec) {
// we skip these tests on Windows so we do not need to worry about CLI compatibility here
commandLine "${wildflyInstall}/bin/jboss-cli.sh", "--controller=localhost:${-> managementPort}", "--connect", "command=shutdown"
}

if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
integTestRunner.dependsOn(configureTransportClient)
final TaskExecutionAdapter logDumpListener = new TaskExecutionAdapter() {
@Override
void afterExecute(final Task task, final TaskState state) {
if (task != startWildfly && task != integTestRunner) {
// we might have been called from a parallel, unrelated task
return
}
if (state.failure != null) {
final File logFile = new File(wildflyInstall, "standalone/log/server.log")
println("\nWildfly server log (from ${logFile}):")
println('-----------------------------------------')
final Stream<String> stream = Files.lines(logFile.toPath(), StandardCharsets.UTF_8)
try {
for (String line : stream) {
println(line)
}
} finally {
stream.close()
}
println('=========================================')
}
}
}
startWildfly.doFirst {
project.gradle.addListener(logDumpListener)
}
integTestRunner.doFirst {
project.gradle.addListener(logDumpListener)
}
integTestRunner.doLast {
project.gradle.removeListener(logDumpListener)
}
startWildfly.doLast {
project.gradle.removeListener(logDumpListener)
}
integTestRunner.finalizedBy(stopWildfly)
} else {
integTest.enabled = false
testingConventions.enabled = false
task integTest(type: Test) {
outputs.doNotCacheIf('Build cache is disabled for Docker tests') { true }
maxParallelForks = '1'
include '**/*IT.class'
}

check.dependsOn(integTest)
check.dependsOn integTest

test.enabled = false

Expand Down
35 changes: 35 additions & 0 deletions qa/wildfly/docker-compose-oss.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: '3.7'
services:

wildfly:
image: jboss/wildfly:18.0.1.Final
environment:
JAVA_OPTS: -Delasticsearch.uri=elasticsearch:9200 -Djboss.http.port=8080 -Djava.net.preferIPv4Stack=true
volumes:
- ./build/distributions/example-app.war:/opt/jboss/wildfly/standalone/deployments/example-app.war
ports:
- "8080"
healthcheck:
start_period: 5s
test: ["CMD", "grep", "Admin console listening on", "/opt/jboss/wildfly/standalone/log/server.log"]
interval: 2s
timeout: 1s
retries: 5

elasticsearch:
image: elasticsearch-oss:test
environment:
discovery.type: single-node
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
healthcheck:
start_period: 15s
test: ["CMD", "curl", "-f", "-k", "http://localhost:9200"]
interval: 10s
timeout: 2s
retries: 5
35 changes: 35 additions & 0 deletions qa/wildfly/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: '3.7'
services:

wildfly:
image: jboss/wildfly:18.0.1.Final
environment:
JAVA_OPTS: -Delasticsearch.uri=elasticsearch:9200 -Djboss.http.port=8080 -Djava.net.preferIPv4Stack=true
volumes:
- ./build/distributions/example-app.war:/opt/jboss/wildfly/standalone/deployments/example-app.war
ports:
- "8080"
healthcheck:
start_period: 5s
test: ["CMD", "grep", "Admin console listening on", "/opt/jboss/wildfly/standalone/log/server.log"]
interval: 2s
timeout: 1s
retries: 5

elasticsearch:
image: elasticsearch:test
environment:
discovery.type: single-node
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
healthcheck:
start_period: 15s
test: ["CMD", "curl", "-f", "-k", "http://localhost:9200"]
interval: 10s
timeout: 2s
retries: 5
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
import java.util.Set;

@ApplicationPath("/transport")
public class TransportClientActivator extends Application {
public class RestHighLevelClientActivator extends Application {

@Override
public Set<Class<?>> getClasses() {
return Collections.singleton(TransportClientEmployeeResource.class);
return Collections.singleton(RestHighLevelClientEmployeeResource.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@

package org.elasticsearch.wildfly.transport;

import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.wildfly.model.Employee;

Expand All @@ -33,7 +36,6 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -44,25 +46,26 @@
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

@Path("/employees")
public class TransportClientEmployeeResource {
public class RestHighLevelClientEmployeeResource {

@Inject
private TransportClient client;
private RestHighLevelClient client;

@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getEmployeeById(final @PathParam("id") Long id) {
public Response getEmployeeById(final @PathParam("id") Long id) throws IOException {
Objects.requireNonNull(id);
final GetResponse response = client.prepareGet("megacorp", "employee", Long.toString(id)).get();
final GetResponse response = client.get(new GetRequest("megacorp", Long.toString(id)), RequestOptions.DEFAULT);
if (response.isExists()) {
final Map<String, Object> source = response.getSource();
final Employee employee = new Employee();
employee.setFirstName((String) source.get("first_name"));
employee.setLastName((String) source.get("last_name"));
employee.setAge((Integer) source.get("age"));
employee.setAbout((String) source.get("about"));
@SuppressWarnings("unchecked") final List<String> interests = (List<String>) source.get("interests");
@SuppressWarnings("unchecked")
final List<String> interests = (List<String>) source.get("interests");
employee.setInterests(interests);
return Response.ok(employee).build();
} else {
Expand Down Expand Up @@ -94,7 +97,10 @@ public Response putEmployeeById(final @PathParam("id") Long id, final Employee e
}
}
builder.endObject();
final IndexResponse response = client.prepareIndex("megacorp", "employee", Long.toString(id)).setSource(builder).get();
final IndexRequest request = new IndexRequest("megacorp");
request.id(Long.toString(id));
request.source(builder);
final IndexResponse response = client.index(request, RequestOptions.DEFAULT);
if (response.status().getStatus() == 201) {
return Response.created(new URI("/employees/" + id)).build();
} else {
Expand Down
Loading