Merge pull request #14728 from rjernst/no_more_jvm_leaks

Use ant exec for starting elasticsearch in integ tests
This commit is contained in:
Ryan Ernst 2015-11-12 22:48:11 -08:00
commit 9aa39401d6
1 changed files with 58 additions and 42 deletions

View File

@ -18,22 +18,17 @@
*/ */
package org.elasticsearch.gradle.test package org.elasticsearch.gradle.test
import org.gradle.internal.jvm.Jvm import org.apache.tools.ant.DefaultLogger
import java.nio.file.Paths
import org.apache.tools.ant.taskdefs.condition.Os import org.apache.tools.ant.taskdefs.condition.Os
import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.VersionProperties
import org.gradle.api.DefaultTask import org.gradle.api.*
import org.gradle.api.GradleException
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Exec
import java.nio.file.Paths
/** /**
* A helper for creating tasks to build a cluster that is used by a task, and tear down the cluster when the task is finished. * A helper for creating tasks to build a cluster that is used by a task, and tear down the cluster when the task is finished.
*/ */
@ -216,23 +211,57 @@ class ClusterFormationTasks {
'JAVA_HOME' : project.javaHome, 'JAVA_HOME' : project.javaHome,
'ES_GC_OPTS': config.jvmArgs 'ES_GC_OPTS': config.jvmArgs
] ]
List esProps = config.systemProperties.collect { key, value -> "-D${key}=${value}" } List<String> esProps = config.systemProperties.collect { key, value -> "-D${key}=${value}" }
for (Map.Entry<String, String> property : System.properties.entrySet()) { for (Map.Entry<String, String> property : System.properties.entrySet()) {
if (property.getKey().startsWith('es.')) { if (property.getKey().startsWith('es.')) {
esProps.add("-D${property.getKey()}=${property.getValue()}") esProps.add("-D${property.getKey()}=${property.getValue()}")
} }
} }
Closure esPostStartActions = { ant, logger -> String executable
ant.waitfor(maxwait: '30', maxwaitunit: 'second', checkevery: '500', checkeveryunit: 'millisecond', timeoutproperty: "failed${name.capitalize()}") { List<String> esArgs = []
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
executable = 'cmd'
esArgs.add('/C')
esArgs.add('call')
} else {
executable = 'sh'
}
// running with cmd on windows will look for this with the .bat extension
esArgs.add(new File(home, 'bin/elasticsearch').toString())
// this closure is converted into ant nodes by groovy's AntBuilder
Closure antRunner = {
exec(executable: executable, spawn: config.daemonize, dir: cwd, taskname: 'elasticsearch') {
esEnv.each { key, value -> env(key: key, value: value) }
(esArgs + esProps).each { arg(value: it) }
}
waitfor(maxwait: '30', maxwaitunit: 'second', checkevery: '500', checkeveryunit: 'millisecond', timeoutproperty: "failed${name}") {
and { and {
resourceexists { resourceexists {
file file: pidFile.toString() file(file: pidFile.toString())
} }
http(url: "http://localhost:${config.httpPort}") http(url: "http://localhost:${config.httpPort}")
} }
} }
}
// this closure is the actual code to run elasticsearch
Closure elasticsearchRunner = {
ByteArrayOutputStream buffer = new ByteArrayOutputStream()
if (logger.isInfoEnabled() || config.daemonize == false) {
// run with piping streams directly out (even stderr to stdout since gradle would capture it)
runAntCommand(project, antRunner, System.out, System.err)
} else {
// buffer the output, we may not need to print it
PrintStream captureStream = new PrintStream(buffer, true, "UTF-8")
runAntCommand(project, antRunner, captureStream, captureStream)
}
if (ant.properties.containsKey("failed${name}".toString())) { if (ant.properties.containsKey("failed${name}".toString())) {
// the waitfor failed, so dump any output we got (may be empty if info logging, but that is ok)
logger.error(buffer.toString('UTF-8'))
// also dump the cluster's log file, it may be useful
File logFile = new File(home, "logs/${clusterName}.log") File logFile = new File(home, "logs/${clusterName}.log")
if (logFile.exists()) { if (logFile.exists()) {
logFile.eachLine { line -> logger.error(line) } logFile.eachLine { line -> logger.error(line) }
@ -240,35 +269,10 @@ class ClusterFormationTasks {
throw new GradleException('Failed to start elasticsearch') throw new GradleException('Failed to start elasticsearch')
} }
} }
File esScript = new File(home, 'bin/elasticsearch')
if (Os.isFamily(Os.FAMILY_WINDOWS)) { Task start = project.tasks.create(name: name, type: DefaultTask, dependsOn: setup)
// elasticsearch.bat is spawned as it has no daemon mode start.doLast(elasticsearchRunner)
return project.tasks.create(name: name, type: DefaultTask, dependsOn: setup) << { return start
// Fall back to Ant exec task as Gradle Exec task does not support spawning yet
ant.exec(executable: 'cmd', spawn: config.daemonize, dir: cwd) {
esEnv.each { key, value -> env(key: key, value: value) }
(['/C', 'call', esScript] + esProps).each { arg(value: it) }
}
esPostStartActions(ant, logger)
}
} else {
List esExecutable = [esScript]
if(config.daemonize) {
esExecutable.add("-d")
}
return project.tasks.create(name: name, type: Exec, dependsOn: setup) {
workingDir cwd
executable 'sh'
args esExecutable
args esProps
environment esEnv
doLast {
esPostStartActions(ant, logger)
}
}
}
} }
/** Adds a task to check if the process with the given pidfile is actually elasticsearch */ /** Adds a task to check if the process with the given pidfile is actually elasticsearch */
@ -347,4 +351,16 @@ class ClusterFormationTasks {
static File pidFile(File dir) { static File pidFile(File dir) {
return new File(dir, 'es.pid') return new File(dir, 'es.pid')
} }
/** Runs an ant command, sending output to the given out and error streams */
static void runAntCommand(Project project, Closure command, PrintStream outputStream, PrintStream errorStream) {
DefaultLogger listener = new DefaultLogger(
errorPrintStream: errorStream,
outputPrintStream: outputStream,
messageOutputLevel: org.apache.tools.ant.Project.MSG_INFO)
project.ant.project.addBuildListener(listener)
project.configure(project.ant, command)
project.ant.project.removeBuildListener(listener)
}
} }