diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexingIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexingIT.java
index f1e01d24acff6..3898746e5c374 100644
--- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexingIT.java
+++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexingIT.java
@@ -30,6 +30,10 @@
* Basic test that indexed documents survive the rolling restart. See
* {@link RecoveryIT} for much more in depth testing of the mechanism
* by which they survive.
+ *
+ * This test is an almost exact copy of IndexingIT
in the
+ * xpack rolling restart tests. We should work on a way to remove this
+ * duplication but for now we have no real way to share code.
*/
public class IndexingIT extends AbstractRollingTestCase {
public void testIndexing() throws IOException {
diff --git a/x-pack/qa/rolling-upgrade/build.gradle b/x-pack/qa/rolling-upgrade/build.gradle
index 1a53654b38233..13b18b727f23d 100644
--- a/x-pack/qa/rolling-upgrade/build.gradle
+++ b/x-pack/qa/rolling-upgrade/build.gradle
@@ -32,7 +32,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant ->
HttpURLConnection httpURLConnection = null;
try {
// TODO this sucks having to hardcode number of nodes, but node.config.numNodes isn't necessarily accurate for rolling
- httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=2&wait_for_status=yellow").openConnection();
+ httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=3&wait_for_status=yellow").openConnection();
httpURLConnection.setRequestProperty("Authorization", "Basic " +
Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)));
httpURLConnection.setRequestMethod("GET");
@@ -124,9 +124,9 @@ subprojects {
String usersCli = version.before('6.3.0') ? 'bin/x-pack/users' : 'bin/elasticsearch-users'
setupCommand 'setupTestUser', usersCli, 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser'
bwcVersion = version
- numBwcNodes = 2
- numNodes = 2
- minimumMasterNodes = { 2 }
+ numBwcNodes = 3
+ numNodes = 3
+ minimumMasterNodes = { 3 }
clusterName = 'rolling-upgrade'
waitCondition = waitWithAuth
setting 'xpack.monitoring.exporters._http.type', 'http'
@@ -179,87 +179,88 @@ subprojects {
systemProperty 'tests.rest.suite', 'old_cluster'
}
- Task mixedClusterTest = tasks.create(name: "${baseName}#mixedClusterTest", type: RestIntegTestTask)
-
- configure(extensions.findByName("${baseName}#mixedClusterTestCluster")) {
- dependsOn oldClusterTestRunner, "${baseName}#oldClusterTestCluster#node1.stop"
- setupCommand 'setupTestUser', 'bin/elasticsearch-users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser'
- clusterName = 'rolling-upgrade'
- unicastTransportUri = { seedNode, node, ant -> oldClusterTest.nodes.get(0).transportUri() }
- minimumMasterNodes = { 2 }
- dataDir = { nodeNumber -> oldClusterTest.nodes[1].dataDir }
- waitCondition = waitWithAuth
- setting 'xpack.monitoring.exporters._http.type', 'http'
- setting 'xpack.monitoring.exporters._http.enabled', 'false'
- setting 'xpack.monitoring.exporters._http.auth.username', 'test_user'
- setting 'xpack.monitoring.exporters._http.auth.password', 'x-pack-test-password'
- setting 'xpack.license.self_generated.type', 'trial'
- setting 'xpack.security.enabled', 'true'
- setting 'xpack.security.transport.ssl.enabled', 'true'
- setting 'xpack.ssl.keystore.path', 'testnode.jks'
- keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode'
- if (version.onOrAfter('6.0.0') == false) {
- // this is needed since in 5.6 we don't bootstrap the token service if there is no explicit initial password
- keystoreSetting 'xpack.security.authc.token.passphrase', 'xpack_token_passphrase'
- }
- setting 'node.attr.upgraded', 'first'
- setting 'xpack.security.authc.token.enabled', 'true'
- setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
- setting 'xpack.security.audit.enabled', 'true'
- setting 'xpack.security.audit.outputs', 'index'
- setting 'node.name', 'mixed-node-0'
- dependsOn copyTestNodeKeystore
- extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks')
- if (withSystemKey) {
- setting 'xpack.watcher.encrypt_sensitive_data', 'true'
- keystoreFile 'xpack.watcher.encryption_key', "${mainProject.projectDir}/src/test/resources/system_key"
+ Closure configureUpgradeCluster = {String name, Task lastRunner, int stopNode, Closure unicastSeed ->
+ 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 }
+ /* Override the data directory so the new node always gets the node we
+ * just stopped's data directory. */
+ dataDir = { nodeNumber -> oldClusterTest.nodes[stopNode].dataDir }
+ waitCondition = waitWithAuth
+ setting 'xpack.monitoring.exporters._http.type', 'http'
+ setting 'xpack.monitoring.exporters._http.enabled', 'false'
+ setting 'xpack.monitoring.exporters._http.auth.username', 'test_user'
+ setting 'xpack.monitoring.exporters._http.auth.password', 'x-pack-test-password'
+ setting 'xpack.license.self_generated.type', 'trial'
+ setting 'xpack.security.enabled', 'true'
+ setting 'xpack.security.transport.ssl.enabled', 'true'
+ setting 'xpack.ssl.keystore.path', 'testnode.jks'
+ keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode'
+ if (version.onOrAfter('6.0.0') == false) {
+ // this is needed since in 5.6 we don't bootstrap the token service if there is no explicit initial password
+ keystoreSetting 'xpack.security.authc.token.passphrase', 'xpack_token_passphrase'
+ }
+ setting 'node.attr.upgraded', 'true'
+ setting 'xpack.security.authc.token.enabled', 'true'
+ setting 'xpack.security.audit.enabled', 'true'
+ setting 'xpack.security.audit.outputs', 'index'
+ setting 'node.name', "upgraded-node-${stopNode}"
+ dependsOn copyTestNodeKeystore
+ extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks')
+ if (withSystemKey) {
+ setting 'xpack.watcher.encrypt_sensitive_data', 'true'
+ keystoreFile 'xpack.watcher.encryption_key', "${mainProject.projectDir}/src/test/resources/system_key"
+ }
}
}
- Task mixedClusterTestRunner = tasks.getByName("${baseName}#mixedClusterTestRunner")
- mixedClusterTestRunner.configure {
+ Task oneThirdUpgradedTest = tasks.create(name: "${baseName}#oneThirdUpgradedTest", type: RestIntegTestTask)
+
+ configureUpgradeCluster("oneThirdUpgradedTestCluster", oldClusterTestRunner,
+ 0, { oldClusterTest.nodes.get(1).transportUri() })
+
+ Task oneThirdUpgradedTestRunner = tasks.getByName("${baseName}#oneThirdUpgradedTestRunner")
+ oneThirdUpgradedTestRunner.configure {
systemProperty 'tests.rest.suite', 'mixed_cluster'
- finalizedBy "${baseName}#oldClusterTestCluster#node0.stop"
+ systemProperty 'tests.first_round', 'true'
+ // We only need to run these tests once so we may as well do it when we're two thirds upgraded
+ systemProperty 'tests.rest.blacklist', [
+ 'mixed_cluster/10_basic/Start scroll in mixed cluster on upgraded node that we will continue after upgrade',
+ 'mixed_cluster/30_ml_jobs_crud/Create a job in the mixed cluster and write some data',
+ 'mixed_cluster/40_ml_datafeed_crud/Put job and datafeed in mixed cluster',
+ ].join(',')
+ finalizedBy "${baseName}#oldClusterTestCluster#node1.stop"
}
- Task upgradedClusterTest = tasks.create(name: "${baseName}#upgradedClusterTest", type: RestIntegTestTask)
+ Task twoThirdsUpgradedTest = tasks.create(name: "${baseName}#twoThirdsUpgradedTest", type: RestIntegTestTask)
- configure(extensions.findByName("${baseName}#upgradedClusterTestCluster")) {
- dependsOn(mixedClusterTestRunner, "${baseName}#oldClusterTestCluster#node0.stop")
- setupCommand 'setupTestUser', 'bin/elasticsearch-users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser'
- clusterName = 'rolling-upgrade'
- unicastTransportUri = { seedNode, node, ant -> mixedClusterTest.nodes.get(0).transportUri() }
- minimumMasterNodes = { 2 }
- dataDir = { nodeNumber -> oldClusterTest.nodes[0].dataDir }
- waitCondition = waitWithAuth
- setting 'xpack.monitoring.exporters._http.type', 'http'
- setting 'xpack.monitoring.exporters._http.enabled', 'false'
- setting 'xpack.monitoring.exporters._http.auth.username', 'test_user'
- setting 'xpack.monitoring.exporters._http.auth.password', 'x-pack-test-password'
- setting 'xpack.license.self_generated.type', 'trial'
- setting 'xpack.security.enabled', 'true'
- setting 'xpack.security.transport.ssl.enabled', 'true'
- setting 'xpack.ssl.keystore.path', 'testnode.jks'
- keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode'
- if (version.onOrAfter('6.0.0') == false) {
- // this is needed since in 5.6 we don't bootstrap the token service if there is no explicit initial password
- keystoreSetting 'xpack.security.authc.token.passphrase', 'xpack_token_passphrase'
- }
- setting 'xpack.security.authc.token.enabled', 'true'
- setting 'xpack.security.audit.enabled', 'true'
- setting 'xpack.security.audit.outputs', 'index'
- setting 'node.name', 'upgraded-node-0'
- dependsOn copyTestNodeKeystore
- extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks')
- if (withSystemKey) {
- setting 'xpack.watcher.encrypt_sensitive_data', 'true'
- keystoreFile 'xpack.watcher.encryption_key', "${mainProject.projectDir}/src/test/resources/system_key"
- }
+ configureUpgradeCluster("twoThirdsUpgradedTestCluster", oneThirdUpgradedTestRunner,
+ 1, { oneThirdUpgradedTest.nodes.get(0).transportUri() })
+
+ Task twoThirdsUpgradedTestRunner = tasks.getByName("${baseName}#twoThirdsUpgradedTestRunner")
+ twoThirdsUpgradedTestRunner.configure {
+ systemProperty 'tests.rest.suite', 'mixed_cluster'
+ systemProperty 'tests.first_round', 'false'
+ finalizedBy "${baseName}#oldClusterTestCluster#node2.stop"
}
+ Task upgradedClusterTest = tasks.create(name: "${baseName}#upgradedClusterTest", type: RestIntegTestTask)
+
+ configureUpgradeCluster("upgradedClusterTestCluster", twoThirdsUpgradedTestRunner,
+ 2, { twoThirdsUpgradedTest.nodes.get(0).transportUri() })
+
Task upgradedClusterTestRunner = tasks.getByName("${baseName}#upgradedClusterTestRunner")
upgradedClusterTestRunner.configure {
systemProperty 'tests.rest.suite', 'upgraded_cluster'
+ /*
+ * Force stopping all the upgraded nodes after the test runner
+ * so they are alive during the test.
+ */
+ finalizedBy "${baseName}#oneThirdUpgradedTestCluster#stop"
+ finalizedBy "${baseName}#twoThirdsUpgradedTestCluster#stop"
// migration tests should only run when the original/old cluster nodes where versions < 5.2.0.
// this stinks but we do the check here since our rest tests do not support conditionals
@@ -272,13 +273,9 @@ subprojects {
systemProperty 'tests.rest.blacklist', '/20_security/Verify default password migration results in upgraded cluster'
}
}
-
if (version.before('6.1.0') || version.onOrAfter('6.3.0')) {
systemProperty 'tests.rest.blacklist', '/30_ml_jobs_crud/Test model memory limit is updated'
}
-
- // only need to kill the mixed cluster tests node here because we explicitly told it to not stop nodes upon completion
- finalizedBy "${baseName}#mixedClusterTestCluster#stop"
}
Task versionBwcTest = tasks.create(name: "${baseName}#bwcTest") {
diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java
index 65b1a7c85dcb1..a3576b7b8c3e8 100644
--- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java
+++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java
@@ -37,12 +37,12 @@ protected boolean preserveTemplatesUponCompletion() {
return true;
}
- enum CLUSTER_TYPE {
+ enum ClusterType {
OLD,
MIXED,
UPGRADED;
- public static CLUSTER_TYPE parse(String value) {
+ public static ClusterType parse(String value) {
switch (value) {
case "old_cluster":
return OLD;
@@ -56,7 +56,7 @@ public static CLUSTER_TYPE parse(String value) {
}
}
- protected final CLUSTER_TYPE clusterType = CLUSTER_TYPE.parse(System.getProperty("tests.rest.suite"));
+ protected static final ClusterType CLUSTER_TYPE = ClusterType.parse(System.getProperty("tests.rest.suite"));
@Override
protected Settings restClientSettings() {
diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexAuditUpgradeIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexAuditUpgradeIT.java
index 97a61f25d7b03..d8c508d730cf2 100644
--- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexAuditUpgradeIT.java
+++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/IndexAuditUpgradeIT.java
@@ -12,6 +12,7 @@
import org.elasticsearch.client.Response;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import org.hamcrest.Matcher;
+import org.elasticsearch.common.Booleans;
import org.hamcrest.Matchers;
import org.junit.Before;
@@ -19,77 +20,80 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
public class IndexAuditUpgradeIT extends AbstractUpgradeTestCase {
-
private Version minVersionInCluster;
@Before
public void findMinVersionInCluster() throws IOException {
- Response response = client().performRequest("GET", "_nodes");
- ObjectPath objectPath = ObjectPath.createFromResponse(response);
- Map nodesAsMap = objectPath.evaluate("nodes");
- Version version = Version.CURRENT;
- for (String id : nodesAsMap.keySet()) {
- Version nodeVersion = Version.fromString(objectPath.evaluate("nodes." + id + ".version"));
- if (nodeVersion.before(version)) {
- version = nodeVersion;
+ if (CLUSTER_TYPE == ClusterType.UPGRADED) {
+ // cannot use minVersion in cluster as we are upgraded on all nodes,
+ // BUT we can check the version created on the index
+ Response response = client().performRequest("GET", "/.security_audit_log*/_settings/index.version.created",
+ Collections.singletonMap("flat_settings", "true"));
+ Map responseMap = entityAsMap(response);
+ logger.info("get settings response {}", responseMap);
+ for (Map.Entry entry : responseMap.entrySet()) {
+ Map indexEntry = (Map) entry.getValue();
+ Map indexSettings = (Map) indexEntry.get("settings");
+ String versionCreated = (String) indexSettings.get("index.version.created");
+ if (versionCreated != null) {
+ Version indexVersionCreated = Version.fromId(Integer.valueOf(versionCreated));
+ if (minVersionInCluster == null || indexVersionCreated.before(minVersionInCluster)) {
+ minVersionInCluster = indexVersionCreated;
+ }
+ }
}
- }
- minVersionInCluster = version;
- }
- public void testDocsAuditedInOldCluster() throws Exception {
- assumeTrue("only runs against old cluster", clusterType == CLUSTER_TYPE.OLD);
- final Matcher expectedBuckets = minVersionInCluster.onOrAfter(Version.V_6_2_3) ? is(2) : is(0);
- assertBusy(() -> {
- assertAuditDocsExist();
- assertNumUniqueNodeNameBuckets(expectedBuckets);
- });
+ assertNotNull(minVersionInCluster);
+ } else {
+ Response response = client().performRequest("GET", "_nodes");
+ ObjectPath objectPath = ObjectPath.createFromResponse(response);
+ Map nodesAsMap = objectPath.evaluate("nodes");
+ minVersionInCluster = Version.CURRENT;
+ for (String id : nodesAsMap.keySet()) {
+ Version nodeVersion = Version.fromString(objectPath.evaluate("nodes." + id + ".version"));
+ if (nodeVersion.before(minVersionInCluster)) {
+ minVersionInCluster = nodeVersion;
+ }
+ }
+
+ assertTrue(minVersionInCluster + " is older than " + Version.CURRENT,
+ minVersionInCluster.before(Version.CURRENT));
+ }
}
- public void testDocsAuditedInMixedCluster() throws Exception {
- assumeTrue("only runs against mixed cluster", clusterType == CLUSTER_TYPE.MIXED);
- // the isOneOf(0, 1) check is necessary for instances where this test runs across an
- // an index rollover and the audit trail on the upgraded node starts so we get a bucket
- // with a node name
- final Matcher expectedBuckets = minVersionInCluster.onOrAfter(Version.V_6_2_3) ? is(2) : isOneOf(0, 1);
+ public void testAuditLogs() throws Exception {
assertBusy(() -> {
assertAuditDocsExist();
- assertNumUniqueNodeNameBuckets(expectedBuckets);
+ assertNumUniqueNodeNameBuckets(expectedNumUniqueNodeNameBuckets());
});
}
- public void testDocsAuditedInUpgradedCluster() throws Exception {
- assumeTrue("only runs against upgraded cluster", clusterType == CLUSTER_TYPE.UPGRADED);
- // cannot use minVersion in cluster as we are upgraded on all nodes,
- // BUT we can check the version created on the index
- Response response = client().performRequest("GET", "/.security_audit_log*/_settings/index.version.created",
- Collections.singletonMap("flat_settings", "true"));
- Map responseMap = entityAsMap(response);
- logger.error("get settings response {}", responseMap);
- Version minVersion = null;
- for (Map.Entry entry : responseMap.entrySet()) {
- Map indexEntry = (Map) entry.getValue();
- Map indexSettings = (Map) indexEntry.get("settings");
- String versionCreated = (String) indexSettings.get("index.version.created");
- if (versionCreated != null) {
- Version indexVersionCreated = Version.fromId(Integer.valueOf(versionCreated));
- if (minVersion == null || indexVersionCreated.before(minVersion)) {
- minVersion = indexVersionCreated;
+ private int expectedNumUniqueNodeNameBuckets() throws IOException {
+ int oldVal = minVersionInCluster.onOrAfter(Version.V_6_2_3) ? 3 : 0;
+ switch (CLUSTER_TYPE) {
+ case OLD:
+ return oldVal;
+ case MIXED:
+ if (false == masterIsNewVersion()) {
+ return oldVal;
+ }
+ if (Booleans.parseBoolean(System.getProperty("tests.first_round"))) {
+ return oldVal + 1;
}
+ return oldVal + 2;
+ case UPGRADED:
+ return oldVal + 3;
+ default:
+ throw new IllegalArgumentException("Unsupported cluster type [" + CLUSTER_TYPE + "]");
}
- }
-
- assertNotNull(minVersion);
- final Matcher expectedBuckets = minVersion.onOrAfter(Version.V_6_2_3) ? is(4) : is(2);
- assertBusy(() -> {
- assertAuditDocsExist();
- assertNumUniqueNodeNameBuckets(expectedBuckets);
- });
}
private void assertAuditDocsExist() throws Exception {
@@ -101,28 +105,42 @@ private void assertAuditDocsExist() throws Exception {
assertThat((Integer) responseMap.get("count"), Matchers.greaterThanOrEqualTo(1));
}
- private void assertNumUniqueNodeNameBuckets(Matcher numBucketsMatcher) throws Exception {
+ private void assertNumUniqueNodeNameBuckets(int numBuckets) throws Exception {
// call API that will hit all nodes
- assertEquals(200, client().performRequest("GET", "/_nodes").getStatusLine().getStatusCode());
+ Map, ?> nodesResponse = entityAsMap(client().performRequest("GET", "/_nodes/_all/info/version"));
+ logger.info("all nodes {}", nodesResponse);
HttpEntity httpEntity = new StringEntity(
"{\n" +
- " \"aggs\" : {\n" +
- " \"nodes\" : {\n" +
- " \"terms\" : { \"field\" : \"node_name\" }\n" +
- " }\n" +
- " }\n" +
- "}", ContentType.APPLICATION_JSON);
+ " \"aggs\" : {\n" +
+ " \"nodes\" : {\n" +
+ " \"terms\" : { \"field\" : \"node_name\" }\n" +
+ " }\n" +
+ " }\n" +
+ "}", ContentType.APPLICATION_JSON);
Response aggResponse = client().performRequest("GET", "/.security_audit_log*/_search",
Collections.singletonMap("pretty", "true"), httpEntity);
Map aggResponseMap = entityAsMap(aggResponse);
logger.debug("aggResponse {}", aggResponseMap);
- Map aggregations = (Map) aggResponseMap.get("aggregations");
+ Map, ?> aggregations = (Map, ?>) aggResponseMap.get("aggregations");
assertNotNull(aggregations);
- Map nodesAgg = (Map) aggregations.get("nodes");
+ Map, ?> nodesAgg = (Map, ?>) aggregations.get("nodes");
assertNotNull(nodesAgg);
- List