From 15fc185e562daaa2152bd7c78655b02874033689 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Wed, 24 Oct 2018 17:18:52 +0200 Subject: [PATCH 1/5] TESTS: Use File Based Discovery in REST Tests (#34560) * For `6.5+` use file based discovery in REST tests * Relates #33675 --- .../gradle/test/ClusterConfiguration.groovy | 4 +- .../gradle/test/ClusterFormationTasks.groovy | 51 +++++++++++++++---- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy index b29bb7a8cd3b7..d2eb6cc60a576 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy @@ -68,7 +68,9 @@ class ClusterConfiguration { * In case of more than one node, this defaults to the number of nodes */ @Input - Closure minimumMasterNodes = { getNumNodes() > 1 ? getNumNodes() : -1 } + Closure minimumMasterNodes = { + return getNumNodes() > 1 ? getNumNodes() : -1 + } @Input String jvmArgs = "-Xms" + System.getProperty('tests.heap.size', '512m') + diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 52ed30880d374..61cc050da95ed 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -122,8 +122,31 @@ class ClusterFormationTasks { } NodeInfo node = new NodeInfo(config, i, project, prefix, elasticsearchVersion, sharedDir) nodes.add(node) - Object dependsOn = startTasks.empty ? startDependencies : startTasks.get(0) - startTasks.add(configureNode(project, prefix, runner, dependsOn, node, config, distro, nodes.get(0))) + Closure writeConfigSetup + Object dependsOn + if (node.nodeVersion.onOrAfter("6.5.0-SNAPSHOT")) { + writeConfigSetup = { Map esConfig -> + // Don't force discovery provider if one is set by the test cluster specs already + if (esConfig.containsKey('discovery.zen.hosts_provider') == false) { + esConfig['discovery.zen.hosts_provider'] = 'file' + } + esConfig['discovery.zen.ping.unicast.hosts'] = [] + esConfig + } + dependsOn = startDependencies + } else { + dependsOn = startTasks.empty ? startDependencies : startTasks.get(0) + writeConfigSetup = { Map esConfig -> + String unicastTransportUri = node.config.unicastTransportUri(nodes.get(0), node, project.ant) + if (unicastTransportUri == null) { + esConfig['discovery.zen.ping.unicast.hosts'] = [] + } else { + esConfig['discovery.zen.ping.unicast.hosts'] = "\"${unicastTransportUri}\"" + } + esConfig + } + } + startTasks.add(configureNode(project, prefix, runner, dependsOn, node, config, distro, writeConfigSetup)) } Task wait = configureWaitTask("${prefix}#wait", project, nodes, startTasks, config.nodeStartupWaitSeconds) @@ -184,7 +207,7 @@ class ClusterFormationTasks { * @return a task which starts the node. */ static Task configureNode(Project project, String prefix, Task runner, Object dependsOn, NodeInfo node, ClusterConfiguration config, - Configuration distribution, NodeInfo seedNode) { + Configuration distribution, Closure writeConfig) { // tasks are chained so their execution order is maintained Task setup = project.tasks.create(name: taskName(prefix, node, 'clean'), type: Delete, dependsOn: dependsOn) { @@ -200,7 +223,7 @@ class ClusterFormationTasks { setup = configureCheckPreviousTask(taskName(prefix, node, 'checkPrevious'), project, setup, node) setup = configureStopTask(taskName(prefix, node, 'stopPrevious'), project, setup, node) setup = configureExtractTask(taskName(prefix, node, 'extract'), project, setup, node, distribution) - setup = configureWriteConfigTask(taskName(prefix, node, 'configure'), project, setup, node, seedNode) + setup = configureWriteConfigTask(taskName(prefix, node, 'configure'), project, setup, node, writeConfig) setup = configureCreateKeystoreTask(taskName(prefix, node, 'createKeystore'), project, setup, node) setup = configureAddKeystoreSettingTasks(prefix, project, setup, node) setup = configureAddKeystoreFileTasks(prefix, project, setup, node) @@ -303,7 +326,7 @@ class ClusterFormationTasks { } /** Adds a task to write elasticsearch.yml for the given node configuration */ - static Task configureWriteConfigTask(String name, Project project, Task setup, NodeInfo node, NodeInfo seedNode) { + static Task configureWriteConfigTask(String name, Project project, Task setup, NodeInfo node, Closure configFilter) { Map esConfig = [ 'cluster.name' : node.clusterName, 'node.name' : "node-" + node.nodeNum, @@ -347,10 +370,7 @@ class ClusterFormationTasks { Task writeConfig = project.tasks.create(name: name, type: DefaultTask, dependsOn: setup) writeConfig.doFirst { - String unicastTransportUri = node.config.unicastTransportUri(seedNode, node, project.ant) - if (unicastTransportUri != null) { - esConfig['discovery.zen.ping.unicast.hosts'] = "\"${unicastTransportUri}\"" - } + esConfig = configFilter.call(esConfig) File configFile = new File(node.pathConf, 'elasticsearch.yml') logger.info("Configuring ${configFile}") configFile.setText(esConfig.collect { key, value -> "${key}: ${value}" }.join('\n'), 'UTF-8') @@ -681,6 +701,19 @@ class ClusterFormationTasks { static Task configureWaitTask(String name, Project project, List nodes, List startTasks, int waitSeconds) { Task wait = project.tasks.create(name: name, dependsOn: startTasks) wait.doLast { + + Collection unicastHosts = new HashSet<>() + nodes.forEach { otherNode -> + String unicastHost = otherNode.config.unicastTransportUri(otherNode, null, project.ant) + if (unicastHost != null) { + unicastHosts.addAll(Arrays.asList(unicastHost.split(","))) + } + } + String unicastHostsTxt = String.join("\n", unicastHosts) + nodes.forEach { node -> + node.pathConf.toPath().resolve("unicast_hosts.txt").setText(unicastHostsTxt) + } + ant.waitfor(maxwait: "${waitSeconds}", maxwaitunit: 'second', checkevery: '500', checkeveryunit: 'millisecond', timeoutproperty: "failed${name}") { or { for (NodeInfo node : nodes) { From 41d065e591c8a9dc5334fd04cdfa30c86aa61a88 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Fri, 9 Nov 2018 10:47:30 +0100 Subject: [PATCH 2/5] DISCOVERY: Fix RollingUpgradeTests (#35375) * DISCOVERY: Fix RollingUpgradeTests * Don't manually manage min master nodes if not necessary * Remove some dead code * Allow for manually supplying list of seed nodes * Closes #35178 --- .../gradle/test/ClusterConfiguration.groovy | 8 ++++++++ .../gradle/test/ClusterFormationTasks.groovy | 5 +++-- qa/rolling-upgrade/build.gradle | 13 ++++++------- x-pack/qa/rolling-upgrade/build.gradle | 14 ++++++-------- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy index d2eb6cc60a576..305d295067e0e 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy @@ -106,6 +106,14 @@ class ClusterConfiguration { return seedNode.transportUri() } + /** + * A closure to call which returns a manually supplied list of unicast seed hosts. + */ + @Input + Closure> otherUnicastHostAddresses = { + Collections.emptyList() + } + /** * A closure to call before the cluster is considered ready. The closure is passed the node info, * as well as a groovy AntBuilder, to enable running ant condition checks. The default wait diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 61cc050da95ed..8ffa259050d75 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -703,8 +703,9 @@ class ClusterFormationTasks { wait.doLast { Collection unicastHosts = new HashSet<>() - nodes.forEach { otherNode -> - String unicastHost = otherNode.config.unicastTransportUri(otherNode, null, project.ant) + nodes.forEach { node -> + unicastHosts.addAll(node.config.otherUnicastHostAddresses.call()) + String unicastHost = node.config.unicastTransportUri(node, null, project.ant) if (unicastHost != null) { unicastHosts.addAll(Arrays.asList(unicastHost.split(","))) } diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index be8269ae941da..42c3c115d2f36 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -56,7 +56,6 @@ for (Version version : bwcVersions.wireCompatible) { mustRunAfter(precommit) } - Object extension = extensions.findByName("${baseName}#oldClusterTestCluster") configure(extensions.findByName("${baseName}#oldClusterTestCluster")) { bwcVersion = version numBwcNodes = 3 @@ -76,12 +75,12 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.upgrade_from_version', version.toString().replace('-SNAPSHOT', '') } - Closure configureUpgradeCluster = {String name, Task lastRunner, int stopNode, Closure unicastSeed -> + Closure configureUpgradeCluster = {String name, Task lastRunner, int stopNode, Closure getOtherUnicastHostAddresses -> configure(extensions.findByName("${baseName}#${name}")) { dependsOn lastRunner, "${baseName}#oldClusterTestCluster#node${stopNode}.stop" clusterName = 'rolling-upgrade' - unicastTransportUri = { seedNode, node, ant -> unicastSeed() } - minimumMasterNodes = { 3 } + otherUnicastHostAddresses = { getOtherUnicastHostAddresses() } + minimumMasterNodes = { 2 } /* Override the data directory so the new node always gets the node we * just stopped's data directory. */ dataDir = { nodeNumber -> oldClusterTest.nodes[stopNode].dataDir } @@ -95,7 +94,7 @@ for (Version version : bwcVersions.wireCompatible) { configureUpgradeCluster("oneThirdUpgradedTestCluster", oldClusterTestRunner, 0, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oldClusterTest.nodes.get(1).transportUri() + ',' + oldClusterTest.nodes.get(2).transportUri() }) + { [oldClusterTest.nodes.get(1).transportUri(), oldClusterTest.nodes.get(2).transportUri()] }) Task oneThirdUpgradedTestRunner = tasks.getByName("${baseName}#oneThirdUpgradedTestRunner") oneThirdUpgradedTestRunner.configure { @@ -109,7 +108,7 @@ for (Version version : bwcVersions.wireCompatible) { configureUpgradeCluster("twoThirdsUpgradedTestCluster", oneThirdUpgradedTestRunner, 1, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oldClusterTest.nodes.get(2).transportUri() + ',' + oneThirdUpgradedTest.nodes.get(0).transportUri() }) + { [oldClusterTest.nodes.get(2).transportUri(), oneThirdUpgradedTest.nodes.get(0).transportUri()] }) Task twoThirdsUpgradedTestRunner = tasks.getByName("${baseName}#twoThirdsUpgradedTestRunner") twoThirdsUpgradedTestRunner.configure { @@ -123,7 +122,7 @@ for (Version version : bwcVersions.wireCompatible) { configureUpgradeCluster("upgradedClusterTestCluster", twoThirdsUpgradedTestRunner, 2, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oneThirdUpgradedTest.nodes.get(0).transportUri() + ',' + twoThirdsUpgradedTest.nodes.get(0).transportUri() }) + { [oneThirdUpgradedTest.nodes.get(0).transportUri(), twoThirdsUpgradedTest.nodes.get(0).transportUri()] }) Task upgradedClusterTestRunner = tasks.getByName("${baseName}#upgradedClusterTestRunner") upgradedClusterTestRunner.configure { diff --git a/x-pack/qa/rolling-upgrade/build.gradle b/x-pack/qa/rolling-upgrade/build.gradle index 6e482b29415e8..f07aa7d7a7a8b 100644 --- a/x-pack/qa/rolling-upgrade/build.gradle +++ b/x-pack/qa/rolling-upgrade/build.gradle @@ -116,7 +116,6 @@ subprojects { mustRunAfter(precommit) } - Object extension = extensions.findByName("${baseName}#oldClusterTestCluster") configure(extensions.findByName("${baseName}#oldClusterTestCluster")) { dependsOn copyTestNodeKeystore if (version.before('6.3.0')) { @@ -131,7 +130,6 @@ subprojects { bwcVersion = version numBwcNodes = 3 numNodes = 3 - minimumMasterNodes = { 3 } clusterName = 'rolling-upgrade' waitCondition = waitWithAuth setting 'xpack.monitoring.exporters._http.type', 'http' @@ -184,13 +182,13 @@ subprojects { systemProperty 'tests.upgrade_from_version', version.toString().replace('-SNAPSHOT', '') } - Closure configureUpgradeCluster = {String name, Task lastRunner, int stopNode, Closure unicastSeed -> + Closure configureUpgradeCluster = {String name, Task lastRunner, int stopNode, Closure getOtherUnicastHostAddresses -> configure(extensions.findByName("${baseName}#${name}")) { dependsOn lastRunner, "${baseName}#oldClusterTestCluster#node${stopNode}.stop" setupCommand 'setupTestUser', 'bin/elasticsearch-users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' clusterName = 'rolling-upgrade' - unicastTransportUri = { seedNode, node, ant -> unicastSeed() } - minimumMasterNodes = { 3 } + otherUnicastHostAddresses = { getOtherUnicastHostAddresses() } + minimumMasterNodes = { 2 } /* Override the data directory so the new node always gets the node we * just stopped's data directory. */ dataDir = { nodeNumber -> oldClusterTest.nodes[stopNode].dataDir } @@ -226,7 +224,7 @@ subprojects { configureUpgradeCluster("oneThirdUpgradedTestCluster", oldClusterTestRunner, 0, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oldClusterTest.nodes.get(1).transportUri() + ',' + oldClusterTest.nodes.get(2).transportUri() }) + { [oldClusterTest.nodes.get(1).transportUri(), oldClusterTest.nodes.get(2).transportUri()] }) Task oneThirdUpgradedTestRunner = tasks.getByName("${baseName}#oneThirdUpgradedTestRunner") oneThirdUpgradedTestRunner.configure { @@ -246,7 +244,7 @@ subprojects { configureUpgradeCluster("twoThirdsUpgradedTestCluster", oneThirdUpgradedTestRunner, 1, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oldClusterTest.nodes.get(2).transportUri() + ',' + oneThirdUpgradedTest.nodes.get(0).transportUri() }) + { [oldClusterTest.nodes.get(2).transportUri(), oneThirdUpgradedTest.nodes.get(0).transportUri()] }) Task twoThirdsUpgradedTestRunner = tasks.getByName("${baseName}#twoThirdsUpgradedTestRunner") twoThirdsUpgradedTestRunner.configure { @@ -260,7 +258,7 @@ subprojects { configureUpgradeCluster("upgradedClusterTestCluster", twoThirdsUpgradedTestRunner, 2, // Use all running nodes as seed nodes so there is no race between pinging and the tests - { oneThirdUpgradedTest.nodes.get(0).transportUri() + ',' + twoThirdsUpgradedTest.nodes.get(0).transportUri() }) + { [oneThirdUpgradedTest.nodes.get(0).transportUri(), twoThirdsUpgradedTest.nodes.get(0).transportUri()] }) Task upgradedClusterTestRunner = tasks.getByName("${baseName}#upgradedClusterTestRunner") upgradedClusterTestRunner.configure { From ae6bf3683af47625070e8fc9a5a355e9c362aec2 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Tue, 13 Nov 2018 14:19:05 +0200 Subject: [PATCH 3/5] DISCOVERY: 0s Initial State Timeout in Tests (#35481) * DISCOVERY: 0s Initial State Timeout in Tests * Don't wait for initial state even with a single node, otherwise the loop writing the discovery file causes that single node to wait for its own transport.ports file for 30s. * Closes #35456 --- .../org/elasticsearch/gradle/test/ClusterFormationTasks.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 8ffa259050d75..25923c8430434 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -340,7 +340,7 @@ class ClusterFormationTasks { if (minimumMasterNodes > 0) { esConfig['discovery.zen.minimum_master_nodes'] = minimumMasterNodes } - if (node.config.numNodes > 1) { + if (minimumMasterNodes > 1) { // don't wait for state.. just start up quickly // this will also allow new and old nodes in the BWC case to become the master esConfig['discovery.initial_state_timeout'] = '0s' From fddd774985523ad5c2a5feb51b12963281b5ccad Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Thu, 15 Nov 2018 14:23:28 +0100 Subject: [PATCH 4/5] REST-Tests: Use Dedicated AntBuilders (#35576) * REST-Tests: Use Dedicated AntBuilders * Use dedicated AntBuilder everywhere since AntBuilder is not threadsafe * Closes #33778 --- .../gradle/test/ClusterFormationTasks.groovy | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 25923c8430434..9a59043cd944e 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -137,7 +137,7 @@ class ClusterFormationTasks { } else { dependsOn = startTasks.empty ? startDependencies : startTasks.get(0) writeConfigSetup = { Map esConfig -> - String unicastTransportUri = node.config.unicastTransportUri(nodes.get(0), node, project.ant) + String unicastTransportUri = node.config.unicastTransportUri(nodes.get(0), node, project.createAntBuilder()) if (unicastTransportUri == null) { esConfig['discovery.zen.ping.unicast.hosts'] = [] } else { @@ -705,7 +705,7 @@ class ClusterFormationTasks { Collection unicastHosts = new HashSet<>() nodes.forEach { node -> unicastHosts.addAll(node.config.otherUnicastHostAddresses.call()) - String unicastHost = node.config.unicastTransportUri(node, null, project.ant) + String unicastHost = node.config.unicastTransportUri(node, null, project.createAntBuilder()) if (unicastHost != null) { unicastHosts.addAll(Arrays.asList(unicastHost.split(","))) } @@ -901,9 +901,10 @@ class ClusterFormationTasks { outputPrintStream: outputStream, messageOutputLevel: org.apache.tools.ant.Project.MSG_INFO) - project.ant.project.addBuildListener(listener) - Object retVal = command(project.ant) - project.ant.project.removeBuildListener(listener) + AntBuilder ant = project.createAntBuilder() + ant.project.addBuildListener(listener) + Object retVal = command(ant) + ant.project.removeBuildListener(listener) return retVal } From 192d5d93ae8216ffd1d7e627cd9e6a2dd791eae0 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Thu, 15 Nov 2018 14:24:04 +0100 Subject: [PATCH 5/5] MINOR: Remove SNAPSHOT Suffixes in Gradle (#35577) * MINOR: Remove SNAPSHOT Suffixes in Gradle * The snapshot qualifiers here are redundant and 6.5.0 is released anyway --- .../elasticsearch/gradle/test/ClusterConfiguration.groovy | 6 +++++- .../elasticsearch/gradle/test/ClusterFormationTasks.groovy | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy index 305d295067e0e..399c4838d2b14 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy @@ -69,7 +69,11 @@ class ClusterConfiguration { */ @Input Closure minimumMasterNodes = { - return getNumNodes() > 1 ? getNumNodes() : -1 + if (bwcVersion != null && bwcVersion.before("6.5.0")) { + return numNodes > 1 ? numNodes : -1 + } else { + return numNodes > 1 ? numNodes.intdiv(2) + 1 : -1 + } } @Input diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 9a59043cd944e..6bc37d63b37b4 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -124,7 +124,7 @@ class ClusterFormationTasks { nodes.add(node) Closure writeConfigSetup Object dependsOn - if (node.nodeVersion.onOrAfter("6.5.0-SNAPSHOT")) { + if (node.nodeVersion.onOrAfter("6.5.0")) { writeConfigSetup = { Map esConfig -> // Don't force discovery provider if one is set by the test cluster specs already if (esConfig.containsKey('discovery.zen.hosts_provider') == false) {