diff --git a/build-tools-internal/src/main/groovy/elasticsearch.bwc-test.gradle b/build-tools-internal/src/main/groovy/elasticsearch.bwc-test.gradle index b80c450c5914e..a5e74c3721297 100644 --- a/build-tools-internal/src/main/groovy/elasticsearch.bwc-test.gradle +++ b/build-tools-internal/src/main/groovy/elasticsearch.bwc-test.gradle @@ -9,6 +9,8 @@ import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.internal.ElasticsearchTestBasePlugin import org.elasticsearch.gradle.internal.info.BuildParams +import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin +import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask ext.bwcTaskName = { Version version -> return "v${version}#bwcTest" @@ -36,5 +38,17 @@ plugins.withType(ElasticsearchTestBasePlugin) { } } +plugins.withType(InternalJavaRestTestPlugin) { + tasks.named("javaRestTest") { + enabled = false + } + + tasks.withType(StandaloneRestIntegTestTask).configureEach { + testClassesDirs = sourceSets.javaRestTest.output.classesDirs + classpath = sourceSets.javaRestTest.runtimeClasspath + usesDefaultDistribution() + } +} + tasks.matching { it.name.equals("check") }.configureEach {dependsOn(bwcTestSnapshots) } tasks.matching { it.name.equals("test") }.configureEach {enabled = false} diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcVersions.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcVersions.java index 28c5067840ce5..4fa444bb62ab5 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcVersions.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcVersions.java @@ -352,11 +352,11 @@ public List getAllIndexCompatible() { .collect(Collectors.toList()); } - public void withIndexCompatiple(BiConsumer versionAction) { + public void withIndexCompatible(BiConsumer versionAction) { getIndexCompatible().forEach(v -> versionAction.accept(v, "v" + v.toString())); } - public void withIndexCompatiple(Predicate filter, BiConsumer versionAction) { + public void withIndexCompatible(Predicate filter, BiConsumer versionAction) { getIndexCompatible().stream().filter(filter).forEach(v -> versionAction.accept(v, "v" + v.toString())); } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java index dbc290c5dff91..68d4d871abbde 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java @@ -109,7 +109,7 @@ public void execute(Task t) { test.getJvmArgumentProviders().add(nonInputProperties); test.getExtensions().add("nonInputProperties", nonInputProperties); - test.setWorkingDir(project.file(project.getBuildDir() + "/testrun/" + test.getName())); + test.setWorkingDir(project.file(project.getBuildDir() + "/testrun/" + test.getName().replace("#", "_"))); test.setMaxParallelForks(Integer.parseInt(System.getProperty("tests.jvms", BuildParams.getDefaultParallel().toString()))); test.exclude("**/*$*.class"); diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java index 1cf70d4564f37..da1544ea6d01b 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java @@ -13,6 +13,11 @@ import org.elasticsearch.gradle.Architecture; import org.elasticsearch.gradle.DistributionDownloadPlugin; import org.elasticsearch.gradle.ElasticsearchDistribution; +import org.elasticsearch.gradle.ElasticsearchDistributionType; +import org.elasticsearch.gradle.Jdk; +import org.elasticsearch.gradle.JdkDownloadPlugin; +import org.elasticsearch.gradle.OS; +import org.elasticsearch.gradle.Version; import org.elasticsearch.gradle.VersionProperties; import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes; import org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin; @@ -54,8 +59,11 @@ public class RestTestBasePlugin implements Plugin { private static final String TESTS_RUNTIME_JAVA_SYSPROP = "tests.runtime.java"; + private static final String TESTS_LEGACY_JAVA_SYSPROP = "tests.legacy.java"; private static final String DEFAULT_DISTRIBUTION_SYSPROP = "tests.default.distribution"; private static final String INTEG_TEST_DISTRIBUTION_SYSPROP = "tests.integ-test.distribution"; + private static final String BWC_SNAPSHOT_DISTRIBUTION_SYSPROP_PREFIX = "tests.snapshot.distribution."; + private static final String BWC_RELEASED_DISTRIBUTION_SYSPROP_PREFIX = "tests.release.distribution."; private static final String TESTS_CLUSTER_MODULES_PATH_SYSPROP = "tests.cluster.modules.path"; private static final String TESTS_CLUSTER_PLUGINS_PATH_SYSPROP = "tests.cluster.plugins.path"; private static final String DEFAULT_REST_INTEG_TEST_DISTRO = "default_distro"; @@ -63,6 +71,8 @@ public class RestTestBasePlugin implements Plugin { private static final String MODULES_CONFIGURATION = "clusterModules"; private static final String PLUGINS_CONFIGURATION = "clusterPlugins"; private static final String EXTRACTED_PLUGINS_CONFIGURATION = "extractedPlugins"; + private static final String LEGACY_JAVA_VENDOR = "adoptium"; + private static final String LEGACY_JAVA_VERSION = "8u302+b08"; private final ProviderFactory providerFactory; @@ -75,18 +85,20 @@ public RestTestBasePlugin(ProviderFactory providerFactory) { public void apply(Project project) { project.getPluginManager().apply(ElasticsearchJavaPlugin.class); project.getPluginManager().apply(InternalDistributionDownloadPlugin.class); + project.getPluginManager().apply(JdkDownloadPlugin.class); // Register integ-test and default distributions - NamedDomainObjectContainer distributions = DistributionDownloadPlugin.getContainer(project); - ElasticsearchDistribution defaultDistro = distributions.create(DEFAULT_REST_INTEG_TEST_DISTRO, distro -> { - distro.setVersion(VersionProperties.getElasticsearch()); - distro.setArchitecture(Architecture.current()); - }); - ElasticsearchDistribution integTestDistro = distributions.create(INTEG_TEST_REST_INTEG_TEST_DISTRO, distro -> { - distro.setVersion(VersionProperties.getElasticsearch()); - distro.setArchitecture(Architecture.current()); - distro.setType(ElasticsearchDistributionTypes.INTEG_TEST_ZIP); - }); + ElasticsearchDistribution defaultDistro = createDistribution( + project, + DEFAULT_REST_INTEG_TEST_DISTRO, + VersionProperties.getElasticsearch() + ); + ElasticsearchDistribution integTestDistro = createDistribution( + project, + INTEG_TEST_REST_INTEG_TEST_DISTRO, + VersionProperties.getElasticsearch(), + ElasticsearchDistributionTypes.INTEG_TEST_ZIP + ); // Create configures for module and plugin dependencies Configuration modulesConfiguration = createPluginConfiguration(project, MODULES_CONFIGURATION, true); @@ -105,6 +117,14 @@ public void apply(Project project) { }); + // Register legacy JDK for running pre-7.0 clusters + Jdk legacyJdk = JdkDownloadPlugin.getContainer(project).create("legacy_jdk", jdk -> { + jdk.setVendor(LEGACY_JAVA_VENDOR); + jdk.setVersion(LEGACY_JAVA_VERSION); + jdk.setPlatform(OS.current().name().toLowerCase()); + jdk.setArchitecture(Architecture.current().name().toLowerCase()); + }); + project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(task -> { SystemPropertyCommandLineArgumentProvider nonInputSystemProperties = task.getExtensions() .getByType(SystemPropertyCommandLineArgumentProvider.class); @@ -149,6 +169,40 @@ public Void call(Object... args) { return null; } }); + + // Add `usesBwcDistribution(version)` extension method to test tasks to indicate they require a BWC distribution + task.getExtensions().getExtraProperties().set("usesBwcDistribution", new Closure(task) { + @Override + public Void call(Object... args) { + if (args.length != 1 && args[0] instanceof Version == false) { + throw new IllegalArgumentException("Expected exactly one argument of type org.elasticsearch.gradle.Version"); + } + + Version version = (Version) args[0]; + boolean isReleased = BuildParams.getBwcVersions().unreleasedInfo(version) == null; + String versionString = version.toString(); + ElasticsearchDistribution bwcDistro = createDistribution(project, "bwc_" + versionString, versionString); + + task.dependsOn(bwcDistro); + registerDistributionInputs(task, bwcDistro); + + nonInputSystemProperties.systemProperty( + (isReleased ? BWC_RELEASED_DISTRIBUTION_SYSPROP_PREFIX : BWC_SNAPSHOT_DISTRIBUTION_SYSPROP_PREFIX) + versionString, + providerFactory.provider(() -> bwcDistro.getExtracted().getSingleFile().getPath()) + ); + + // If we're testing a version pre-7.0 we also need a compatible JDK + if (version.before("7.0.0")) { + task.dependsOn(legacyJdk); + nonInputSystemProperties.systemProperty( + TESTS_LEGACY_JAVA_SYSPROP, + providerFactory.provider(() -> legacyJdk.getJavaHomePath().toString()) + ); + } + + return null; + } + }); }); project.getTasks() @@ -156,6 +210,26 @@ public Void call(Object... args) { .configure(check -> check.dependsOn(project.getTasks().withType(StandaloneRestIntegTestTask.class))); } + private ElasticsearchDistribution createDistribution(Project project, String name, String version) { + return createDistribution(project, name, version, null); + } + + private ElasticsearchDistribution createDistribution(Project project, String name, String version, ElasticsearchDistributionType type) { + NamedDomainObjectContainer distributions = DistributionDownloadPlugin.getContainer(project); + ElasticsearchDistribution maybeDistro = distributions.findByName(name); + if (maybeDistro == null) { + return distributions.create(name, distro -> { + distro.setVersion(version); + distro.setArchitecture(Architecture.current()); + if (type != null) { + distro.setType(type); + } + }); + } else { + return maybeDistro; + } + } + private FileTree getDistributionFiles(ElasticsearchDistribution distribution, Action patternFilter) { return distribution.getExtracted().getAsFileTree().matching(patternFilter); } diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/Version.java b/build-tools/src/main/java/org/elasticsearch/gradle/Version.java index ab65f91f3da0e..27a9f0b352f3b 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/Version.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/Version.java @@ -7,6 +7,7 @@ */ package org.elasticsearch.gradle; +import java.io.Serializable; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -14,7 +15,7 @@ /** * Encapsulates comparison and printing logic for an x.y.z version. */ -public final class Version implements Comparable { +public final class Version implements Comparable, Serializable { private final int major; private final int minor; private final int revision; diff --git a/qa/full-cluster-restart/build.gradle b/qa/full-cluster-restart/build.gradle index 29f2cff1fb5ce..b6f181809e0e4 100644 --- a/qa/full-cluster-restart/build.gradle +++ b/qa/full-cluster-restart/build.gradle @@ -6,54 +6,20 @@ * Side Public License, v 1. */ - import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask -apply plugin: 'elasticsearch.internal-testclusters' -apply plugin: 'elasticsearch.standalone-rest-test' -apply plugin: 'elasticsearch.internal-test-artifact' +apply plugin: 'elasticsearch.internal-java-rest-test' +apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.bwc-test' -BuildParams.bwcVersions.withIndexCompatiple { bwcVersion, baseName -> - def baseCluster = testClusters.register(baseName) { - versions = [bwcVersion.toString(), project.version] - numberOfNodes = 2 - // some tests rely on the translog not being flushed - setting 'indices.memory.shard_inactive_time', '60m' - setting 'http.content_type.required', 'true' - setting 'path.repo', "${buildDir}/cluster/shared/repo/${baseName}" - setting 'xpack.security.enabled', 'false' - } - - tasks.register("${baseName}#oldClusterTest", StandaloneRestIntegTestTask) { - useCluster baseCluster - mustRunAfter("precommit") - doFirst { - delete("${buildDir}/cluster/shared/repo/${baseName}") - } - - systemProperty 'tests.is_old_cluster', 'true' - } - - tasks.register("${baseName}#upgradedClusterTest", StandaloneRestIntegTestTask) { - useCluster baseCluster - dependsOn "${baseName}#oldClusterTest" - doFirst { - baseCluster.get().goToNextVersion() - } - systemProperty 'tests.is_old_cluster', 'false' - } - - String oldVersion = bwcVersion.toString().minus("-SNAPSHOT") - tasks.matching { it.name.startsWith(baseName) && it.name.endsWith("ClusterTest") }.configureEach { - it.systemProperty 'tests.old_cluster_version', oldVersion - it.systemProperty 'tests.path.repo', "${buildDir}/cluster/shared/repo/${baseName}" - it.nonInputProperties.systemProperty('tests.rest.cluster', baseCluster.map(c -> c.allHttpSocketURI.join(","))) - it.nonInputProperties.systemProperty('tests.clustername', baseName) - } +testArtifacts { + registerTestArtifactFromSourceSet(sourceSets.javaRestTest) +} - tasks.register(bwcTaskName(bwcVersion)) { - dependsOn tasks.named("${baseName}#upgradedClusterTest") +BuildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> + tasks.register(bwcTaskName(bwcVersion), StandaloneRestIntegTestTask) { + usesBwcDistribution(bwcVersion) + systemProperty("tests.old_cluster_version", bwcVersion) } } diff --git a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java similarity index 96% rename from qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartIT.java rename to qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java index 2f61e51345340..1863e32ef5eda 100644 --- a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java @@ -8,6 +8,8 @@ package org.elasticsearch.upgrades; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.apache.http.util.EntityUtils; import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; @@ -32,6 +34,10 @@ import org.elasticsearch.rest.action.search.RestExplainAction; import org.elasticsearch.test.NotEqualMessageBuilder; import org.elasticsearch.test.XContentTestUtils; +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.FeatureFlag; +import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider; +import org.elasticsearch.test.cluster.local.distribution.DistributionType; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.yaml.ObjectPath; import org.elasticsearch.transport.Compression; @@ -39,6 +45,10 @@ import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.json.JsonXContent; import org.junit.Before; +import org.junit.ClassRule; +import org.junit.rules.RuleChain; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestRule; import java.io.IOException; import java.util.ArrayList; @@ -48,7 +58,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; @@ -80,15 +89,44 @@ * version is started with the same data directories and then this is rerun * with {@code tests.is_old_cluster} set to {@code false}. */ -public class FullClusterRestartIT extends AbstractFullClusterRestartTestCase { +public class FullClusterRestartIT extends ParameterizedFullClusterRestartTestCase { private final boolean supportsLenientBooleans = getOldClusterVersion().before(Version.V_6_0_0_alpha1); + private static TemporaryFolder repoDirectory = new TemporaryFolder(); + + protected static LocalClusterConfigProvider clusterConfig = c -> {}; + + private static ElasticsearchCluster cluster = ElasticsearchCluster.local() + .distribution(DistributionType.DEFAULT) + .version(getOldClusterTestVersion()) + .nodes(2) + .setting("path.repo", () -> repoDirectory.getRoot().getPath()) + .setting("xpack.security.enabled", "false") + // some tests rely on the translog not being flushed + .setting("indices.memory.shard_inactive_time", "60m") + .setting("http.content_type.required", "true") + .apply(() -> clusterConfig) + .feature(FeatureFlag.TIME_SERIES_MODE) + .build(); + + @ClassRule + public static TestRule ruleChain = RuleChain.outerRule(repoDirectory).around(cluster); + private String index; private String type; + public FullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected ElasticsearchCluster getUpgradeCluster() { + return cluster; + } + @Before public void setIndex() { - index = getTestName().toLowerCase(Locale.ROOT); + index = getRootTestName(); } @Before @@ -236,7 +274,7 @@ public void testNewReplicasWork() throws Exception { search.addParameter("preference", "_only_nodes:" + node); Map responseBody = entityAsMap(client().performRequest(search)); assertNoFailures(responseBody); - int hits = extractTotalHits(responseBody); + int hits = extractTotalHits(isRunningAgainstOldCluster(), responseBody); counts.add(hits); } assertEquals("All nodes should have a consistent number of documents", 1, counts.size()); @@ -367,7 +405,7 @@ public void testShrink() throws IOException { assertThat(totalShards, greaterThan(1)); int successfulShards = (int) XContentMapValues.extractValue("_shards.successful", response); assertEquals(totalShards, successfulShards); - int totalHits = extractTotalHits(response); + int totalHits = extractTotalHits(isRunningAgainstOldCluster(), response); assertEquals(numDocs, totalHits); response = entityAsMap(client().performRequest(new Request("GET", "/" + shrunkenIndex + "/_search"))); @@ -376,7 +414,7 @@ public void testShrink() throws IOException { assertEquals(1, totalShards); successfulShards = (int) XContentMapValues.extractValue("_shards.successful", response); assertEquals(1, successfulShards); - totalHits = extractTotalHits(response); + totalHits = extractTotalHits(isRunningAgainstOldCluster(), response); assertEquals(numDocs, totalHits); } @@ -444,7 +482,7 @@ public void testShrinkAfterUpgrade() throws IOException { assertThat(totalShards, greaterThan(1)); int successfulShards = (int) XContentMapValues.extractValue("_shards.successful", response); assertEquals(totalShards, successfulShards); - int totalHits = extractTotalHits(response); + int totalHits = extractTotalHits(isRunningAgainstOldCluster(), response); assertEquals(numDocs, totalHits); if (isRunningAgainstOldCluster() == false) { @@ -454,7 +492,7 @@ public void testShrinkAfterUpgrade() throws IOException { assertEquals(1, totalShards); successfulShards = (int) XContentMapValues.extractValue("_shards.successful", response); assertEquals(1, successfulShards); - totalHits = extractTotalHits(response); + totalHits = extractTotalHits(isRunningAgainstOldCluster(), response); assertEquals(numDocs, totalHits); } } @@ -508,7 +546,7 @@ public void testRollover() throws IOException { assertNoFailures(count); int expectedCount = bulkCount + (isRunningAgainstOldCluster() ? 0 : bulkCount); - assertEquals(expectedCount, extractTotalHits(count)); + assertEquals(expectedCount, extractTotalHits(isRunningAgainstOldCluster(), count)); } void assertBasicSearchWorks(int count) throws IOException { @@ -516,7 +554,7 @@ void assertBasicSearchWorks(int count) throws IOException { { Map response = entityAsMap(client().performRequest(new Request("GET", "/" + index + "/_search"))); assertNoFailures(response); - int numDocs = extractTotalHits(response); + int numDocs = extractTotalHits(isRunningAgainstOldCluster(), response); logger.info("Found {} in old index", numDocs); assertEquals(count, numDocs); } @@ -913,7 +951,7 @@ public void testSnapshotRestore() throws IOException { repoConfig.startObject("settings"); { repoConfig.field("compress", randomBoolean()); - repoConfig.field("location", System.getProperty("tests.path.repo")); + repoConfig.field("location", repoDirectory.getRoot().getPath()); } repoConfig.endObject(); } @@ -1613,7 +1651,7 @@ public void testEnableSoftDeletesOnRestore() throws Exception { repoConfig.startObject("settings"); { repoConfig.field("compress", randomBoolean()); - repoConfig.field("location", System.getProperty("tests.path.repo")); + repoConfig.field("location", repoDirectory.getRoot().getPath()); } repoConfig.endObject(); } @@ -1668,7 +1706,7 @@ public void testForbidDisableSoftDeletesOnRestore() throws Exception { repoConfig.startObject("settings"); { repoConfig.field("compress", randomBoolean()); - repoConfig.field("location", System.getProperty("tests.path.repo")); + repoConfig.field("location", repoDirectory.getRoot().getPath()); } repoConfig.endObject(); } @@ -1739,12 +1777,29 @@ public void testTransportCompressionSetting() throws IOException { } } - public static void assertNumHits(String index, int numHits, int totalShards) throws IOException { + public static void assertNumHits(boolean isRunningAgainstOldCluster, String index, int numHits, int totalShards) throws IOException { Map resp = entityAsMap(client().performRequest(new Request("GET", "/" + index + "/_search"))); assertNoFailures(resp); assertThat(XContentMapValues.extractValue("_shards.total", resp), equalTo(totalShards)); assertThat(XContentMapValues.extractValue("_shards.successful", resp), equalTo(totalShards)); - assertThat(extractTotalHits(resp), equalTo(numHits)); + assertThat(extractTotalHits(isRunningAgainstOldCluster, resp), equalTo(numHits)); + } + + protected static void assertNoFailures(Map response) { + int failed = (int) XContentMapValues.extractValue("_shards.failed", response); + assertEquals(0, failed); + } + + protected void assertTotalHits(int expectedTotalHits, Map response) { + int actualTotalHits = extractTotalHits(isRunningAgainstOldCluster(), response); + assertEquals(response.toString(), expectedTotalHits, actualTotalHits); } + protected static int extractTotalHits(boolean isRunningAgainstOldCluster, Map response) { + if (isRunningAgainstOldCluster && getOldClusterVersion().before(org.elasticsearch.Version.V_7_0_0)) { + return (Integer) XContentMapValues.extractValue("hits.total", response); + } else { + return (Integer) XContentMapValues.extractValue("hits.total.value", response); + } + } } diff --git a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java similarity index 83% rename from qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java rename to qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java index 31df3638302b4..3c160af23c3b5 100644 --- a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.java @@ -8,6 +8,8 @@ package org.elasticsearch.upgrades; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; import org.elasticsearch.client.Request; @@ -15,11 +17,15 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider; +import org.elasticsearch.test.cluster.local.distribution.DistributionType; import org.elasticsearch.transport.RemoteClusterService; import org.elasticsearch.transport.SniffConnectionStrategy; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.json.JsonXContent; +import org.junit.ClassRule; import java.io.IOException; import java.util.Collections; @@ -29,7 +35,27 @@ import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; import static org.hamcrest.Matchers.equalTo; -public class FullClusterRestartSettingsUpgradeIT extends AbstractFullClusterRestartTestCase { +public class FullClusterRestartSettingsUpgradeIT extends ParameterizedFullClusterRestartTestCase { + + protected static LocalClusterConfigProvider clusterConfig = c -> {}; + + @ClassRule + public static ElasticsearchCluster cluster = ElasticsearchCluster.local() + .distribution(DistributionType.DEFAULT) + .version(getOldClusterTestVersion()) + .nodes(2) + .setting("xpack.security.enabled", "false") + .apply(() -> clusterConfig) + .build(); + + public FullClusterRestartSettingsUpgradeIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected ElasticsearchCluster getUpgradeCluster() { + return cluster; + } public void testRemoteClusterSettingsUpgraded() throws IOException { assumeTrue("skip_unavailable did not exist until 6.1.0", getOldClusterVersion().onOrAfter(Version.V_6_1_0)); diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartTestOrdering.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartTestOrdering.java new file mode 100644 index 0000000000000..232619ee93bb9 --- /dev/null +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartTestOrdering.java @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.upgrades; + +import com.carrotsearch.randomizedtesting.TestMethodAndParams; + +import java.util.Comparator; + +public class FullClusterRestartTestOrdering implements Comparator { + @Override + public int compare(TestMethodAndParams o1, TestMethodAndParams o2) { + return Integer.compare(getOrdinal(o1), getOrdinal(o2)); + } + + private int getOrdinal(TestMethodAndParams t) { + return ((FullClusterRestartUpgradeStatus) t.getInstanceArguments().get(0)).ordinal(); + } +} diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartUpgradeStatus.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartUpgradeStatus.java new file mode 100644 index 0000000000000..06048d020e2a0 --- /dev/null +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartUpgradeStatus.java @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.upgrades; + +public enum FullClusterRestartUpgradeStatus { + OLD, + UPGRADED +} diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java new file mode 100644 index 0000000000000..01bcd1b65d720 --- /dev/null +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java @@ -0,0 +1,134 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.upgrades; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; + +import org.elasticsearch.client.Request; +import org.elasticsearch.common.Strings; +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.util.Version; +import org.elasticsearch.test.rest.ESRestTestCase; +import org.elasticsearch.xcontent.XContentBuilder; +import org.junit.AfterClass; +import org.junit.Before; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Collectors; + +import static org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus.OLD; +import static org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus.UPGRADED; +import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; +import static org.hamcrest.Matchers.equalTo; + +@TestCaseOrdering(FullClusterRestartTestOrdering.class) +public abstract class ParameterizedFullClusterRestartTestCase extends ESRestTestCase { + private static final Version OLD_CLUSTER_VERSION = Version.fromString(System.getProperty("tests.old_cluster_version")); + private static boolean upgradeFailed = false; + private static boolean upgraded = false; + private final FullClusterRestartUpgradeStatus requestedUpgradeStatus; + + public ParameterizedFullClusterRestartTestCase(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + this.requestedUpgradeStatus = upgradeStatus; + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return Arrays.stream(FullClusterRestartUpgradeStatus.values()).map(v -> new Object[] { v }).collect(Collectors.toList()); + } + + @Before + public void maybeUpgrade() throws Exception { + if (upgraded == false && requestedUpgradeStatus == UPGRADED) { + try { + getUpgradeCluster().upgradeToVersion(Version.CURRENT); + closeClients(); + initClient(); + } catch (Exception e) { + upgradeFailed = true; + throw e; + } finally { + upgraded = true; + } + } + + // Skip remaining tests if upgrade failed + assumeFalse("Cluster upgrade failed", upgradeFailed); + } + + @Before + public void init() throws IOException { + assertThat( + "we don't need this branch if we aren't compatible with 6.0", + org.elasticsearch.Version.CURRENT.minimumIndexCompatibilityVersion().onOrBefore(org.elasticsearch.Version.V_6_0_0), + equalTo(true) + ); + if (isRunningAgainstOldCluster() && getOldClusterVersion().before(org.elasticsearch.Version.V_7_0_0)) { + XContentBuilder template = jsonBuilder(); + template.startObject(); + { + template.field("index_patterns", "*"); + template.field("order", "0"); + template.startObject("settings"); + template.field("number_of_shards", 5); + template.endObject(); + } + template.endObject(); + Request createTemplate = new Request("PUT", "/_template/template"); + createTemplate.setJsonEntity(Strings.toString(template)); + client().performRequest(createTemplate); + } + } + + @AfterClass + public static void resetUpgrade() { + upgraded = false; + upgradeFailed = false; + } + + public boolean isRunningAgainstOldCluster() { + return requestedUpgradeStatus == OLD; + } + + public static org.elasticsearch.Version getOldClusterVersion() { + return org.elasticsearch.Version.fromString(OLD_CLUSTER_VERSION.toString()); + } + + public static Version getOldClusterTestVersion() { + return Version.fromString(OLD_CLUSTER_VERSION.toString()); + } + + /** + * @return true if test is running against an old cluster before that last major, in this case + * when System.getProperty("tests.is_old_cluster" == true) and oldClusterVersion is before {@link org.elasticsearch.Version#V_7_0_0} + */ + protected final boolean isRunningAgainstAncientCluster() { + return isRunningAgainstOldCluster() && getOldClusterVersion().before(org.elasticsearch.Version.V_7_0_0); + } + + protected abstract ElasticsearchCluster getUpgradeCluster(); + + @Override + protected String getTestRestCluster() { + return getUpgradeCluster().getHttpAddresses(); + } + + @Override + protected boolean preserveClusterUponCompletion() { + return true; + } + + protected String getRootTestName() { + return getTestName().split(" ")[0].toLowerCase(Locale.ROOT); + } +} diff --git a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java similarity index 92% rename from qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java rename to qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java index a0c7d213cade3..2eb218dfe3b1e 100644 --- a/qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/QueryBuilderBWCIT.java @@ -8,6 +8,8 @@ package org.elasticsearch.upgrades; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.apache.http.util.EntityUtils; import org.elasticsearch.Version; import org.elasticsearch.client.Request; @@ -34,8 +36,12 @@ import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; import org.elasticsearch.index.query.functionscore.RandomScoreFunctionBuilder; import org.elasticsearch.search.SearchModule; +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider; +import org.elasticsearch.test.cluster.local.distribution.DistributionType; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.json.JsonXContent; +import org.junit.ClassRule; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -58,10 +64,29 @@ * The queries to test are specified in json format, which turns out to work because we tend break here rarely. If the * json format of a query being tested here then feel free to change this. */ -public class QueryBuilderBWCIT extends AbstractFullClusterRestartTestCase { - +public class QueryBuilderBWCIT extends ParameterizedFullClusterRestartTestCase { private static final List CANDIDATES = new ArrayList<>(); + protected static LocalClusterConfigProvider clusterConfig = c -> {}; + + @ClassRule + public static ElasticsearchCluster cluster = ElasticsearchCluster.local() + .distribution(DistributionType.DEFAULT) + .version(getOldClusterTestVersion()) + .nodes(2) + .setting("xpack.security.enabled", "false") + .apply(() -> clusterConfig) + .build(); + + @Override + protected ElasticsearchCluster getUpgradeCluster() { + return cluster; + } + + public QueryBuilderBWCIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + static { addCandidate("\"match\": { \"text_field\": \"value\"}", new MatchQueryBuilder("text_field", "value")); addCandidate( diff --git a/qa/repository-multi-version/build.gradle b/qa/repository-multi-version/build.gradle index c626a7573b6b8..0b9bad2b705ce 100644 --- a/qa/repository-multi-version/build.gradle +++ b/qa/repository-multi-version/build.gradle @@ -19,7 +19,7 @@ dependencies { testImplementation project(':client:rest-high-level') } -BuildParams.bwcVersions.withIndexCompatiple { bwcVersion, baseName -> +BuildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> String oldClusterName = "${baseName}-old" String newClusterName = "${baseName}-new" diff --git a/qa/verify-version-constants/build.gradle b/qa/verify-version-constants/build.gradle index 22a277d44b812..72cc4240b1cbd 100644 --- a/qa/verify-version-constants/build.gradle +++ b/qa/verify-version-constants/build.gradle @@ -14,7 +14,7 @@ apply plugin: 'elasticsearch.internal-testclusters' apply plugin: 'elasticsearch.standalone-rest-test' apply plugin: 'elasticsearch.bwc-test' -BuildParams.bwcVersions.withIndexCompatiple { bwcVersion, baseName -> +BuildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> def baseCluster = testClusters.register(baseName) { version = bwcVersion.toString() setting 'http.content_type.required', 'true' diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/ClusterHandle.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/ClusterHandle.java index 658925744860d..2a4e3e3958c57 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/ClusterHandle.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/ClusterHandle.java @@ -8,6 +8,8 @@ package org.elasticsearch.test.cluster; +import org.elasticsearch.test.cluster.util.Version; + import java.io.Closeable; /** @@ -73,4 +75,19 @@ public interface ClusterHandle extends Closeable { * @return cluster node TCP transport endpoints */ String getTransportEndpoint(int index); + + /** + * Upgrades a single node to the given version. Method blocks until the node is back up and ready to respond to requests. + * + * @param index index of node ot upgrade + * @param version version to upgrade to + */ + void upgradeNodeToVersion(int index, Version version); + + /** + * Performs a "full cluster restart" upgrade to the given version. Method blocks until the cluster is restarted and available. + * + * @param version version to upgrade to + */ + void upgradeToVersion(Version version); } diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalSpecBuilder.java index 2e3366cdf9af3..aa71ffdf27a72 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalSpecBuilder.java @@ -12,6 +12,7 @@ import org.elasticsearch.test.cluster.FeatureFlag; import org.elasticsearch.test.cluster.SettingsProvider; import org.elasticsearch.test.cluster.local.distribution.DistributionType; +import org.elasticsearch.test.cluster.util.Version; import org.elasticsearch.test.cluster.util.resource.Resource; import java.util.ArrayList; @@ -32,9 +33,11 @@ public abstract class AbstractLocalSpecBuilder> im private final Set plugins = new HashSet<>(); private final Set features = new HashSet<>(); private final Map keystoreSettings = new HashMap<>(); + private final Map keystoreFiles = new HashMap<>(); private final Map extraConfigFiles = new HashMap<>(); private final Map systemProperties = new HashMap<>(); private DistributionType distributionType; + private Version version; private String keystorePassword; protected AbstractLocalSpecBuilder(AbstractLocalSpecBuilder parent) { @@ -138,6 +141,16 @@ public Map getKeystoreSettings() { return inherit(() -> parent.getKeystoreSettings(), keystoreSettings); } + @Override + public T keystore(String key, Resource file) { + this.keystoreFiles.put(key, file); + return cast(this); + } + + public Map getKeystoreFiles() { + return inherit(() -> parent.getKeystoreFiles(), keystoreFiles); + } + @Override public T configFile(String fileName, Resource configFile) { this.extraConfigFiles.put(fileName, configFile); @@ -168,6 +181,16 @@ public String getKeystorePassword() { return inherit(() -> parent.getKeystorePassword(), keystorePassword); } + @Override + public T version(Version version) { + this.version = version; + return cast(this); + } + + public Version getVersion() { + return inherit(() -> parent.getVersion(), version); + } + private List inherit(Supplier> parent, List child) { List combinedList = new ArrayList<>(); if (this.parent != null) { diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultEnvironmentProvider.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultEnvironmentProvider.java index aa3982e076ae0..c1a1bc4d5f14e 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultEnvironmentProvider.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultEnvironmentProvider.java @@ -21,6 +21,7 @@ public class DefaultEnvironmentProvider implements EnvironmentProvider { private static final String HOSTNAME_OVERRIDE = "LinuxDarwinHostname"; private static final String COMPUTERNAME_OVERRIDE = "WindowsComputername"; private static final String TESTS_RUNTIME_JAVA_SYSPROP = "tests.runtime.java"; + private static final String TESTS_LEGACY_JAVA_SYSPROP = "tests.legacy.java"; @Override public Map get(LocalNodeSpec nodeSpec) { @@ -29,6 +30,8 @@ public Map get(LocalNodeSpec nodeSpec) { // If we are testing the current version of Elasticsearch, use the configured runtime Java, otherwise use the bundled JDK if (nodeSpec.getDistributionType() == DistributionType.INTEG_TEST || nodeSpec.getVersion().equals(Version.CURRENT)) { environment.put("ES_JAVA_HOME", System.getProperty(TESTS_RUNTIME_JAVA_SYSPROP)); + } else if (nodeSpec.getVersion().before("7.0.0")) { + environment.put("JAVA_HOME", System.getProperty(TESTS_LEGACY_JAVA_SYSPROP)); } // Override the system hostname variables for testing diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java index 9b3b82b2571d6..3a28e57255dbb 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java @@ -19,19 +19,20 @@ import java.util.List; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.Supplier; public class DefaultLocalClusterSpecBuilder extends AbstractLocalSpecBuilder implements LocalClusterSpecBuilder { private String name = "test-cluster"; private final List nodeBuilders = new ArrayList<>(); private final List users = new ArrayList<>(); private final List roleFiles = new ArrayList<>(); + private final List> lazyConfigProviders = new ArrayList<>(); public DefaultLocalClusterSpecBuilder() { super(null); this.apply(new FipsEnabledClusterConfigProvider()); this.settings(new DefaultSettingsProvider()); this.environment(new DefaultEnvironmentProvider()); - this.rolesFile(Resource.fromClasspath("default_test_roles.yml")); } @Override @@ -46,6 +47,12 @@ public DefaultLocalClusterSpecBuilder apply(LocalClusterConfigProvider configPro return this; } + @Override + public LocalClusterSpecBuilder apply(Supplier configProvider) { + lazyConfigProviders.add(configProvider); + return this; + } + @Override public DefaultLocalClusterSpecBuilder nodes(int nodes) { if (nodes < nodeBuilders.size()) { @@ -116,7 +123,28 @@ public ElasticsearchCluster build() { clusterSpec.setNodes(nodeSpecs); clusterSpec.validate(); - return new LocalElasticsearchCluster(clusterSpec); + return new LocalElasticsearchCluster(this); + } + + LocalClusterSpec buildClusterSpec() { + // Apply lazily provided configuration + lazyConfigProviders.forEach(s -> s.get().apply(this)); + + List clusterUsers = users.isEmpty() ? List.of(User.DEFAULT_USER) : users; + LocalClusterSpec clusterSpec = new LocalClusterSpec(name, clusterUsers, roleFiles); + List nodeSpecs; + + if (nodeBuilders.isEmpty()) { + // No node-specific configuration so assume a single-node cluster + nodeSpecs = List.of(new DefaultLocalNodeSpecBuilder(this).build(clusterSpec)); + } else { + nodeSpecs = nodeBuilders.stream().map(node -> node.build(clusterSpec)).toList(); + } + + clusterSpec.setNodes(nodeSpecs); + clusterSpec.validate(); + + return clusterSpec; } public static class DefaultLocalNodeSpecBuilder extends AbstractLocalSpecBuilder implements LocalNodeSpecBuilder { @@ -137,7 +165,7 @@ private LocalNodeSpec build(LocalClusterSpec cluster) { return new LocalNodeSpec( cluster, name, - Version.CURRENT, + Optional.ofNullable(getVersion()).orElse(Version.CURRENT), getSettingsProviders(), getSettings(), getEnvironmentProviders(), @@ -147,6 +175,7 @@ private LocalNodeSpec build(LocalClusterSpec cluster) { Optional.ofNullable(getDistributionType()).orElse(DistributionType.INTEG_TEST), getFeatures(), getKeystoreSettings(), + getKeystoreFiles(), getKeystorePassword(), getExtraConfigFiles(), getSystemProperties() diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java index a1c5e5892ef10..1828db60b9480 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java @@ -25,7 +25,11 @@ public Map get(LocalNodeSpec nodeSpec) { settings.put("node.attr.testattr", "test"); settings.put("node.portsfile", "true"); settings.put("http.port", "0"); - settings.put("transport.port", "0"); + if (nodeSpec.getVersion().onOrAfter("6.7.0")) { + settings.put("transport.port", "0"); + } else { + settings.put("transport.tcp.port", "0"); + } settings.put("network.host", "_local_"); if (nodeSpec.getDistributionType() == DistributionType.INTEG_TEST) { @@ -52,7 +56,9 @@ public Map get(LocalNodeSpec nodeSpec) { // Temporarily disable the real memory usage circuit breaker. It depends on real memory usage which we have no full control // over and the REST client will not retry on circuit breaking exceptions yet (see #31986 for details). Once the REST client // can retry on circuit breaking exceptions, we can revert again to the default configuration. - settings.put("indices.breaker.total.use_real_memory", "false"); + if (nodeSpec.getVersion().onOrAfter("7.0.0")) { + settings.put("indices.breaker.total.use_real_memory", "false"); + } // 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 settings.put("discovery.initial_state_timeout", "0s"); @@ -72,15 +78,26 @@ public Map get(LocalNodeSpec nodeSpec) { .map(LocalNodeSpec::getName) .collect(Collectors.joining(",")); - if (masterEligibleNodes.isEmpty()) { - throw new IllegalStateException( - "Cannot start cluster '" + nodeSpec.getCluster().getName() + "' as it configured with no master-eligible nodes." - ); - } + if (nodeSpec.getVersion().onOrAfter("7.0.0")) { + if (masterEligibleNodes.isEmpty()) { + throw new IllegalStateException( + "Cannot start cluster '" + nodeSpec.getCluster().getName() + "' as it configured with no master-eligible nodes." + ); + } - settings.put("cluster.initial_master_nodes", "[" + masterEligibleNodes + "]"); - settings.put("discovery.seed_providers", "file"); - settings.put("discovery.seed_hosts", "[]"); + settings.put("cluster.initial_master_nodes", "[" + masterEligibleNodes + "]"); + settings.put("discovery.seed_providers", "file"); + settings.put("discovery.seed_hosts", "[]"); + } else { + settings.put("discovery.zen.master_election.wait_for_joins_timeout", "5s"); + if (nodeSpec.getCluster().getNodes().size() > 1) { + settings.put("discovery.zen.minimum_master_nodes", Integer.toString(nodeSpec.getCluster().getNodes().size() / 2 + 1)); + } + if (nodeSpec.getVersion().onOrAfter("6.5.0")) { + settings.put("discovery.zen.hosts_provider", "file"); + settings.put("discovery.zen.ping.unicast.hosts", "[]"); + } + } return settings; } diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java index 8db6ad208edae..20a2625d0f321 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java @@ -80,21 +80,20 @@ public LocalClusterHandle create(LocalClusterSpec spec) { public class Node { private final LocalNodeSpec spec; private final Path workingDir; - private final Path distributionDir; private final Path repoDir; private final Path dataDir; private final Path logsDir; private final Path configDir; private final Path tempDir; - private boolean initialized = false; + private Path distributionDir; + private Version currentVersion; private Process process = null; private DistributionDescriptor distributionDescriptor; public Node(LocalNodeSpec spec) { this.spec = spec; this.workingDir = baseWorkingDir.resolve(spec.getCluster().getName()).resolve(spec.getName()); - this.distributionDir = workingDir.resolve("distro"); // location of es distribution files, typically hard-linked this.repoDir = baseWorkingDir.resolve("repo"); this.dataDir = workingDir.resolve("data"); this.logsDir = workingDir.resolve("logs"); @@ -102,30 +101,39 @@ public Node(LocalNodeSpec spec) { this.tempDir = workingDir.resolve("tmp"); // elasticsearch temporary directory } - public synchronized void start() { + public synchronized void start(Version version, String seedTransportAddress) { LOGGER.info("Starting Elasticsearch node '{}'", spec.getName()); + if (version != null) { + spec.setVersion(version); + } - if (initialized == false) { + if (currentVersion == null || currentVersion.equals(spec.getVersion()) == false) { LOGGER.info("Creating installation for node '{}' in {}", spec.getName(), workingDir); distributionDescriptor = resolveDistribution(); LOGGER.info("Distribution for node '{}': {}", spec.getName(), distributionDescriptor); - initializeWorkingDirectory(); + distributionDir = OS.conditional( + // Use per-version distribution directories on Windows to avoid cleanup failures + c -> c.onWindows(() -> workingDir.resolve("distro").resolve(distributionDescriptor.getVersion().toString())) + .onUnix(() -> workingDir.resolve("distro")) + ); + initializeWorkingDirectory(currentVersion != null); createConfigDirectory(); copyExtraConfigFiles(); // extra config files might be needed for running cli tools like plugin install copyExtraJarFiles(); installPlugins(); - if (spec.getDistributionType() == DistributionType.INTEG_TEST) { + if (distributionDescriptor.getType() == DistributionType.INTEG_TEST) { installModules(); } - initialized = true; + currentVersion = spec.getVersion(); } else { createConfigDirectory(); copyExtraConfigFiles(); } - writeConfiguration(); + writeConfiguration(seedTransportAddress); createKeystore(); addKeystoreSettings(); + addKeystoreFiles(); configureSecurity(); startElasticsearch(); @@ -136,6 +144,7 @@ public synchronized void stop(boolean forcibly) { ProcessUtils.stopHandle(process.toHandle(), forcibly); ProcessReaper.instance().unregister(getServiceName()); } + deletePortsFiles(); } public void waitForExit() { @@ -160,6 +169,20 @@ public String getTransportEndpoint() { return readPortsFile(portsFile).get(0); } + public void deletePortsFiles() { + try { + Path hostsFile = workingDir.resolve("config").resolve("unicast_hosts.txt"); + Path httpPortsFile = workingDir.resolve("logs").resolve("http.ports"); + Path transportPortsFile = workingDir.resolve("logs").resolve("transport.ports"); + + Files.deleteIfExists(hostsFile); + Files.deleteIfExists(httpPortsFile); + Files.deleteIfExists(transportPortsFile); + } catch (IOException e) { + throw new UncheckedIOException("Failed to write unicast_hosts for: " + this, e); + } + } + public LocalNodeSpec getSpec() { return spec; } @@ -206,9 +229,13 @@ private List readPortsFile(Path file) { } } - private void initializeWorkingDirectory() { + private void initializeWorkingDirectory(boolean preserveWorkingDirectory) { try { - IOUtils.deleteWithRetry(workingDir); + if (preserveWorkingDirectory) { + IOUtils.deleteWithRetry(distributionDir); + } else { + IOUtils.deleteWithRetry(workingDir); + } try { IOUtils.syncWithLinks(distributionDescriptor.getDistributionDir(), distributionDir); } catch (IOUtils.LinkCreationException e) { @@ -250,7 +277,7 @@ private DistributionDescriptor resolveDistribution() { ); } - private void writeConfiguration() { + private void writeConfiguration(String seedTransportAddress) { Path configFile = configDir.resolve("elasticsearch.yml"); Path jvmOptionsFile = configDir.resolve("jvm.options"); @@ -262,6 +289,16 @@ private void writeConfiguration() { finalSettings.put("path.logs", logsDir.toString()); finalSettings.putAll(spec.resolveSettings()); + // For versions pre-6.5 we cannot use the unicast hosts file + if (spec.getVersion().before("6.5.0")) { + if (seedTransportAddress != null) { + finalSettings.put("discovery.zen.ping.unicast.hosts", "[\"" + seedTransportAddress + "\"]"); + } else { + finalSettings.put("discovery.zen.ping.unicast.hosts", "[]"); + + } + } + Files.writeString( configFile, finalSettings.entrySet() @@ -302,27 +339,10 @@ private void copyExtraConfigFiles() { } private void createKeystore() { - try { - Path executable = OS.conditional( - c -> c.onWindows(() -> distributionDir.resolve("bin").resolve("elasticsearch-keystore.bat")) - .onUnix(() -> distributionDir.resolve("bin").resolve("elasticsearch-keystore")) - ); - - if (spec.getKeystorePassword() == null || spec.getKeystorePassword().isEmpty()) { - ProcessUtils.exec(workingDir, executable, getEnvironmentVariables(), false, "-v", "create").waitFor(); - } else { - ProcessUtils.exec( - spec.getKeystorePassword() + "\n" + spec.getKeystorePassword(), - workingDir, - executable, - getEnvironmentVariables(), - false, - "create", - "-p" - ).waitFor(); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); + if (spec.getKeystorePassword() == null || spec.getKeystorePassword().isEmpty()) { + runToolScript("elasticsearch-keystore", "", "-v", "create"); + } else { + runToolScript("elasticsearch-keystore", spec.getKeystorePassword() + "\n" + spec.getKeystorePassword(), "create", "-p"); } } @@ -332,9 +352,18 @@ private void addKeystoreSettings() { ? value : spec.getKeystorePassword() + "\n" + value; + runToolScript("elasticsearch-keystore", input, "add", key); + }); + } + + private void addKeystoreFiles() { + spec.getKeystoreFiles().forEach((key, file) -> { try { + Path path = Files.createTempFile(tempDir, key, null); + file.writeTo(path); + ProcessUtils.exec( - input, + spec.getKeystorePassword(), workingDir, OS.conditional( c -> c.onWindows(() -> distributionDir.resolve("bin").resolve("elasticsearch-keystore.bat")) @@ -342,10 +371,11 @@ private void addKeystoreSettings() { ), getEnvironmentVariables(), false, - "add", - key + "add-file", + key, + path.toString() ).waitFor(); - } catch (InterruptedException e) { + } catch (InterruptedException | IOException e) { throw new RuntimeException(e); } }); @@ -370,89 +400,66 @@ private void configureSecurity() { } LOGGER.info("Creating users for node '{}'", spec.getName()); + String tool = spec.getVersion().onOrAfter("6.3.0") ? "elasticsearch-users" : "x-pack/users"; for (User user : spec.getUsers()) { - try { - ProcessUtils.exec( - workingDir, - distributionDir.resolve("bin").resolve("elasticsearch-users"), - getEnvironmentVariables(), - false, - "useradd", - user.getUsername(), - "-p", - user.getPassword(), - "-r", - user.getRole() - ).waitFor(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + runToolScript(tool, null, "useradd", user.getUsername(), "-p", user.getPassword(), "-r", user.getRole()); } } } private void installPlugins() { - if (spec.getPlugins().isEmpty() == false) { - LOGGER.info("Installing plugins {} into node '{}", spec.getPlugins(), spec.getName()); - List pluginPaths = Arrays.stream(System.getProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP).split(File.pathSeparator)) - .map(Path::of) - .toList(); + List pluginPaths = Arrays.stream(System.getProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP).split(File.pathSeparator)) + .map(Path::of) + .toList(); + + List toInstall = spec.getPlugins() + .stream() + .map( + pluginName -> pluginPaths.stream() + .map(path -> Pair.of(BUNDLE_ARTIFACT_PATTERN.matcher(path.getFileName().toString()), path)) + .filter(pair -> pair.left.matches()) + .map(p -> p.right.getParent().resolve(p.left.group(1))) + .findFirst() + .orElseThrow(() -> { + String taskPath = System.getProperty("tests.task"); + String project = taskPath.substring(0, taskPath.lastIndexOf(':')); + + throw new RuntimeException( + "Unable to locate plugin '" + + pluginName + + "'. Ensure you've added the following to the build script for project '" + + project + + "':\n\n" + + "dependencies {\n" + + " clusterPlugins " + + "project(':plugins:" + + pluginName + + "')" + + "\n}" + ); + }) + ) + .map(p -> p.toUri().toString()) + .collect(Collectors.toList()); + + if (spec.getVersion().before("6.3.0")) { + // X-pack was not bundled by default prior to 6.3.0 + toInstall.add("x-pack"); + } - List toInstall = spec.getPlugins() - .stream() - .map( - pluginName -> pluginPaths.stream() - .map(path -> Pair.of(BUNDLE_ARTIFACT_PATTERN.matcher(path.getFileName().toString()), path)) - .filter(pair -> pair.left.matches()) - .map(p -> p.right.getParent().resolve(p.left.group(1))) - .findFirst() - .orElseThrow(() -> { - String taskPath = System.getProperty("tests.task"); - String project = taskPath.substring(0, taskPath.lastIndexOf(':')); - - throw new RuntimeException( - "Unable to locate plugin '" - + pluginName - + "'. Ensure you've added the following to the build script for project '" - + project - + "':\n\n" - + "dependencies {\n" - + " clusterPlugins " - + "project(':plugins:" - + pluginName - + "')" - + "\n}" - ); - }) - ) - .map(p -> p.toUri().toString()) - .toList(); + if (toInstall.isEmpty() == false) { + LOGGER.info("Installing plugins {} into node '{}", spec.getPlugins(), spec.getName()); - Path pluginCommand = OS.conditional( - c -> c.onWindows(() -> distributionDir.resolve("bin").resolve("elasticsearch-plugin.bat")) - .onUnix(() -> distributionDir.resolve("bin").resolve("elasticsearch-plugin")) - ); if (spec.getVersion().onOrAfter("7.6.0")) { - try { - ProcessUtils.exec( - workingDir, - pluginCommand, - getEnvironmentVariables(), - false, - Stream.concat(Stream.of("install", "--batch"), toInstall.stream()).toArray(String[]::new) - ).waitFor(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + runToolScript( + "elasticsearch-plugin", + null, + Stream.concat(Stream.of("install", "--batch"), toInstall.stream()).toArray(String[]::new) + ); + } else if (spec.getVersion().onOrAfter("6.3.0")) { + toInstall.forEach(plugin -> runToolScript("elasticsearch-plugin", "", "install", "--batch", plugin)); } else { - toInstall.forEach(plugin -> { - try { - ProcessUtils.exec(workingDir, pluginCommand, getEnvironmentVariables(), false, "install", "--batch", plugin) - .waitFor(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - }); + toInstall.forEach(plugin -> runToolScript("elasticsearch-plugin", "", "install", plugin)); } } } @@ -579,14 +586,35 @@ private Map getEnvironmentVariables() { private Map getJvmOptionsReplacements() { Path relativeLogsDir = workingDir.relativize(logsDir); - return Map.of( - "-XX:HeapDumpPath=data", - "-XX:HeapDumpPath=" + relativeLogsDir, - "logs/gc.log", - relativeLogsDir.resolve("gc.log").toString(), - "-XX:ErrorFile=logs/hs_err_pid%p.log", - "-XX:ErrorFile=" + relativeLogsDir.resolve("hs_err_pid%p.log") - ); + Map expansions = new HashMap<>(); + String heapDumpOrigin = spec.getVersion().onOrAfter("6.3.0") ? "-XX:HeapDumpPath=data" : "-XX:HeapDumpPath=/heap/dump/path"; + expansions.put(heapDumpOrigin, "-XX:HeapDumpPath=" + relativeLogsDir.toString()); + if (spec.getVersion().onOrAfter("6.2.0")) { + expansions.put("logs/gc.log", relativeLogsDir.resolve("gc.log").toString()); + } + if (spec.getVersion().getMajor() >= 7) { + expansions.put( + "-XX:ErrorFile=logs/hs_err_pid%p.log", + "-XX:ErrorFile=" + relativeLogsDir.resolve("hs_err_pid%p.log").toString() + ); + } + return expansions; + } + + private void runToolScript(String tool, String input, String... args) { + try { + ProcessUtils.exec( + input, + distributionDir, + distributionDir.resolve("bin") + .resolve(OS.conditional(c -> c.onWindows(() -> tool + ".bat").onUnix(() -> tool))), + getEnvironmentVariables(), + false, + args + ).waitFor(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } private String getServiceName() { diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterHandle.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterHandle.java index 58630a106ff85..870ad1b1f7064 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterHandle.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterHandle.java @@ -14,7 +14,7 @@ import org.elasticsearch.test.cluster.local.LocalClusterFactory.Node; import org.elasticsearch.test.cluster.local.model.User; import org.elasticsearch.test.cluster.util.ExceptionUtils; -import org.elasticsearch.test.cluster.util.Retry; +import org.elasticsearch.test.cluster.util.Version; import java.io.IOException; import java.io.UncheckedIOException; @@ -28,7 +28,6 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -66,7 +65,13 @@ public LocalClusterHandle(String name, List nodes) { public void start() { if (started.getAndSet(true) == false) { LOGGER.info("Starting Elasticsearch test cluster '{}'", name); - execute(() -> nodes.parallelStream().forEach(Node::start)); + if (nodes.stream().anyMatch(n -> n.getSpec().getVersion().before("6.5.0"))) { + // We need to start a seed node for clusters before 6.5.0 that don't support unicast hosts file provider + nodes.get(0).start(null, null); + execute(() -> nodes.parallelStream().skip(1).forEach(n -> n.start(null, nodes.get(0).getTransportEndpoint()))); + } else { + execute(() -> nodes.parallelStream().forEach(n -> n.start(null, null))); + } } waitUntilReady(); } @@ -75,11 +80,10 @@ public void start() { public void stop(boolean forcibly) { if (started.getAndSet(false)) { LOGGER.info("Stopping Elasticsearch test cluster '{}', forcibly: {}", name, forcibly); - execute(() -> nodes.forEach(n -> n.stop(forcibly))); - deletePortFiles(); + execute(() -> nodes.parallelStream().forEach(n -> n.stop(forcibly))); } else { // Make sure the process is stopped, otherwise wait - execute(() -> nodes.forEach(n -> n.waitForExit())); + execute(() -> nodes.parallelStream().forEach(Node::waitForExit)); } } @@ -128,16 +132,31 @@ public String getTransportEndpoint(int index) { return getTransportEndpoints().split(",")[index]; } + @Override + public void upgradeNodeToVersion(int index, Version version) { + Node node = nodes.get(index); + node.stop(false); + LOGGER.info("Upgrading node '{}' to version {}", node.getSpec().getName(), version); + node.start(version, null); + waitUntilReady(); + } + + @Override + public void upgradeToVersion(Version version) { + stop(false); + if (started.getAndSet(true) == false) { + LOGGER.info("Upgrading Elasticsearch test cluster '{}' to version {}", name, version); + execute(() -> nodes.parallelStream().forEach(n -> n.start(version, null))); + } + waitUntilReady(); + } + private void waitUntilReady() { writeUnicastHostsFile(); try { - Retry.retryUntilTrue(CLUSTER_UP_TIMEOUT, Duration.ZERO, () -> { - WaitForHttpResource wait = configureWaitForReady(); - return wait.wait(500); - }); - } catch (TimeoutException e) { - throw new RuntimeException("Timed out after " + CLUSTER_UP_TIMEOUT + " waiting for cluster '" + name + "' status to be yellow"); - } catch (ExecutionException e) { + WaitForHttpResource wait = configureWaitForReady(); + wait.waitFor(CLUSTER_UP_TIMEOUT.toMillis()); + } catch (Exception e) { throw new RuntimeException("An error occurred while checking cluster '" + name + "' status.", e); } } @@ -193,7 +212,7 @@ private boolean isSecurityAutoConfigured(Node node) { private void writeUnicastHostsFile() { String transportUris = execute(() -> nodes.parallelStream().map(Node::getTransportEndpoint).collect(Collectors.joining("\n"))); - nodes.forEach(node -> { + execute(() -> nodes.parallelStream().forEach(node -> { try { Path hostsFile = node.getWorkingDir().resolve("config").resolve("unicast_hosts.txt"); if (Files.notExists(hostsFile)) { @@ -202,23 +221,7 @@ private void writeUnicastHostsFile() { } catch (IOException e) { throw new UncheckedIOException("Failed to write unicast_hosts for: " + node, e); } - }); - } - - private void deletePortFiles() { - nodes.forEach(node -> { - try { - Path hostsFile = node.getWorkingDir().resolve("config").resolve("unicast_hosts.txt"); - Path httpPortsFile = node.getWorkingDir().resolve("logs").resolve("http.ports"); - Path tranportPortsFile = node.getWorkingDir().resolve("logs").resolve("transport.ports"); - - Files.deleteIfExists(hostsFile); - Files.deleteIfExists(httpPortsFile); - Files.deleteIfExists(tranportPortsFile); - } catch (IOException e) { - throw new UncheckedIOException("Failed to write unicast_hosts for: " + node, e); - } - }); + })); } private T execute(Callable task) { diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java index 2836411bbb067..2234b037381a8 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java @@ -69,7 +69,6 @@ void validate() { public static class LocalNodeSpec { private final LocalClusterSpec cluster; private final String name; - private final Version version; private final List settingsProviders; private final Map settings; private final List environmentProviders; @@ -79,9 +78,11 @@ public static class LocalNodeSpec { private final DistributionType distributionType; private final Set features; private final Map keystoreSettings; + private final Map keystoreFiles; private final String keystorePassword; private final Map extraConfigFiles; private final Map systemProperties; + private Version version; public LocalNodeSpec( LocalClusterSpec cluster, @@ -96,6 +97,7 @@ public LocalNodeSpec( DistributionType distributionType, Set features, Map keystoreSettings, + Map keystoreFiles, String keystorePassword, Map extraConfigFiles, Map systemProperties @@ -112,11 +114,16 @@ public LocalNodeSpec( this.distributionType = distributionType; this.features = features; this.keystoreSettings = keystoreSettings; + this.keystoreFiles = keystoreFiles; this.keystorePassword = keystorePassword; this.extraConfigFiles = extraConfigFiles; this.systemProperties = systemProperties; } + void setVersion(Version version) { + this.version = version; + } + public LocalClusterSpec getCluster() { return cluster; } @@ -157,6 +164,10 @@ public Map getKeystoreSettings() { return keystoreSettings; } + public Map getKeystoreFiles() { + return keystoreFiles; + } + public String getKeystorePassword() { return keystorePassword; } @@ -254,6 +265,7 @@ private LocalNodeSpec getFilteredSpec(SettingsProvider filteredProvider) { n.distributionType, n.features, n.keystoreSettings, + n.keystoreFiles, n.keystorePassword, n.extraConfigFiles, n.systemProperties diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java index c07a491d2ace6..1f4086fd47fe8 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java @@ -12,6 +12,7 @@ import org.elasticsearch.test.cluster.util.resource.Resource; import java.util.function.Consumer; +import java.util.function.Supplier; public interface LocalClusterSpecBuilder extends LocalSpecBuilder { /** @@ -19,8 +20,18 @@ public interface LocalClusterSpecBuilder extends LocalSpecBuilder configProvider); + /** * Sets the number of nodes for the cluster. */ diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalElasticsearchCluster.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalElasticsearchCluster.java index 54d541cd07144..9a5e5666f5e9a 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalElasticsearchCluster.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalElasticsearchCluster.java @@ -10,18 +10,21 @@ import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.local.distribution.LocalDistributionResolver; +import org.elasticsearch.test.cluster.local.distribution.ReleasedDistributionResolver; import org.elasticsearch.test.cluster.local.distribution.SnapshotDistributionResolver; +import org.elasticsearch.test.cluster.util.Version; import org.junit.runner.Description; import org.junit.runners.model.Statement; import java.nio.file.Path; public class LocalElasticsearchCluster implements ElasticsearchCluster { - private final LocalClusterSpec spec; + private final DefaultLocalClusterSpecBuilder builder; + private LocalClusterSpec spec; private LocalClusterHandle handle; - public LocalElasticsearchCluster(LocalClusterSpec spec) { - this.spec = spec; + public LocalElasticsearchCluster(DefaultLocalClusterSpecBuilder builder) { + this.builder = builder; } @Override @@ -30,9 +33,10 @@ public Statement apply(Statement base, Description description) { @Override public void evaluate() throws Throwable { try { + spec = builder.buildClusterSpec(); handle = new LocalClusterFactory( Path.of(System.getProperty("java.io.tmpdir")).resolve(description.getDisplayName()).toAbsolutePath(), - new LocalDistributionResolver(new SnapshotDistributionResolver()) + new LocalDistributionResolver(new SnapshotDistributionResolver(new ReleasedDistributionResolver())) ).create(spec); handle.start(); base.evaluate(); @@ -97,6 +101,18 @@ public String getTransportEndpoint(int index) { return handle.getTransportEndpoint(index); } + @Override + public void upgradeNodeToVersion(int index, Version version) { + checkHandle(); + handle.upgradeNodeToVersion(index, version); + } + + @Override + public void upgradeToVersion(Version version) { + checkHandle(); + handle.upgradeToVersion(version); + } + private void checkHandle() { if (handle == null) { throw new IllegalStateException("Cluster handle has not been initialized. Did you forget the @ClassRule annotation?"); diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalSpecBuilder.java index 3b9428bc1a1aa..d01d7d303748f 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalSpecBuilder.java @@ -12,6 +12,7 @@ import org.elasticsearch.test.cluster.FeatureFlag; import org.elasticsearch.test.cluster.SettingsProvider; import org.elasticsearch.test.cluster.local.distribution.DistributionType; +import org.elasticsearch.test.cluster.util.Version; import org.elasticsearch.test.cluster.util.resource.Resource; import java.util.function.Supplier; @@ -68,6 +69,11 @@ interface LocalSpecBuilder> { */ T keystore(String key, String value); + /** + * Adds a secure file to the node keystore. + */ + T keystore(String key, Resource file); + /** * Sets the security setting keystore password. */ @@ -78,6 +84,11 @@ interface LocalSpecBuilder> { */ T configFile(String fileName, Resource configFile); + /** + * Sets the version of Elasticsearch. Defaults to {@link Version#CURRENT}. + */ + T version(Version version); + /** * Adds a system property to node JVM arguments. */ diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/WaitForHttpResource.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/WaitForHttpResource.java index edab2cdf1e7e9..f00e6f13cb314 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/WaitForHttpResource.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/WaitForHttpResource.java @@ -90,7 +90,7 @@ public void setPassword(String password) { this.password = password; } - public boolean wait(int durationInMs) throws GeneralSecurityException, InterruptedException, IOException { + public boolean waitFor(long durationInMs) throws GeneralSecurityException, InterruptedException, IOException { final long waitUntil = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(durationInMs); final long sleep = Long.max(durationInMs / 10, 100); diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/LocalDistributionResolver.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/LocalDistributionResolver.java index 5c9f45cbe092f..b9442b28e1591 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/LocalDistributionResolver.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/LocalDistributionResolver.java @@ -13,6 +13,9 @@ import java.nio.file.Files; import java.nio.file.Path; +/** + * A {@link DistributionResolver} for resolving locally built distributions for the current version of Elasticsearch. + */ public class LocalDistributionResolver implements DistributionResolver { private final DistributionResolver delegate; diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/ReleasedDistributionResolver.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/ReleasedDistributionResolver.java new file mode 100644 index 0000000000000..12654be310ef8 --- /dev/null +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/ReleasedDistributionResolver.java @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.test.cluster.local.distribution; + +import org.elasticsearch.test.cluster.util.Version; + +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * A {@link DistributionResolver} for resolving previously released distributions of Elasticsearch. + */ +public class ReleasedDistributionResolver implements DistributionResolver { + private static final String BWC_DISTRIBUTION_SYSPROP_PREFIX = "tests.release.distribution."; + + @Override + public DistributionDescriptor resolve(Version version, DistributionType type) { + String distributionPath = System.getProperty(BWC_DISTRIBUTION_SYSPROP_PREFIX + version.toString()); + + if (distributionPath == null) { + String taskPath = System.getProperty("tests.task"); + String project = taskPath.substring(0, taskPath.lastIndexOf(':')); + String taskName = taskPath.substring(taskPath.lastIndexOf(':') + 1); + + throw new IllegalStateException( + "Cannot locate Elasticsearch distribution. Ensure you've added the following to the build script for project '" + + project + + "':\n\n" + + "tasks.named('" + + taskName + + "') {\n" + + " usesBwcDistribution(" + + version + + ")\n" + + "}" + ); + } + + Path distributionDir = Path.of(distributionPath); + if (Files.notExists(distributionDir)) { + throw new IllegalStateException( + "Cannot locate Elasticsearch distribution. Directory at '" + distributionDir + "' does not exist." + ); + } + + return new DefaultDistributionDescriptor(version, false, distributionDir, DistributionType.DEFAULT); + } +} diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/SnapshotDistributionResolver.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/SnapshotDistributionResolver.java index 182dbe66a584d..c6cecf09e9b9d 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/SnapshotDistributionResolver.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/distribution/SnapshotDistributionResolver.java @@ -10,10 +10,36 @@ import org.elasticsearch.test.cluster.util.Version; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * A {@link DistributionResolver} for resolving snapshot versions of Elasticsearch for previous, backwards-compatible versions. + */ public class SnapshotDistributionResolver implements DistributionResolver { + private static final String BWC_DISTRIBUTION_SYSPROP_PREFIX = "tests.snapshot.distribution."; + private final DistributionResolver delegate; + + public SnapshotDistributionResolver(DistributionResolver delegate) { + this.delegate = delegate; + } + @Override public DistributionDescriptor resolve(Version version, DistributionType type) { - // Not yet implemented - throw new UnsupportedOperationException("Cannot resolve distribution for version " + version); + String distributionPath = System.getProperty(BWC_DISTRIBUTION_SYSPROP_PREFIX + version.toString()); + + if (distributionPath != null) { + Path distributionDir = Path.of(distributionPath); + if (Files.notExists(distributionDir)) { + throw new IllegalStateException( + "Cannot locate Elasticsearch distribution. Directory at '" + distributionDir + "' does not exist." + ); + } + + // Snapshot distributions are never release builds and always use the default distribution + return new DefaultDistributionDescriptor(version, true, distributionDir, DistributionType.DEFAULT); + } + + return delegate.resolve(version, type); } } diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java index f056bbb4d0bda..c8930bd9b26f3 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java @@ -9,7 +9,7 @@ package org.elasticsearch.test.cluster.local.model; public class User { - public static final User DEFAULT_USER = new User("test_user", "x-pack-test-password", "_es_test_root"); + public static final User DEFAULT_USER = new User("test_user", "x-pack-test-password", "superuser"); private final String username; private final String password; @@ -18,7 +18,7 @@ public class User { public User(String username, String password) { this.username = username; this.password = password; - this.role = "_es_test_root"; + this.role = DEFAULT_USER.role; } public User(String username, String password, String role) { diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/util/ProcessUtils.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/util/ProcessUtils.java index e8f88c513bdd0..9685eac566a18 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/util/ProcessUtils.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/util/ProcessUtils.java @@ -57,8 +57,8 @@ public static Process exec( List command = new ArrayList<>(); command.addAll( OS.conditional( - c -> c.onWindows(() -> List.of("cmd", "/c", executable.toAbsolutePath().toString())) - .onUnix(() -> List.of(executable.toAbsolutePath().toString())) + c -> c.onWindows(() -> List.of("cmd", "/c", workingDir.relativize(executable).toString())) + .onUnix(() -> List.of(workingDir.relativize(executable).toString())) ) ); command.addAll(Arrays.asList(args)); diff --git a/x-pack/plugin/sql/qa/jdbc/build.gradle b/x-pack/plugin/sql/qa/jdbc/build.gradle index c5343b50efc10..b315a5ce1c5c7 100644 --- a/x-pack/plugin/sql/qa/jdbc/build.gradle +++ b/x-pack/plugin/sql/qa/jdbc/build.gradle @@ -71,7 +71,7 @@ subprojects { } // Configure compatibility testing tasks - BuildParams.bwcVersions.withIndexCompatiple { bwcVersion, baseName -> + BuildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> // Compatibility testing for JDBC driver started with version 7.9.0 if (bwcVersion.onOrAfter(Version.fromString("7.9.0"))) { def cluster = testClusters.maybeCreate(baseName) diff --git a/x-pack/qa/full-cluster-restart/build.gradle b/x-pack/qa/full-cluster-restart/build.gradle index a78d73e8153af..dbf33d1cfcebb 100644 --- a/x-pack/qa/full-cluster-restart/build.gradle +++ b/x-pack/qa/full-cluster-restart/build.gradle @@ -1,99 +1,21 @@ import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask -apply plugin: 'elasticsearch.internal-testclusters' -apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.bwc-test' dependencies { // TODO: Remove core dependency and change tests to not use builders that are part of xpack-core. // Currently needed for MlConfigIndexMappingsFullClusterRestartIT and SLM classes used in // FullClusterRestartIT - testImplementation(testArtifact(project(xpackModule('core')))) - testImplementation(testArtifact(project(":qa:full-cluster-restart"))) - testImplementation project(':x-pack:qa') + javaRestTestImplementation(testArtifact(project(xpackModule('core')))) + javaRestTestImplementation(testArtifact(project(":qa:full-cluster-restart"), 'javaRestTest')) + javaRestTestImplementation project(':x-pack:qa') } -tasks.named("forbiddenPatterns") { - exclude '**/system_key' -} - -String outputDir = "${buildDir}/generated-resources/${project.name}" - -tasks.register("copyTestNodeKeyMaterial", Copy) { - from project(':x-pack:plugin:core') - .files( - 'src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem', - 'src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt' - ) - into outputDir -} - -BuildParams.bwcVersions.withIndexCompatiple { bwcVersion, baseName -> - def baseCluster = testClusters.register(baseName) { - testDistribution = "DEFAULT" - versions = [bwcVersion.toString(), project.version] - numberOfNodes = 2 - setting 'path.repo', "${buildDir}/cluster/shared/repo/${baseName}" - user username: "test_user", password: "x-pack-test-password" - - setting 'path.repo', "${buildDir}/cluster/shared/repo/${baseName}" - // some tests rely on the translog not being flushed - setting 'indices.memory.shard_inactive_time', '60m' - setting 'xpack.security.enabled', 'true' - setting 'xpack.security.transport.ssl.enabled', 'true' - setting 'xpack.license.self_generated.type', 'trial' - - extraConfigFile 'testnode.pem', file("${outputDir}/testnode.pem") - extraConfigFile 'testnode.crt', file("${outputDir}/testnode.crt") - - keystore 'xpack.watcher.encryption_key', file("${project.projectDir}/src/test/resources/system_key") - setting 'xpack.watcher.encrypt_sensitive_data', 'true' - - setting 'xpack.security.transport.ssl.key', 'testnode.pem' - setting 'xpack.security.transport.ssl.certificate', 'testnode.crt' - keystore 'xpack.security.transport.ssl.secure_key_passphrase', 'testnode' - - if (bwcVersion.onOrAfter('6.7.0')) { - setting 'xpack.security.authc.api_key.enabled', 'true' - } - } - - tasks.register("${baseName}#oldClusterTest", StandaloneRestIntegTestTask) { - mustRunAfter("precommit") - useCluster baseCluster - dependsOn "copyTestNodeKeyMaterial" - doFirst { - delete("${buildDir}/cluster/shared/repo/${baseName}") - } - systemProperty 'tests.is_old_cluster', 'true' - exclude 'org/elasticsearch/upgrades/FullClusterRestartIT.class' - exclude 'org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.class' - exclude 'org/elasticsearch/upgrades/QueryBuilderBWCIT.class' - } - - tasks.register("${baseName}#upgradedClusterTest", StandaloneRestIntegTestTask) { - mustRunAfter("precommit") - useCluster baseCluster - dependsOn "${baseName}#oldClusterTest" - doFirst { - testClusters.named(baseName).get().goToNextVersion() - } - systemProperty 'tests.is_old_cluster', 'false' - exclude 'org/elasticsearch/upgrades/FullClusterRestartIT.class' - exclude 'org/elasticsearch/upgrades/FullClusterRestartSettingsUpgradeIT.class' - exclude 'org/elasticsearch/upgrades/QueryBuilderBWCIT.class' - } - - String oldVersion = bwcVersion.toString().minus("-SNAPSHOT") - tasks.matching { it.name.startsWith("${baseName}#") && it.name.endsWith("ClusterTest") }.configureEach { - it.systemProperty 'tests.old_cluster_version', oldVersion - it.systemProperty 'tests.path.repo', "${buildDir}/cluster/shared/repo/${baseName}" - it.nonInputProperties.systemProperty('tests.rest.cluster', baseCluster.map(c -> c.allHttpSocketURI.join(","))) - it.nonInputProperties.systemProperty('tests.clustername', baseName) - } - - tasks.register(bwcTaskName(bwcVersion)) { - dependsOn "${baseName}#upgradedClusterTest" +BuildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> + tasks.register(bwcTaskName(bwcVersion), StandaloneRestIntegTestTask) { + usesBwcDistribution(bwcVersion) + systemProperty("tests.old_cluster_version", bwcVersion) } } diff --git a/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/AbstractXpackFullClusterRestartTestCase.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/AbstractXpackFullClusterRestartTestCase.java new file mode 100644 index 0000000000000..1366d8c656f28 --- /dev/null +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/AbstractXpackFullClusterRestartTestCase.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.restart; + +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.FeatureFlag; +import org.elasticsearch.test.cluster.local.distribution.DistributionType; +import org.elasticsearch.test.cluster.util.resource.Resource; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; +import org.elasticsearch.upgrades.ParameterizedFullClusterRestartTestCase; +import org.junit.ClassRule; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public abstract class AbstractXpackFullClusterRestartTestCase extends ParameterizedFullClusterRestartTestCase { + + @ClassRule + public static ElasticsearchCluster cluster = ElasticsearchCluster.local() + .distribution(DistributionType.DEFAULT) + .version(getOldClusterTestVersion()) + .nodes(2) + .user("test_user", "x-pack-test-password") + // some tests rely on the translog not being flushed + .setting("indices.memory.shard_inactive_time", "60m") + .setting("xpack.security.enabled", "true") + .setting("xpack.security.transport.ssl.enabled", "true") + .setting("xpack.security.transport.ssl.key", "testnode.pem") + .setting("xpack.security.transport.ssl.certificate", "testnode.crt") + .setting("xpack.license.self_generated.type", "trial") + .setting("xpack.watcher.encrypt_sensitive_data", "true") + .settings(n -> { + if (n.getVersion().onOrAfter("6.7.0")) { + Map settings = new HashMap<>(); + settings.put("xpack.security.authc.api_key.enabled", "true"); + return settings; + } + return Collections.emptyMap(); + }) + .configFile("testnode.pem", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem")) + .configFile("testnode.crt", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .keystore("xpack.watcher.encryption_key", Resource.fromClasspath("system_key")) + .keystore("xpack.security.transport.ssl.secure_key_passphrase", "testnode") + .feature(FeatureFlag.TIME_SERIES_MODE) + .build(); + + public AbstractXpackFullClusterRestartTestCase(FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected ElasticsearchCluster getUpgradeCluster() { + return cluster; + } +} diff --git a/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java new file mode 100644 index 0000000000000..328304a5bd7d2 --- /dev/null +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.restart; + +import com.carrotsearch.randomizedtesting.annotations.Name; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.test.cluster.util.resource.Resource; +import org.elasticsearch.upgrades.FullClusterRestartIT; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class CoreFullClusterRestartIT extends FullClusterRestartIT { + + static { + clusterConfig = c -> c.setting("xpack.security.enabled", "true") + .setting("xpack.security.transport.ssl.enabled", "true") + .setting("xpack.security.transport.ssl.key", "testnode.pem") + .setting("xpack.security.transport.ssl.certificate", "testnode.crt") + .setting("xpack.license.self_generated.type", "trial") + .setting("xpack.watcher.encrypt_sensitive_data", "true") + .settings(n -> { + if (n.getVersion().onOrAfter("6.7.0")) { + Map settings = new HashMap<>(); + settings.put("xpack.security.authc.api_key.enabled", "true"); + return settings; + } + return Collections.emptyMap(); + }) + .configFile("testnode.pem", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem")) + .configFile("testnode.crt", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .keystore("xpack.watcher.encryption_key", Resource.fromClasspath("system_key")) + .keystore("xpack.security.transport.ssl.secure_key_passphrase", "testnode"); + } + + public CoreFullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected Settings restClientSettings() { + String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); + return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); + } + +} diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java similarity index 98% rename from x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java rename to x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java index e9f404afbc453..5a638b0be3d9e 100644 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java @@ -6,6 +6,8 @@ */ package org.elasticsearch.xpack.restart; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; @@ -27,7 +29,7 @@ import org.elasticsearch.rest.action.search.RestSearchAction; import org.elasticsearch.test.StreamsUtils; import org.elasticsearch.test.rest.ESRestTestCase; -import org.elasticsearch.upgrades.AbstractFullClusterRestartTestCase; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; import org.elasticsearch.xcontent.DeprecationHandler; import org.elasticsearch.xcontent.NamedXContentRegistry; import org.elasticsearch.xcontent.ObjectPath; @@ -67,7 +69,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.startsWith; -public class FullClusterRestartIT extends AbstractFullClusterRestartTestCase { +public class FullClusterRestartIT extends AbstractXpackFullClusterRestartTestCase { public static final String INDEX_ACTION_TYPES_DEPRECATION_MESSAGE = "[types removal] Specifying types in a watcher index action is deprecated."; @@ -85,6 +87,10 @@ public void setType() { type = getOldClusterVersion().before(Version.V_6_7_0) ? "doc" : "_doc"; } + public FullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + @Override protected Settings restClientSettings() { String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); @@ -125,17 +131,7 @@ public void testSecurityNativeRealm() throws Exception { } else { waitForYellow(".security"); final Request getSettingsRequest = new Request("GET", "/.security/_settings/index.format"); - RequestOptions.Builder systemIndexWarningOptions = RequestOptions.DEFAULT.toBuilder(); - systemIndexWarningOptions.setWarningsHandler(warnings -> { - if (warnings.isEmpty()) { - return false; - } else if (warnings.size() > 1) { - return true; - } else { - return warnings.get(0).contains("this request accesses system indices:") == false; - } - }); - getSettingsRequest.setOptions(systemIndexWarningOptions); + getSettingsRequest.setOptions(systemIndexWarningHandlerOptions()); Response settingsResponse = client().performRequest(getSettingsRequest); Map settingsResponseMap = entityAsMap(settingsResponse); logger.info("settings response map {}", settingsResponseMap); @@ -1074,7 +1070,7 @@ public void testDataStreams() throws Exception { assertEquals("ds", ds.get("name")); assertEquals(1, indices.size()); assertEquals(DataStream.getDefaultBackingIndexName("ds", 1, timestamp, getOldClusterVersion()), indices.get(0).get("index_name")); - assertNumHits("ds", 1, 1); + assertNumHits(isRunningAgainstOldCluster(), "ds", 1, 1); } private static void createComposableTemplate(RestClient client, String templateName, String indexPattern) throws IOException { @@ -1086,4 +1082,9 @@ private static void createComposableTemplate(RestClient client, String templateN createIndexTemplateRequest.setEntity(templateJSON); client.performRequest(createIndexTemplateRequest); } + + private RequestOptions.Builder systemIndexWarningHandlerOptions() { + return RequestOptions.DEFAULT.toBuilder() + .setWarningsHandler(w -> w.size() > 0 && w.get(0).contains("this request accesses system indices") == false); + } } diff --git a/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java new file mode 100644 index 0000000000000..bebe4d779314d --- /dev/null +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.restart; + +import com.carrotsearch.randomizedtesting.annotations.Name; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.test.cluster.util.resource.Resource; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class FullClusterRestartSettingsUpgradeIT extends org.elasticsearch.upgrades.FullClusterRestartSettingsUpgradeIT { + + static { + clusterConfig = c -> c.setting("xpack.security.enabled", "true") + .setting("xpack.security.transport.ssl.enabled", "true") + .setting("xpack.security.transport.ssl.key", "testnode.pem") + .setting("xpack.security.transport.ssl.certificate", "testnode.crt") + .setting("xpack.license.self_generated.type", "trial") + .setting("xpack.watcher.encrypt_sensitive_data", "true") + .settings(n -> { + if (n.getVersion().onOrAfter("6.7.0")) { + Map settings = new HashMap<>(); + settings.put("xpack.security.authc.api_key.enabled", "true"); + return settings; + } + return Collections.emptyMap(); + }) + .configFile("testnode.pem", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem")) + .configFile("testnode.crt", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .keystore("xpack.watcher.encryption_key", Resource.fromClasspath("system_key")) + .keystore("xpack.security.transport.ssl.secure_key_passphrase", "testnode"); + } + + public FullClusterRestartSettingsUpgradeIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected Settings restClientSettings() { + final String token = "Basic " + + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); + return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); + } + +} diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java similarity index 95% rename from x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java rename to x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java index d5b282940fba5..e771fa6657b9a 100644 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlConfigIndexMappingsFullClusterRestartIT.java @@ -6,6 +6,8 @@ */ package org.elasticsearch.xpack.restart; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.elasticsearch.Version; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; @@ -13,7 +15,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.xcontent.support.XContentMapValues; -import org.elasticsearch.upgrades.AbstractFullClusterRestartTestCase; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; import org.elasticsearch.xpack.test.rest.IndexMappingTemplateAsserter; import org.elasticsearch.xpack.test.rest.XPackRestTestConstants; import org.elasticsearch.xpack.test.rest.XPackRestTestHelper; @@ -30,11 +32,15 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -public class MlConfigIndexMappingsFullClusterRestartIT extends AbstractFullClusterRestartTestCase { +public class MlConfigIndexMappingsFullClusterRestartIT extends AbstractXpackFullClusterRestartTestCase { private static final String OLD_CLUSTER_JOB_ID = "ml-config-mappings-old-cluster-job"; private static final String NEW_CLUSTER_JOB_ID = "ml-config-mappings-new-cluster-job"; + public MlConfigIndexMappingsFullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + @Override protected Settings restClientSettings() { String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java similarity index 97% rename from x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java rename to x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java index fcec7d9342df6..e20f91ffcc99b 100644 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/MlMigrationFullClusterRestartIT.java @@ -6,6 +6,8 @@ */ package org.elasticsearch.xpack.restart; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.elasticsearch.Version; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; @@ -17,7 +19,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactories; import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; import org.elasticsearch.search.aggregations.metrics.MaxAggregationBuilder; -import org.elasticsearch.upgrades.AbstractFullClusterRestartTestCase; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; import org.elasticsearch.xpack.core.ml.MlTasks; import org.elasticsearch.xpack.core.ml.datafeed.DatafeedConfig; import org.elasticsearch.xpack.test.rest.XPackRestTestConstants; @@ -37,13 +39,17 @@ import static org.hamcrest.Matchers.emptyOrNullString; import static org.hamcrest.Matchers.is; -public class MlMigrationFullClusterRestartIT extends AbstractFullClusterRestartTestCase { +public class MlMigrationFullClusterRestartIT extends AbstractXpackFullClusterRestartTestCase { private static final String OLD_CLUSTER_OPEN_JOB_ID = "migration-old-cluster-open-job"; private static final String OLD_CLUSTER_STARTED_DATAFEED_ID = "migration-old-cluster-started-datafeed"; private static final String OLD_CLUSTER_CLOSED_JOB_ID = "migration-old-cluster-closed-job"; private static final String OLD_CLUSTER_STOPPED_DATAFEED_ID = "migration-old-cluster-stopped-datafeed"; + public MlMigrationFullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + @Override protected Settings restClientSettings() { String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); diff --git a/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java new file mode 100644 index 0000000000000..42c681b83363a --- /dev/null +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.restart; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.test.cluster.util.resource.Resource; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class QueryBuilderBWCIT extends org.elasticsearch.upgrades.QueryBuilderBWCIT { + + static { + clusterConfig = c -> c.setting("xpack.security.enabled", "true") + .setting("xpack.security.transport.ssl.enabled", "true") + .setting("xpack.security.transport.ssl.key", "testnode.pem") + .setting("xpack.security.transport.ssl.certificate", "testnode.crt") + .setting("xpack.license.self_generated.type", "trial") + .setting("xpack.watcher.encrypt_sensitive_data", "true") + .settings(n -> { + if (n.getVersion().onOrAfter("6.7.0")) { + Map settings = new HashMap<>(); + settings.put("xpack.security.authc.api_key.enabled", "true"); + return settings; + } + return Collections.emptyMap(); + }) + .configFile("testnode.pem", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem")) + .configFile("testnode.crt", Resource.fromClasspath("org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .keystore("xpack.watcher.encryption_key", Resource.fromClasspath("system_key")) + .keystore("xpack.security.transport.ssl.secure_key_passphrase", "testnode"); + } + + public QueryBuilderBWCIT(FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } + + @Override + protected Settings restClientSettings() { + String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); + return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); + } +} diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java similarity index 91% rename from x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java rename to x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java index 758d5f0b82b3a..46aaf079ec2fd 100644 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java +++ b/x-pack/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/xpack/restart/WatcherMappingUpdateIT.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.restart; +import com.carrotsearch.randomizedtesting.annotations.Name; + import org.apache.http.util.EntityUtils; import org.elasticsearch.Version; import org.elasticsearch.client.Request; @@ -14,7 +16,7 @@ import org.elasticsearch.client.Response; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.upgrades.AbstractFullClusterRestartTestCase; +import org.elasticsearch.upgrades.FullClusterRestartUpgradeStatus; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -23,7 +25,11 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; -public class WatcherMappingUpdateIT extends AbstractFullClusterRestartTestCase { +public class WatcherMappingUpdateIT extends AbstractXpackFullClusterRestartTestCase { + + public WatcherMappingUpdateIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) { + super(upgradeStatus); + } @Override protected Settings restClientSettings() { @@ -101,7 +107,7 @@ && getOldClusterVersion().onOrAfter(Version.V_6_7_0)) { private RequestOptions.Builder getWarningHandlerOptions(String index) { return RequestOptions.DEFAULT.toBuilder() - .setWarningsHandler(w -> w.contains(getWatcherSystemIndexWarning(index)) == false || w.size() != 1); + .setWarningsHandler(w -> w.size() > 0 && w.contains(getWatcherSystemIndexWarning(index)) == false); } private String getWatcherSystemIndexWarning(String index) { diff --git a/x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/funny-timeout-watch.json b/x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/funny-timeout-watch.json similarity index 100% rename from x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/funny-timeout-watch.json rename to x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/funny-timeout-watch.json diff --git a/x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/logging-watch.json b/x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/logging-watch.json similarity index 100% rename from x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/logging-watch.json rename to x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/logging-watch.json diff --git a/x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/simple-watch.json b/x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/simple-watch.json similarity index 100% rename from x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/simple-watch.json rename to x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/simple-watch.json diff --git a/x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/throttle-period-watch.json b/x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/throttle-period-watch.json similarity index 100% rename from x-pack/qa/full-cluster-restart/src/test/resources/org/elasticsearch/xpack/restart/throttle-period-watch.json rename to x-pack/qa/full-cluster-restart/src/javaRestTest/resources/org/elasticsearch/xpack/restart/throttle-period-watch.json diff --git a/x-pack/qa/full-cluster-restart/src/test/resources/system_key b/x-pack/qa/full-cluster-restart/src/javaRestTest/resources/system_key similarity index 100% rename from x-pack/qa/full-cluster-restart/src/test/resources/system_key rename to x-pack/qa/full-cluster-restart/src/javaRestTest/resources/system_key diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java deleted file mode 100644 index e06cb12f747a7..0000000000000 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/CoreFullClusterRestartIT.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package org.elasticsearch.xpack.restart; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.upgrades.FullClusterRestartIT; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; - -public class CoreFullClusterRestartIT extends FullClusterRestartIT { - - @Override - protected Settings restClientSettings() { - String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); - return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); - } - -} diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java b/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java deleted file mode 100644 index c5fa41daff2ad..0000000000000 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartSettingsUpgradeIT.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.restart; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; - -public class FullClusterRestartSettingsUpgradeIT extends org.elasticsearch.upgrades.FullClusterRestartSettingsUpgradeIT { - - @Override - protected Settings restClientSettings() { - final String token = "Basic " - + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); - return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); - } - -} diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java b/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java deleted file mode 100644 index cffc6881df645..0000000000000 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/QueryBuilderBWCIT.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package org.elasticsearch.xpack.restart; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; - -public class QueryBuilderBWCIT extends org.elasticsearch.upgrades.QueryBuilderBWCIT { - - @Override - protected Settings restClientSettings() { - String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); - return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); - } -}