Skip to content

Commit ddf1252

Browse files
committed
Merge pull request #15098 from rjernst/integ_test_output
Improve output when integ test fails
2 parents fe20677 + d37930d commit ddf1252

File tree

2 files changed

+77
-45
lines changed

2 files changed

+77
-45
lines changed

buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -315,49 +315,27 @@ class ClusterFormationTasks {
315315

316316
/** Adds a task to start an elasticsearch node with the given configuration */
317317
static Task configureStartTask(String name, Project project, Task setup, NodeInfo node) {
318-
String executable
319-
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
320-
executable = 'cmd'
321-
} else {
322-
executable = 'sh'
323-
}
324318

325319
// this closure is converted into ant nodes by groovy's AntBuilder
326320
Closure antRunner = { AntBuilder ant ->
321+
ant.exec(executable: node.executable, spawn: node.config.daemonize, dir: node.cwd, taskname: 'elasticsearch') {
322+
node.env.each { key, value -> env(key: key, value: value) }
323+
node.args.each { arg(value: it) }
324+
}
325+
}
326+
327+
// this closure is the actual code to run elasticsearch
328+
Closure elasticsearchRunner = {
327329
// Due to how ant exec works with the spawn option, we lose all stdout/stderr from the
328330
// process executed. To work around this, when spawning, we wrap the elasticsearch start
329331
// command inside another shell script, which simply internally redirects the output
330332
// of the real elasticsearch script. This allows ant to keep the streams open with the
331333
// dummy process, but us to have the output available if there is an error in the
332334
// elasticsearch start script
333-
String script = node.esScript
334335
if (node.config.daemonize) {
335-
String scriptName = 'run'
336-
String argsPasser = '"$@"'
337-
String exitMarker = "; if [ \$? != 0 ]; then touch run.failed; fi"
338-
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
339-
scriptName += '.bat'
340-
argsPasser = '%*'
341-
exitMarker = "\r\n if \"%errorlevel%\" neq \"0\" ( type nul >> run.failed )"
342-
}
343-
File wrapperScript = new File(node.cwd, scriptName)
344-
wrapperScript.setText("\"${script}\" ${argsPasser} > run.log 2>&1 ${exitMarker}", 'UTF-8')
345-
script = wrapperScript.toString()
336+
node.writeWrapperScript()
346337
}
347338

348-
ant.exec(executable: executable, spawn: node.config.daemonize, dir: node.cwd, taskname: 'elasticsearch') {
349-
node.env.each { key, value -> env(key: key, value: value) }
350-
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
351-
arg(value: '/C')
352-
}
353-
arg(value: script)
354-
node.args.each { arg(value: it) }
355-
}
356-
357-
}
358-
359-
// this closure is the actual code to run elasticsearch
360-
Closure elasticsearchRunner = {
361339
// we must add debug options inside the closure so the config is read at execution time, as
362340
// gradle task options are not processed until the end of the configuration phase
363341
if (node.config.debug) {
@@ -436,14 +414,19 @@ class ClusterFormationTasks {
436414
// We already log the command at info level. No need to do it twice.
437415
node.getCommandString().eachLine { line -> logger.error(line) }
438416
}
439-
// the waitfor failed, so dump any output we got (may be empty if info logging, but that is ok)
440-
logger.error("Node ${node.nodeNum} ant output:")
441-
node.buffer.toString('UTF-8').eachLine { line -> logger.error(line) }
417+
logger.error("Node ${node.nodeNum} output:")
418+
logger.error("|-----------------------------------------")
419+
logger.error("| failure marker exists: ${node.failedMarker.exists()}")
420+
logger.error("| pid file exists: ${node.pidFile.exists()}")
421+
// the waitfor failed, so dump any output we got (if info logging this goes directly to stdout)
422+
logger.error("|\n| [ant output]")
423+
node.buffer.toString('UTF-8').eachLine { line -> logger.error("| ${line}") }
442424
// also dump the log file for the startup script (which will include ES logging output to stdout)
443425
if (node.startLog.exists()) {
444-
logger.error("Node ${node.nodeNum} log:")
445-
node.startLog.eachLine { line -> logger.error(line) }
426+
logger.error("|\n| [log]")
427+
node.startLog.eachLine { line -> logger.error("| ${line}") }
446428
}
429+
logger.error("|-----------------------------------------")
447430
}
448431
throw new GradleException(msg)
449432
}

buildSrc/src/main/groovy/org/elasticsearch/gradle/test/NodeInfo.groovy

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.elasticsearch.gradle.test
2020

21+
import org.apache.tools.ant.taskdefs.condition.Os
2122
import org.elasticsearch.gradle.VersionProperties
2223
import org.gradle.api.InvalidUserDataException
2324
import org.gradle.api.Project
@@ -48,6 +49,9 @@ class NodeInfo {
4849
/** config directory */
4950
File confDir
5051

52+
/** THE config file */
53+
File configFile
54+
5155
/** working directory for the node process */
5256
File cwd
5357

@@ -66,8 +70,14 @@ class NodeInfo {
6670
/** arguments to start the node with */
6771
List<String> args
6872

73+
/** Executable to run the bin/elasticsearch with, either cmd or sh */
74+
String executable
75+
6976
/** Path to the elasticsearch start script */
70-
String esScript
77+
File esScript
78+
79+
/** script to run when running in the background */
80+
File wrapperScript
7181

7282
/** buffer for ant output when starting this node */
7383
ByteArrayOutputStream buffer = new ByteArrayOutputStream()
@@ -81,35 +91,74 @@ class NodeInfo {
8191
pidFile = new File(baseDir, 'es.pid')
8292
homeDir = homeDir(baseDir, config.distribution)
8393
confDir = confDir(baseDir, config.distribution)
94+
configFile = new File(confDir, 'elasticsearch.yml')
8495
cwd = new File(baseDir, "cwd")
8596
failedMarker = new File(cwd, 'run.failed')
8697
startLog = new File(cwd, 'run.log')
8798
pluginsTmpDir = new File(baseDir, "plugins tmp")
8899

100+
args = []
101+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
102+
executable = 'cmd'
103+
args.add('/C')
104+
args.add('"') // quote the entire command
105+
wrapperScript = new File(cwd, "run.bat")
106+
esScript = new File(homeDir, 'bin/elasticsearch.bat')
107+
} else {
108+
executable = 'sh'
109+
wrapperScript = new File(cwd, "run")
110+
esScript = new File(homeDir, 'bin/elasticsearch')
111+
}
112+
if (config.daemonize) {
113+
args.add("${wrapperScript}")
114+
} else {
115+
args.add("${esScript}")
116+
}
117+
89118
env = [
90119
'JAVA_HOME' : project.javaHome,
91120
'ES_GC_OPTS': config.jvmArgs // we pass these with the undocumented gc opts so the argline can set gc, etc
92121
]
93-
args = config.systemProperties.collect { key, value -> "-D${key}=${value}" }
122+
args.addAll(config.systemProperties.collect { key, value -> "-D${key}=${value}" })
94123
for (Map.Entry<String, String> property : System.properties.entrySet()) {
95124
if (property.getKey().startsWith('es.')) {
96125
args.add("-D${property.getKey()}=${property.getValue()}")
97126
}
98127
}
99-
args.add("-Des.default.path.conf=${confDir}")
100-
// running with cmd on windows will look for this with the .bat extension
101-
esScript = new File(homeDir, 'bin/elasticsearch').toString()
128+
args.add("-Des.path.conf=${confDir}")
129+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
130+
args.add('"') // end the entire command, quoted
131+
}
102132
}
103133

104134
/** Returns debug string for the command that started this node. */
105135
String getCommandString() {
106-
String esCommandString = "Elasticsearch node ${nodeNum} command: ${esScript} "
107-
esCommandString += args.join(' ')
108-
esCommandString += '\nenvironment:'
109-
env.each { k, v -> esCommandString += "\n ${k}: ${v}" }
136+
String esCommandString = "\nNode ${nodeNum} configuration:\n"
137+
esCommandString += "|-----------------------------------------\n"
138+
esCommandString += "| cwd: ${cwd}\n"
139+
esCommandString += "| command: ${executable} ${args.join(' ')}\n"
140+
esCommandString += '| environment:\n'
141+
env.each { k, v -> esCommandString += "| ${k}: ${v}\n" }
142+
if (config.daemonize) {
143+
esCommandString += "|\n| [${wrapperScript.name}]\n"
144+
wrapperScript.eachLine('UTF-8', { line -> esCommandString += " ${line}\n"})
145+
}
146+
esCommandString += '|\n| [elasticsearch.yml]\n'
147+
configFile.eachLine('UTF-8', { line -> esCommandString += "| ${line}\n" })
148+
esCommandString += "|-----------------------------------------"
110149
return esCommandString
111150
}
112151

152+
void writeWrapperScript() {
153+
String argsPasser = '"$@"'
154+
String exitMarker = "; if [ \$? != 0 ]; then touch run.failed; fi"
155+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
156+
argsPasser = '%*'
157+
exitMarker = "\r\n if \"%errorlevel%\" neq \"0\" ( type nul >> run.failed )"
158+
}
159+
wrapperScript.setText("\"${esScript}\" ${argsPasser} > run.log 2>&1 ${exitMarker}", 'UTF-8')
160+
}
161+
113162
/** Returns the http port for this node */
114163
int httpPort() {
115164
return config.baseHttpPort + nodeNum

0 commit comments

Comments
 (0)