[7.17] Add JUnit rule based integration test cluster orchestration framework… (#92517)

This commit adds a new test framework for configuring and orchestrating
test clusters for both Java and YAML REST testing. This will eventually
replace the existing "test-clusters" Gradle plugin and the build-time
cluster orchestration.
This commit is contained in:
Mark Vieira 2022-12-22 17:48:07 -08:00 committed by GitHub
parent 91724a6f0e
commit 47c6fd34da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
220 changed files with 4003 additions and 248 deletions

View file

@ -116,6 +116,10 @@ gradlePlugin {
id = 'elasticsearch.java' id = 'elasticsearch.java'
implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin' implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin'
} }
legacyInternalJavaRestTest {
id = 'elasticsearch.legacy-java-rest-test'
implementationClass = 'org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin'
}
internalJavaRestTest { internalJavaRestTest {
id = 'elasticsearch.internal-java-rest-test' id = 'elasticsearch.internal-java-rest-test'
implementationClass = 'org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin' implementationClass = 'org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin'
@ -164,6 +168,10 @@ gradlePlugin {
id = 'elasticsearch.validate-rest-spec' id = 'elasticsearch.validate-rest-spec'
implementationClass = 'org.elasticsearch.gradle.internal.precommit.ValidateRestSpecPlugin' implementationClass = 'org.elasticsearch.gradle.internal.precommit.ValidateRestSpecPlugin'
} }
legacyYamlRestTest {
id = 'elasticsearch.legacy-yaml-rest-test'
implementationClass = 'org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin'
}
yamlRestTest { yamlRestTest {
id = 'elasticsearch.internal-yaml-rest-test' id = 'elasticsearch.internal-yaml-rest-test'
implementationClass = 'org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin' implementationClass = 'org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin'

View file

@ -13,6 +13,7 @@ abstract class AbstractRestResourcesFuncTest extends AbstractGradleFuncTest {
def setup() { def setup() {
subProject(":test:framework") << "apply plugin: 'elasticsearch.java'" subProject(":test:framework") << "apply plugin: 'elasticsearch.java'"
subProject(":test:test-clusters") << "apply plugin: 'elasticsearch.java'"
subProject(":rest-api-spec") << """ subProject(":rest-api-spec") << """
configurations { restSpecs\nrestTests } configurations { restSpecs\nrestTests }
artifacts { artifacts {

View file

@ -195,7 +195,7 @@ class TestingConventionsPrecommitPluginFuncTest extends AbstractGradlePrecommitP
given: given:
clazz(dir('src/yamlRestTest/java'), "org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase") clazz(dir('src/yamlRestTest/java'), "org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase")
buildFile << """ buildFile << """
apply plugin:'elasticsearch.internal-yaml-rest-test' apply plugin:'elasticsearch.legacy-yaml-rest-test'
dependencies { dependencies {
yamlRestTestImplementation "org.apache.lucene:tests.util:1.0" yamlRestTestImplementation "org.apache.lucene:tests.util:1.0"
@ -274,7 +274,7 @@ class TestingConventionsPrecommitPluginFuncTest extends AbstractGradlePrecommitP
where: where:
pluginName | taskName | sourceSetName pluginName | taskName | sourceSetName
"elasticsearch.internal-java-rest-test" | ":javaRestTestTestingConventions" | "javaRestTest" "elasticsearch.legacy-java-rest-test" | ":javaRestTestTestingConventions" | "javaRestTest"
"elasticsearch.internal-cluster-test" | ":internalClusterTestTestingConventions" | "internalClusterTest" "elasticsearch.internal-cluster-test" | ":internalClusterTestTestingConventions" | "internalClusterTest"
} }

View file

@ -19,7 +19,7 @@ class InternalYamlRestTestPluginFuncTest extends AbstractRestResourcesFuncTest {
configurationCacheCompatible = false configurationCacheCompatible = false
buildFile << """ buildFile << """
plugins { plugins {
id 'elasticsearch.internal-yaml-rest-test' id 'elasticsearch.legacy-yaml-rest-test'
} }
""" """
@ -38,7 +38,7 @@ class InternalYamlRestTestPluginFuncTest extends AbstractRestResourcesFuncTest {
configurationCacheCompatible = false configurationCacheCompatible = false
internalBuild() internalBuild()
buildFile << """ buildFile << """
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
dependencies { dependencies {
yamlRestTestImplementation "junit:junit:4.12" yamlRestTestImplementation "junit:junit:4.12"

View file

@ -25,10 +25,15 @@ if (buildNumber) {
include("**/*.hprof") include("**/*.hprof")
include("**/build/test-results/**/*.xml") include("**/build/test-results/**/*.xml")
include("**/build/testclusters/**") include("**/build/testclusters/**")
include("**/build/testrun/**")
exclude("**/build/testclusters/**/data/**") exclude("**/build/testclusters/**/data/**")
exclude("**/build/testclusters/**/distro/**") exclude("**/build/testclusters/**/distro/**")
exclude("**/build/testclusters/**/repo/**") exclude("**/build/testclusters/**/repo/**")
exclude("**/build/testclusters/**/extract/**") exclude("**/build/testclusters/**/extract/**")
exclude("**/build/testrun/**/data/**")
exclude("**/build/testrun/**/distro/**")
exclude("**/build/testrun/**/repo/**")
exclude("**/build/testrun/**/extract/**")
} }
.files .files
.findAll { Files.isRegularFile(it.toPath()) } .findAll { Files.isRegularFile(it.toPath()) }

View file

@ -10,20 +10,13 @@ import org.elasticsearch.gradle.Architecture
import org.elasticsearch.gradle.OS import org.elasticsearch.gradle.OS
import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.rest.RestTestBasePlugin
import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask
// gradle has an open issue of failing applying plugins in // gradle has an open issue of failing applying plugins in
// precompiled script plugins (see https://github.com/gradle/gradle/issues/17004) // precompiled script plugins (see https://github.com/gradle/gradle/issues/17004)
// apply plugin: 'elasticsearch.jdk-download' // apply plugin: 'elasticsearch.jdk-download'
if (BuildParams.getIsRuntimeJavaHomeSet()) {
configure(allprojects) {
project.tasks.withType(Test).configureEach { Test test ->
if (BuildParams.getIsRuntimeJavaHomeSet()) {
test.executable = "${BuildParams.runtimeJavaHome}/bin/java"
}
}
}
} else {
jdks { jdks {
provisioned_runtime { provisioned_runtime {
vendor = VersionProperties.bundledJdkVendor vendor = VersionProperties.bundledJdkVendor
@ -35,9 +28,23 @@ if (BuildParams.getIsRuntimeJavaHomeSet()) {
configure(allprojects) { configure(allprojects) {
project.tasks.withType(Test).configureEach { Test test -> project.tasks.withType(Test).configureEach { Test test ->
if (BuildParams.getIsRuntimeJavaHomeSet()) {
test.executable = "${BuildParams.runtimeJavaHome}/bin/java"
} else {
test.dependsOn(rootProject.jdks.provisioned_runtime) test.dependsOn(rootProject.jdks.provisioned_runtime)
test.executable = rootProject.jdks.provisioned_runtime.getBinJavaPath() test.executable = rootProject.jdks.provisioned_runtime.getBinJavaPath()
} }
} }
project.plugins.withType(RestTestBasePlugin) {
// Use later JDK for new REST test plugins since :test:test-clusters requires Java 17+
// The clusters under test still use the configured runtime java home
project.tasks.withType(StandaloneRestIntegTestTask).configureEach { StandaloneRestIntegTestTask test ->
test.dependsOn(rootProject.jdks.provisioned_runtime)
test.executable = rootProject.jdks.provisioned_runtime.getBinJavaPath()
// Pass actual runtime java version used for clusters under test
test.systemProperty("tests.runtime.java.version", BuildParams.runtimeJavaVersion)
} }
}
}
// if neither condition above is executed, tests will use the gradle jvm // if neither condition above is executed, tests will use the gradle jvm

View file

@ -25,7 +25,7 @@ class DocsTestPlugin implements Plugin<Project> {
@Override @Override
void apply(Project project) { void apply(Project project) {
project.pluginManager.apply('elasticsearch.internal-yaml-rest-test') project.pluginManager.apply('elasticsearch.legacy-yaml-rest-test')
String distribution = System.getProperty('tests.distribution', 'default') String distribution = System.getProperty('tests.distribution', 'default')
// The distribution can be configured with -Dtests.distribution on the command line // The distribution can be configured with -Dtests.distribution on the command line

View file

@ -11,7 +11,8 @@ package org.elasticsearch.gradle.internal.precommit;
import org.elasticsearch.gradle.internal.conventions.precommit.PrecommitPlugin; import org.elasticsearch.gradle.internal.conventions.precommit.PrecommitPlugin;
import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin; import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
import org.gradle.api.Action; import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project; import org.gradle.api.Project;
@ -43,8 +44,8 @@ public class TestingConventionsPrecommitPlugin extends PrecommitPlugin {
}); });
}); });
project.getPlugins().withType(InternalYamlRestTestPlugin.class, yamlRestTestPlugin -> { project.getPlugins().withType(LegacyYamlRestTestPlugin.class, yamlRestTestPlugin -> {
NamedDomainObjectProvider<SourceSet> sourceSet = sourceSets.named(InternalYamlRestTestPlugin.SOURCE_SET_NAME); NamedDomainObjectProvider<SourceSet> sourceSet = sourceSets.named(LegacyYamlRestTestPlugin.SOURCE_SET_NAME);
setupTaskForSourceSet(project, sourceSet, t -> { setupTaskForSourceSet(project, sourceSet, t -> {
t.getSuffixes().convention(List.of("IT")); t.getSuffixes().convention(List.of("IT"));
t.getBaseClasses().convention(List.of("org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase")); t.getBaseClasses().convention(List.of("org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase"));
@ -68,8 +69,17 @@ public class TestingConventionsPrecommitPlugin extends PrecommitPlugin {
}); });
}); });
project.getPlugins().withType(LegacyJavaRestTestPlugin.class, javaRestTestPlugin -> {
NamedDomainObjectProvider<SourceSet> sourceSet = sourceSets.named(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
setupTaskForSourceSet(project, sourceSet, t -> {
t.getSuffixes().convention(List.of("IT"));
t.getBaseClasses()
.convention(List.of("org.elasticsearch.test.ESIntegTestCase", "org.elasticsearch.test.rest.ESRestTestCase"));
});
});
project.getPlugins().withType(InternalJavaRestTestPlugin.class, javaRestTestPlugin -> { project.getPlugins().withType(InternalJavaRestTestPlugin.class, javaRestTestPlugin -> {
NamedDomainObjectProvider<SourceSet> sourceSet = sourceSets.named(InternalJavaRestTestPlugin.SOURCE_SET_NAME); NamedDomainObjectProvider<SourceSet> sourceSet = sourceSets.named(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
setupTaskForSourceSet(project, sourceSet, t -> { setupTaskForSourceSet(project, sourceSet, t -> {
t.getSuffixes().convention(List.of("IT")); t.getSuffixes().convention(List.of("IT"));
t.getBaseClasses() t.getBaseClasses()

View file

@ -29,14 +29,18 @@ import org.gradle.api.tasks.bundling.Zip;
import javax.inject.Inject; import javax.inject.Inject;
public class RestTestBasePlugin implements Plugin<Project> { /**
* @deprecated use {@link RestTestBasePlugin} instead
*/
@Deprecated
public class LegacyRestTestBasePlugin implements Plugin<Project> {
private static final String TESTS_REST_CLUSTER = "tests.rest.cluster"; private static final String TESTS_REST_CLUSTER = "tests.rest.cluster";
private static final String TESTS_CLUSTER = "tests.cluster"; private static final String TESTS_CLUSTER = "tests.cluster";
private static final String TESTS_CLUSTER_NAME = "tests.clustername"; private static final String TESTS_CLUSTER_NAME = "tests.clustername";
private ProviderFactory providerFactory; private ProviderFactory providerFactory;
@Inject @Inject
public RestTestBasePlugin(ProviderFactory providerFactory) { public LegacyRestTestBasePlugin(ProviderFactory providerFactory) {
this.providerFactory = providerFactory; this.providerFactory = providerFactory;
} }
@ -82,7 +86,8 @@ public class RestTestBasePlugin implements Plugin<Project> {
.withType(StandaloneRestIntegTestTask.class) .withType(StandaloneRestIntegTestTask.class)
.configureEach(t -> t.finalizedBy(project.getTasks().withType(FixtureStop.class))); .configureEach(t -> t.finalizedBy(project.getTasks().withType(FixtureStop.class)));
project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(t -> project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(t -> {
t.setMaxParallelForks(1);
// if this a module or plugin, it may have an associated zip file with it's contents, add that to the test cluster // if this a module or plugin, it may have an associated zip file with it's contents, add that to the test cluster
project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> { project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> {
TaskProvider<Zip> bundle = project.getTasks().withType(Zip.class).named("bundlePlugin"); TaskProvider<Zip> bundle = project.getTasks().withType(Zip.class).named("bundlePlugin");
@ -93,7 +98,8 @@ public class RestTestBasePlugin implements Plugin<Project> {
t.getClusters().forEach(c -> c.plugin(bundle.flatMap(AbstractArchiveTask::getArchiveFile))); t.getClusters().forEach(c -> c.plugin(bundle.flatMap(AbstractArchiveTask::getArchiveFile)));
} }
})); });
});
} }
private String systemProperty(String propName) { private String systemProperty(String propName) {

View file

@ -11,8 +11,8 @@ package org.elasticsearch.gradle.internal.test;
import org.elasticsearch.gradle.internal.ExportElasticsearchBuildResourcesTask; import org.elasticsearch.gradle.internal.ExportElasticsearchBuildResourcesTask;
import org.elasticsearch.gradle.internal.info.GlobalBuildInfoPlugin; import org.elasticsearch.gradle.internal.info.GlobalBuildInfoPlugin;
import org.elasticsearch.gradle.internal.precommit.InternalPrecommitTasks; import org.elasticsearch.gradle.internal.precommit.InternalPrecommitTasks;
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.RestTestUtil; import org.elasticsearch.gradle.internal.test.rest.RestTestUtil;
import org.gradle.api.InvalidUserDataException; import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
@ -32,8 +32,8 @@ import java.util.Map;
* and run REST tests. Use BuildPlugin if you want to build main code as well * and run REST tests. Use BuildPlugin if you want to build main code as well
* as tests. * as tests.
* *
* @deprecated use {@link InternalClusterTestPlugin}, {@link InternalJavaRestTestPlugin} or * @deprecated use {@link InternalClusterTestPlugin}, {@link LegacyJavaRestTestPlugin} or
* {@link InternalYamlRestTestPlugin} instead. * {@link LegacyYamlRestTestPlugin} instead.
*/ */
@Deprecated @Deprecated
public class StandaloneRestTestPlugin implements Plugin<Project> { public class StandaloneRestTestPlugin implements Plugin<Project> {
@ -46,7 +46,7 @@ public class StandaloneRestTestPlugin implements Plugin<Project> {
} }
project.getRootProject().getPluginManager().apply(GlobalBuildInfoPlugin.class); project.getRootProject().getPluginManager().apply(GlobalBuildInfoPlugin.class);
project.getPluginManager().apply(RestTestBasePlugin.class); project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
project.getTasks().register("buildResources", ExportElasticsearchBuildResourcesTask.class); project.getTasks().register("buildResources", ExportElasticsearchBuildResourcesTask.class);

View file

@ -10,6 +10,7 @@ package org.elasticsearch.gradle.internal.test;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
import org.elasticsearch.gradle.plugin.PluginBuildPlugin; import org.elasticsearch.gradle.plugin.PluginBuildPlugin;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
@ -48,6 +49,11 @@ public class TestWithDependenciesPlugin implements Plugin<Project> {
return; return;
} }
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets(); SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets();
project.getPlugins()
.withType(
LegacyJavaRestTestPlugin.class,
legacyJavaRestTestPlugin -> processConfiguration(sourceSets.getByName(LegacyJavaRestTestPlugin.SOURCE_SET_NAME))
);
project.getPlugins() project.getPlugins()
.withType( .withType(
InternalJavaRestTestPlugin.class, InternalJavaRestTestPlugin.class,

View file

@ -14,7 +14,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams;
import org.elasticsearch.gradle.internal.precommit.FilePermissionsPrecommitPlugin; import org.elasticsearch.gradle.internal.precommit.FilePermissionsPrecommitPlugin;
import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsPrecommitPlugin; import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsPrecommitPlugin;
import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsTask; import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsTask;
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin; import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
import org.elasticsearch.gradle.testclusters.ElasticsearchCluster; import org.elasticsearch.gradle.testclusters.ElasticsearchCluster;
import org.elasticsearch.gradle.testclusters.TestClustersAware; import org.elasticsearch.gradle.testclusters.TestClustersAware;
import org.elasticsearch.gradle.testclusters.TestClustersPlugin; import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
@ -62,8 +62,8 @@ public class TestWithSslPlugin implements Plugin<Project> {
.withType(RestIntegTestTask.class) .withType(RestIntegTestTask.class)
.configureEach(runner -> runner.systemProperty("tests.ssl.enabled", "true")); .configureEach(runner -> runner.systemProperty("tests.ssl.enabled", "true"));
}); });
project.getPlugins().withType(InternalJavaRestTestPlugin.class).configureEach(restTestPlugin -> { project.getPlugins().withType(LegacyJavaRestTestPlugin.class).configureEach(restTestPlugin -> {
SourceSet testSourceSet = Util.getJavaSourceSets(project).getByName(InternalJavaRestTestPlugin.SOURCE_SET_NAME); SourceSet testSourceSet = Util.getJavaSourceSets(project).getByName(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
testSourceSet.getResources().srcDir(new File(keyStoreDir, "test/ssl")); testSourceSet.getResources().srcDir(new File(keyStoreDir, "test/ssl"));
project.getTasks().named(testSourceSet.getProcessResourcesTaskName()).configure(t -> t.dependsOn(exportKeyStore)); project.getTasks().named(testSourceSet.getProcessResourcesTaskName()).configure(t -> t.dependsOn(exportKeyStore));
project.getTasks().withType(TestClustersAware.class).configureEach(clusterAware -> clusterAware.dependsOn(exportKeyStore)); project.getTasks().withType(TestClustersAware.class).configureEach(clusterAware -> clusterAware.dependsOn(exportKeyStore));

View file

@ -8,7 +8,7 @@
package org.elasticsearch.gradle.internal.test.rest; package org.elasticsearch.gradle.internal.test.rest;
import org.elasticsearch.gradle.internal.test.RestTestBasePlugin; import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
import org.elasticsearch.gradle.util.GradleUtils; import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
@ -33,8 +33,11 @@ public class InternalJavaRestTestPlugin implements Plugin<Project> {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet javaTestSourceSet = sourceSets.create(SOURCE_SET_NAME); SourceSet javaTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
project.getDependencies().add(javaTestSourceSet.getImplementationConfigurationName(), project.project(":test:test-clusters"));
// setup the javaRestTest task // setup the javaRestTest task
registerTestTask(project, javaTestSourceSet); // we use a StandloneRestIntegTestTask here so that the conventions of RestTestBasePlugin don't create a test cluster
registerTestTask(project, javaTestSourceSet, SOURCE_SET_NAME, StandaloneRestIntegTestTask.class);
// setup dependencies // setup dependencies
setupJavaRestTestDependenciesDefaults(project, javaTestSourceSet); setupJavaRestTestDependenciesDefaults(project, javaTestSourceSet);

View file

@ -8,7 +8,7 @@
package org.elasticsearch.gradle.internal.test.rest; package org.elasticsearch.gradle.internal.test.rest;
import org.elasticsearch.gradle.internal.test.RestTestBasePlugin; import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
import org.elasticsearch.gradle.util.GradleUtils; import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
@ -34,10 +34,10 @@ public class InternalYamlRestTestPlugin implements Plugin<Project> {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlTestSourceSet = sourceSets.create(SOURCE_SET_NAME); SourceSet yamlTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
registerTestTask(project, yamlTestSourceSet); registerTestTask(project, yamlTestSourceSet, SOURCE_SET_NAME, StandaloneRestIntegTestTask.class);
// setup the dependencies // setup the dependencies
setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet); setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet, true);
// setup the copy for the rest resources // setup the copy for the rest resources
project.getTasks().withType(CopyRestApiTask.class).configureEach(copyRestApiTask -> { project.getTasks().withType(CopyRestApiTask.class).configureEach(copyRestApiTask -> {

View file

@ -0,0 +1,48 @@
/*
* 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.gradle.internal.test.rest;
import org.elasticsearch.gradle.internal.test.LegacyRestTestBasePlugin;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.registerTestTask;
import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupJavaRestTestDependenciesDefaults;
/**
* Apply this plugin to run the Java based REST tests.
*
* @deprecated use {@link InternalJavaRestTestPlugin}
*/
@Deprecated
public class LegacyJavaRestTestPlugin implements Plugin<Project> {
public static final String SOURCE_SET_NAME = "javaRestTest";
@Override
public void apply(Project project) {
project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
// create source set
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet javaTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
// setup the javaRestTest task
registerTestTask(project, javaTestSourceSet);
// setup dependencies
setupJavaRestTestDependenciesDefaults(project, javaTestSourceSet);
// setup IDE
GradleUtils.setupIdeForTestSourceSet(project, javaTestSourceSet);
}
}

View file

@ -0,0 +1,76 @@
/*
* 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.gradle.internal.test.rest;
import org.elasticsearch.gradle.internal.test.LegacyRestTestBasePlugin;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.registerTestTask;
import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupYamlRestTestDependenciesDefaults;
/**
* Apply this plugin to run the YAML based REST tests.
*
* @deprecated use {@link InternalYamlRestTestPlugin}
*/
@Deprecated
public class LegacyYamlRestTestPlugin implements Plugin<Project> {
public static final String SOURCE_SET_NAME = "yamlRestTest";
@Override
public void apply(Project project) {
project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
project.getPluginManager().apply(RestResourcesPlugin.class);
// create source set
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
registerTestTask(project, yamlTestSourceSet);
// setup the dependencies
setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet);
// setup the copy for the rest resources
project.getTasks().withType(CopyRestApiTask.class).configureEach(copyRestApiTask -> {
copyRestApiTask.setSourceResourceDir(
yamlTestSourceSet.getResources()
.getSrcDirs()
.stream()
.filter(f -> f.isDirectory() && f.getName().equals("resources"))
.findFirst()
.orElse(null)
);
});
// Register rest resources with source set
yamlTestSourceSet.getOutput()
.dir(
project.getTasks()
.withType(CopyRestApiTask.class)
.named(RestResourcesPlugin.COPY_REST_API_SPECS_TASK)
.flatMap(CopyRestApiTask::getOutputResourceDir)
);
yamlTestSourceSet.getOutput()
.dir(
project.getTasks()
.withType(CopyRestTestsTask.class)
.named(RestResourcesPlugin.COPY_YAML_TESTS_TASK)
.flatMap(CopyRestTestsTask::getOutputResourceDir)
);
GradleUtils.setupIdeForTestSourceSet(project, yamlTestSourceSet);
}
}

View file

@ -0,0 +1,241 @@
/*
* 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.gradle.internal.test.rest;
import groovy.lang.Closure;
import org.elasticsearch.gradle.Architecture;
import org.elasticsearch.gradle.DistributionDownloadPlugin;
import org.elasticsearch.gradle.ElasticsearchDistribution;
import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes;
import org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin;
import org.elasticsearch.gradle.internal.InternalDistributionDownloadPlugin;
import org.elasticsearch.gradle.internal.info.BuildParams;
import org.elasticsearch.gradle.plugin.PluginBuildPlugin;
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension;
import org.elasticsearch.gradle.test.SystemPropertyCommandLineArgumentProvider;
import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
import org.elasticsearch.gradle.transform.UnzipTransform;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
import org.gradle.api.file.FileTree;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.tasks.ClasspathNormalizer;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.util.PatternFilterable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import javax.inject.Inject;
/**
* Base plugin used for wiring up build tasks to REST testing tasks using new JUnit rule-based test clusters framework.
*/
public class RestTestBasePlugin implements Plugin<Project> {
private static final String TESTS_RUNTIME_JAVA_SYSPROP = "tests.runtime.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 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";
private static final String INTEG_TEST_REST_INTEG_TEST_DISTRO = "integ_test_distro";
private static final String MODULES_CONFIGURATION = "clusterModules";
private static final String PLUGINS_CONFIGURATION = "clusterPlugins";
private static final String EXTRACTED_PLUGINS_CONFIGURATION = "extractedPlugins";
private final ProviderFactory providerFactory;
@Inject
public RestTestBasePlugin(ProviderFactory providerFactory) {
this.providerFactory = providerFactory;
}
@Override
public void apply(Project project) {
project.getPluginManager().apply(ElasticsearchJavaPlugin.class);
project.getPluginManager().apply(InternalDistributionDownloadPlugin.class);
// Register integ-test and default distributions
NamedDomainObjectContainer<ElasticsearchDistribution> 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);
});
// Create configures for module and plugin dependencies
Configuration modulesConfiguration = createPluginConfiguration(project, MODULES_CONFIGURATION, true);
Configuration pluginsConfiguration = createPluginConfiguration(project, PLUGINS_CONFIGURATION, false);
Configuration extractedPluginsConfiguration = createPluginConfiguration(project, EXTRACTED_PLUGINS_CONFIGURATION, true);
extractedPluginsConfiguration.extendsFrom(pluginsConfiguration);
configureArtifactTransforms(project);
// For plugin and module projects, register the current project plugin bundle as a dependency
project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> {
if (GradleUtils.isModuleProject(project.getPath())) {
project.getDependencies().add(modulesConfiguration.getName(), project.files(project.getTasks().named("bundlePlugin")));
} else {
project.getDependencies().add(pluginsConfiguration.getName(), project.files(project.getTasks().named("bundlePlugin")));
}
});
project.getTasks().withType(StandaloneRestIntegTestTask.class, task -> {
SystemPropertyCommandLineArgumentProvider nonInputSystemProperties = task.getExtensions()
.getByType(SystemPropertyCommandLineArgumentProvider.class);
task.dependsOn(integTestDistro, modulesConfiguration);
registerDistributionInputs(task, integTestDistro);
task.setMaxParallelForks(task.getProject().getGradle().getStartParameter().getMaxWorkerCount() / 2);
// Disable the security manager and syscall filter since the test framework needs to fork processes
task.systemProperty("tests.security.manager", "false");
task.systemProperty("tests.system_call_filter", "false");
// Register plugins and modules as task inputs and pass paths as system properties to tests
nonInputSystemProperties.systemProperty(TESTS_CLUSTER_MODULES_PATH_SYSPROP, modulesConfiguration::getAsPath);
registerConfigurationInputs(task, modulesConfiguration);
nonInputSystemProperties.systemProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP, pluginsConfiguration::getAsPath);
registerConfigurationInputs(task, extractedPluginsConfiguration);
// Wire up integ-test distribution by default for all test tasks
nonInputSystemProperties.systemProperty(
INTEG_TEST_DISTRIBUTION_SYSPROP,
() -> integTestDistro.getExtracted().getSingleFile().getPath()
);
nonInputSystemProperties.systemProperty(TESTS_RUNTIME_JAVA_SYSPROP, BuildParams.getRuntimeJavaHome());
// Add `usesDefaultDistribution()` extension method to test tasks to indicate they require the default distro
task.getExtensions().getExtraProperties().set("usesDefaultDistribution", new Closure<Void>(task) {
@Override
public Void call(Object... args) {
task.dependsOn(defaultDistro);
registerDistributionInputs(task, defaultDistro);
nonInputSystemProperties.systemProperty(
DEFAULT_DISTRIBUTION_SYSPROP,
providerFactory.provider(() -> defaultDistro.getExtracted().getSingleFile().getPath())
);
return null;
}
});
});
project.getTasks()
.named(JavaBasePlugin.CHECK_TASK_NAME)
.configure(check -> check.dependsOn(project.getTasks().withType(StandaloneRestIntegTestTask.class)));
}
private FileTree getDistributionFiles(ElasticsearchDistribution distribution, Action<PatternFilterable> patternFilter) {
return distribution.getExtracted().getAsFileTree().matching(patternFilter);
}
private void registerConfigurationInputs(Task task, Configuration configuration) {
task.getInputs()
.files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar"))))
.withPropertyName(configuration.getName() + "-classpath")
.withNormalizer(ClasspathNormalizer.class);
task.getInputs()
.files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar") == false)))
.withPropertyName(configuration.getName() + "-files")
.withPathSensitivity(PathSensitivity.RELATIVE);
}
private void registerDistributionInputs(Task task, ElasticsearchDistribution distribution) {
task.getInputs()
.files(providerFactory.provider(() -> getDistributionFiles(distribution, filter -> filter.exclude("**/*.jar"))))
.withPropertyName(distribution.getName() + "-files")
.withPathSensitivity(PathSensitivity.RELATIVE);
task.getInputs()
.files(providerFactory.provider(() -> getDistributionFiles(distribution, filter -> filter.include("**/*.jar"))))
.withPropertyName(distribution.getName() + "-classpath")
.withNormalizer(ClasspathNormalizer.class);
}
private Optional<String> findModulePath(Project project, String pluginName) {
return project.getRootProject()
.getAllprojects()
.stream()
.filter(p -> GradleUtils.isModuleProject(p.getPath()))
.filter(p -> p.getPlugins().hasPlugin(PluginBuildPlugin.class))
.filter(p -> p.getExtensions().getByType(PluginPropertiesExtension.class).getName().equals(pluginName))
.findFirst()
.map(Project::getPath);
}
private Configuration createPluginConfiguration(Project project, String name, boolean useExploded) {
return project.getConfigurations().create(name, c -> {
if (useExploded) {
c.attributes(a -> a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE));
} else {
c.attributes(a -> a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.ZIP_TYPE));
}
c.withDependencies(dependencies -> {
// Add dependencies of any modules
Collection<Dependency> additionalDependencies = new HashSet<>();
for (Iterator<Dependency> iterator = dependencies.iterator(); iterator.hasNext();) {
Dependency dependency = iterator.next();
if (dependency instanceof ProjectDependency projectDependency) {
Project dependencyProject = projectDependency.getDependencyProject();
List<String> extendedPlugins = dependencyProject.getExtensions()
.getByType(PluginPropertiesExtension.class)
.getExtendedPlugins();
// Replace project dependency with task artifact dependency so the unzip artifact transform will work
iterator.remove();
additionalDependencies.add(
project.getDependencies().create(project.files(dependencyProject.getTasks().named("bundlePlugin")))
);
for (String extendedPlugin : extendedPlugins) {
findModulePath(project, extendedPlugin).ifPresent(
modulePath -> additionalDependencies.add(
project.getDependencies()
.create(project.files(project.findProject(modulePath).getTasks().named("bundlePlugin")))
)
);
}
}
}
dependencies.addAll(additionalDependencies);
});
});
}
private void configureArtifactTransforms(Project project) {
project.getDependencies().registerTransform(UnzipTransform.class, transformSpec -> {
transformSpec.getFrom().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.ZIP_TYPE);
transformSpec.getTo().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE);
transformSpec.getParameters().setAsFiletreeOutput(false);
});
}
}

View file

@ -14,6 +14,7 @@ import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.testing.Test;
/** /**
* Utility class to configure the necessary tasks and dependencies. * Utility class to configure the necessary tasks and dependencies.
@ -42,8 +43,17 @@ public class RestTestUtil {
* Creates a {@link RestIntegTestTask} task with a custom name for the provided source set * Creates a {@link RestIntegTestTask} task with a custom name for the provided source set
*/ */
public static TaskProvider<RestIntegTestTask> registerTestTask(Project project, SourceSet sourceSet, String taskName) { public static TaskProvider<RestIntegTestTask> registerTestTask(Project project, SourceSet sourceSet, String taskName) {
return registerTestTask(project, sourceSet, taskName, RestIntegTestTask.class);
}
/**
* Creates a {@link T} task with a custom name for the provided source set
*
* @param <T> test task type
*/
public static <T extends Test> TaskProvider<T> registerTestTask(Project project, SourceSet sourceSet, String taskName, Class<T> clazz) {
// lazily create the test task // lazily create the test task
return project.getTasks().register(sourceSet.getName(), RestIntegTestTask.class, testTask -> { return project.getTasks().register(taskName, clazz, testTask -> {
testTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP); testTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
testTask.setDescription("Runs the REST tests against an external cluster"); testTask.setDescription("Runs the REST tests against an external cluster");
project.getPlugins().withType(JavaPlugin.class, t -> testTask.mustRunAfter(project.getTasks().named("test"))); project.getPlugins().withType(JavaPlugin.class, t -> testTask.mustRunAfter(project.getTasks().named("test")));
@ -61,10 +71,17 @@ public class RestTestUtil {
} }
public static void setupYamlRestTestDependenciesDefaults(Project project, SourceSet sourceSet) { public static void setupYamlRestTestDependenciesDefaults(Project project, SourceSet sourceSet) {
setupYamlRestTestDependenciesDefaults(project, sourceSet, false);
}
public static void setupYamlRestTestDependenciesDefaults(Project project, SourceSet sourceSet, boolean useNewTestClusters) {
Project testFramework = project.findProject(":test:framework"); Project testFramework = project.findProject(":test:framework");
// we shield the project dependency to make integration tests easier // we shield the project dependency to make integration tests easier
if (testFramework != null) { if (testFramework != null) {
project.getDependencies().add(sourceSet.getImplementationConfigurationName(), testFramework); project.getDependencies().add(sourceSet.getImplementationConfigurationName(), testFramework);
if (useNewTestClusters) {
project.getDependencies().add(sourceSet.getImplementationConfigurationName(), project.project(":test:test-clusters"));
}
} }
} }

View file

@ -57,6 +57,8 @@ public class Reaper implements Closeable {
try (Reaper reaper = new Reaper(inputDir)) { try (Reaper reaper = new Reaper(inputDir)) {
System.in.read(); System.in.read();
reaper.reap(); reaper.reap();
} catch (Throwable t) {
logFailure("Unexpected error occurred", t);
} }
} }
@ -89,7 +91,7 @@ public class Reaper implements Closeable {
} }
} }
private void logFailure(String message, Throwable e) { private static void logFailure(String message, Throwable e) {
System.err.println(message); System.err.println(message);
if (e != null) { if (e != null) {
e.printStackTrace(System.err); e.printStackTrace(System.err);

View file

@ -69,11 +69,6 @@ public class StandaloneRestIntegTestTask extends Test implements TestClustersAwa
this.debugServer = enabled; this.debugServer = enabled;
} }
@Override
public int getMaxParallelForks() {
return 1;
}
@Nested @Nested
@Override @Override
public Collection<ElasticsearchCluster> getClusters() { public Collection<ElasticsearchCluster> getClusters() {

View file

@ -9,7 +9,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.build' apply plugin: 'elasticsearch.build'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.publish' apply plugin: 'elasticsearch.publish'
apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.rest-resources'

View file

@ -8,7 +8,7 @@
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
// The integ-test-distribution is published to maven // The integ-test-distribution is published to maven
apply plugin: 'elasticsearch.publish' apply plugin: 'elasticsearch.publish'

View file

@ -14,7 +14,7 @@ import org.elasticsearch.gradle.util.GradleUtils
import java.nio.file.Path import java.nio.file.Path
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.test.fixtures' apply plugin: 'elasticsearch.test.fixtures'
apply plugin: 'elasticsearch.internal-distribution-download' apply plugin: 'elasticsearch.internal-distribution-download'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'Adds aggregations whose input are a list of numeric fields and output includes a matrix.' description 'Adds aggregations whose input are a list of numeric fields and output includes a matrix.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -8,7 +8,7 @@
import org.apache.tools.ant.taskdefs.condition.Os import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
testClusters.configureEach { testClusters.configureEach {
testDistribution = 'DEFAULT' testDistribution = 'DEFAULT'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'Ingest processor that extracts information from a user agent' description 'Ingest processor that extracts information from a user agent'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
esplugin { esplugin {
description 'Plugin exposing APIs for Kibana system indices' description 'Plugin exposing APIs for Kibana system indices'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,8 +5,8 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -8,7 +8,7 @@
import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask; import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask;
apply plugin: 'elasticsearch.validate-rest-spec' apply plugin: 'elasticsearch.validate-rest-spec'
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'An easy, safe and fast scripting language for Elasticsearch' description 'An easy, safe and fast scripting language for Elasticsearch'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -16,8 +16,8 @@ import org.gradle.api.internal.artifacts.ArtifactAttributes
apply plugin: 'elasticsearch.test-with-dependencies' apply plugin: 'elasticsearch.test-with-dependencies'
apply plugin: 'elasticsearch.jdk-download' apply plugin: 'elasticsearch.jdk-download'
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -8,7 +8,7 @@
import org.elasticsearch.gradle.PropertyNormalization import org.elasticsearch.gradle.PropertyNormalization
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.test.fixtures' apply plugin: 'elasticsearch.test.fixtures'

View file

@ -7,7 +7,7 @@
*/ */
apply plugin: 'elasticsearch.validate-rest-spec' apply plugin: 'elasticsearch.validate-rest-spec'
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'Module for runtime fields features and extensions that have large dependencies' description 'Module for runtime fields features and extensions that have large dependencies'

View file

@ -7,11 +7,11 @@
*/ */
import org.elasticsearch.gradle.internal.test.RestIntegTestTask import org.elasticsearch.gradle.internal.test.RestIntegTestTask
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin
import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
/* /*
@ -63,7 +63,7 @@ TaskProvider<Test> pooledInternalClusterTest = tasks.register("pooledInternalClu
TaskProvider<RestIntegTestTask> pooledJavaRestTest = tasks.register("pooledJavaRestTest", RestIntegTestTask) { TaskProvider<RestIntegTestTask> pooledJavaRestTest = tasks.register("pooledJavaRestTest", RestIntegTestTask) {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet javaRestTestSourceSet = sourceSets.getByName(InternalJavaRestTestPlugin.SOURCE_SET_NAME) SourceSet javaRestTestSourceSet = sourceSets.getByName(LegacyJavaRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(javaRestTestSourceSet.getOutput().getClassesDirs()) setTestClassesDirs(javaRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(javaRestTestSourceSet.getRuntimeClasspath()) setClasspath(javaRestTestSourceSet.getRuntimeClasspath())

View file

@ -7,7 +7,7 @@ import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Japanese (kuromoji) Analysis plugin integrates Lucene kuromoji analysis module into elasticsearch.' description 'The Japanese (kuromoji) Analysis plugin integrates Lucene kuromoji analysis module into elasticsearch.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Korean (nori) Analysis plugin integrates Lucene nori analysis module into elasticsearch.' description 'The Korean (nori) Analysis plugin integrates Lucene nori analysis module into elasticsearch.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Phonetic Analysis plugin integrates phonetic token filter analysis with elasticsearch.' description 'The Phonetic Analysis plugin integrates phonetic token filter analysis with elasticsearch.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'Smart Chinese Analysis plugin integrates Lucene Smart Chinese analysis module into elasticsearch.' description 'Smart Chinese Analysis plugin integrates Lucene Smart Chinese analysis module into elasticsearch.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Stempel (Polish) Analysis plugin integrates Lucene stempel (polish) analysis module into elasticsearch.' description 'The Stempel (Polish) Analysis plugin integrates Lucene stempel (polish) analysis module into elasticsearch.'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Ukrainian Analysis plugin integrates the Lucene UkrainianMorfologikAnalyzer into elasticsearch.' description 'The Ukrainian Analysis plugin integrates the Lucene UkrainianMorfologikAnalyzer into elasticsearch.'

View file

@ -8,7 +8,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -7,7 +7,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -10,11 +10,11 @@ import org.apache.tools.ant.filters.ReplaceTokens
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.AntFixture import org.elasticsearch.gradle.internal.test.AntFixture
import org.elasticsearch.gradle.internal.test.RestIntegTestTask import org.elasticsearch.gradle.internal.test.RestIntegTestTask
import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
dependencies { dependencies {
yamlRestTestImplementation project(':plugins:discovery-ec2') yamlRestTestImplementation project(':plugins:discovery-ec2')
@ -62,7 +62,7 @@ tasks.named("yamlRestTest").configure { enabled = false }
def yamlRestTestTask = tasks.register("yamlRestTest${action}", RestIntegTestTask) { def yamlRestTestTask = tasks.register("yamlRestTest${action}", RestIntegTestTask) {
dependsOn fixture dependsOn fixture
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME) SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
testClassesDirs = yamlRestTestSourceSet.getOutput().getClassesDirs() testClassesDirs = yamlRestTestSourceSet.getOutput().getClassesDirs()
classpath = yamlRestTestSourceSet.getRuntimeClasspath() classpath = yamlRestTestSourceSet.getRuntimeClasspath()
} }

View file

@ -1,4 +1,4 @@
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -13,7 +13,7 @@ import org.elasticsearch.gradle.internal.test.AntFixture
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
final int gceNumberOfNodes = 3 final int gceNumberOfNodes = 3

View file

@ -7,7 +7,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'Ingest processor that uses Apache Tika to extract contents' description 'Ingest processor that uses Apache Tika to extract contents'

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The Mapper Murmur3 plugin allows to compute hashes of a field\'s values at index-time and to store them in the index.' description 'The Mapper Murmur3 plugin allows to compute hashes of a field\'s values at index-time and to store them in the index.'

View file

@ -11,11 +11,16 @@ package org.elasticsearch.index.mapper.size;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.junit.ClassRule;
public class MapperSizeClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { public class MapperSizeClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
@ClassRule
public static ElasticsearchCluster cluster = ElasticsearchCluster.local().plugin("mapper-size").build();
public MapperSizeClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public MapperSizeClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }
@ -24,4 +29,9 @@ public class MapperSizeClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public static Iterable<Object[]> parameters() throws Exception { public static Iterable<Object[]> parameters() throws Exception {
return createParameters(); return createParameters();
} }
@Override
protected String getTestRestCluster() {
return cluster.getHttpAddresses();
}
} }

View file

@ -13,7 +13,7 @@ import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.internal-test-artifact-base'

View file

@ -1,7 +1,7 @@
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.RestIntegTestTask import org.elasticsearch.gradle.internal.test.RestIntegTestTask
import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin
import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin
import java.nio.file.Files import java.nio.file.Files
@ -16,7 +16,7 @@ import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.internal-test-artifact-base'
@ -269,7 +269,7 @@ def largeBlobYamlRestTest = tasks.register("largeBlobYamlRestTest", RestIntegTes
dependsOn "createServiceAccountFile" dependsOn "createServiceAccountFile"
} }
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME) SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs()) setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(yamlRestTestSourceSet.getRuntimeClasspath()) setClasspath(yamlRestTestSourceSet.getRuntimeClasspath())
@ -320,7 +320,7 @@ if (useFixture) {
tasks.register("yamlRestTestApplicationDefaultCredentials", RestIntegTestTask.class) { tasks.register("yamlRestTestApplicationDefaultCredentials", RestIntegTestTask.class) {
dependsOn('bundlePlugin') dependsOn('bundlePlugin')
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME) SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs()) setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(yamlRestTestSourceSet.getRuntimeClasspath()) setClasspath(yamlRestTestSourceSet.getRuntimeClasspath())
} }

View file

@ -15,8 +15,8 @@ import java.nio.file.Path
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
apply plugin: 'elasticsearch.test.fixtures' apply plugin: 'elasticsearch.test.fixtures'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
description 'The HDFS repository plugin adds support for Hadoop Distributed File-System (HDFS) repositories.' description 'The HDFS repository plugin adds support for Hadoop Distributed File-System (HDFS) repositories.'

View file

@ -1,7 +1,7 @@
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.RestIntegTestTask import org.elasticsearch.gradle.internal.test.RestIntegTestTask
import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin
import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
@ -13,7 +13,7 @@ import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.internal-test-artifact-base'
@ -233,7 +233,7 @@ if (useFixture) {
description = "Runs REST tests using the Minio repository." description = "Runs REST tests using the Minio repository."
dependsOn tasks.named("bundlePlugin") dependsOn tasks.named("bundlePlugin")
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME) SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs()) setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(yamlRestTestSourceSet.getRuntimeClasspath()) setClasspath(yamlRestTestSourceSet.getRuntimeClasspath())
@ -260,7 +260,7 @@ if (useFixture) {
description = "Runs tests using the ECS repository." description = "Runs tests using the ECS repository."
dependsOn('bundlePlugin') dependsOn('bundlePlugin')
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME) SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs()) setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(yamlRestTestSourceSet.getRuntimeClasspath()) setClasspath(yamlRestTestSourceSet.getRuntimeClasspath())
systemProperty 'tests.rest.blacklist', [ systemProperty 'tests.rest.blacklist', [

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-cluster-test'
esplugin { esplugin {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
testClusters.matching { it.name == "javaRestTest" }.configureEach { testClusters.matching { it.name == "javaRestTest" }.configureEach {
setting 'xpack.security.enabled', 'true' setting 'xpack.security.enabled', 'true'

View file

@ -9,7 +9,7 @@ import org.elasticsearch.gradle.internal.test.RestIntegTestTask
*/ */
// apply plugin: 'elasticsearch.standalone-rest-test' // apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
// TODO: this test works, but it isn't really a rest test...should we have another plugin for "non rest test that just needs N clusters?" // TODO: this test works, but it isn't really a rest test...should we have another plugin for "non rest test that just needs N clusters?"

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.test-with-dependencies' apply plugin: 'elasticsearch.test-with-dependencies'
dependencies { dependencies {

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
dependencies { dependencies {
testImplementation project(':modules:ingest-common') testImplementation project(':modules:ingest-common')

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
dependencies { dependencies {
yamlRestTestImplementation project(':modules:ingest-common') yamlRestTestImplementation project(':modules:ingest-common')

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
restResources { restResources {
restTests { restTests {

View file

@ -9,7 +9,7 @@
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
ext.pluginPaths = [] ext.pluginPaths = []
project(':plugins').getChildProjects().each { pluginName, pluginProject -> project(':plugins').getChildProjects().each { pluginName, pluginProject ->

View file

@ -9,7 +9,7 @@
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.rest-resources'
final Project fixture = project(':test:fixtures:azure-fixture') final Project fixture = project(':test:fixtures:azure-fixture')

View file

@ -8,7 +8,7 @@ import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.rest-resources'
dependencies { dependencies {

View file

@ -6,7 +6,7 @@ import java.security.KeyPairGenerator
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.rest-resources'
final Project fixture = project(':test:fixtures:gcs-fixture') final Project fixture = project(':test:fixtures:gcs-fixture')

View file

@ -9,7 +9,7 @@
import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.rest-resources'
final Project fixture = project(':test:fixtures:s3-fixture') final Project fixture = project(':test:fixtures:s3-fixture')

View file

@ -7,7 +7,7 @@
*/ */
apply plugin: 'elasticsearch.base-internal-es-plugin' apply plugin: 'elasticsearch.base-internal-es-plugin'
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
esplugin { esplugin {
name 'system-indices-qa' name 'system-indices-qa'

View file

@ -8,7 +8,7 @@ import org.elasticsearch.gradle.OS
* Side Public License, v 1. * Side Public License, v 1.
*/ */
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
testClusters.configureEach { testClusters.configureEach {
setting 'xpack.security.enabled', 'false' setting 'xpack.security.enabled', 'false'

View file

@ -32,8 +32,8 @@ artifacts {
restTests(new File(projectDir, "src/yamlRestTest/resources/rest-api-spec/test")) restTests(new File(projectDir, "src/yamlRestTest/resources/rest-api-spec/test"))
} }
testClusters.configureEach { dependencies {
module ':modules:mapper-extras' clusterModules project(":modules:mapper-extras")
} }
tasks.named("test").configure {enabled = false } tasks.named("test").configure {enabled = false }

View file

@ -13,8 +13,11 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
import org.apache.lucene.util.TimeUnits; import org.apache.lucene.util.TimeUnits;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.cluster.FeatureFlag;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.junit.ClassRule;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */ /** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
@ -22,6 +25,12 @@ import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
@TimeoutSuite(millis = 40 * TimeUnits.MINUTE) @TimeoutSuite(millis = 40 * TimeUnits.MINUTE)
public class ClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { public class ClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
@ClassRule
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
.module("mapper-extras")
.feature(FeatureFlag.TIME_SERIES_MODE)
.build();
public ClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public ClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }
@ -30,4 +39,9 @@ public class ClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public static Iterable<Object[]> parameters() throws Exception { public static Iterable<Object[]> parameters() throws Exception {
return createParameters(); return createParameters();
} }
@Override
protected String getTestRestCluster() {
return cluster.getHttpAddresses();
}
} }

View file

@ -79,7 +79,8 @@ List projects = [
'test:fixtures:geoip-fixture', 'test:fixtures:geoip-fixture',
'test:fixtures:url-fixture', 'test:fixtures:url-fixture',
'test:fixtures:nginx-fixture', 'test:fixtures:nginx-fixture',
'test:logger-usage' 'test:logger-usage',
'test:test-clusters'
] ]
/** /**

View file

@ -3,7 +3,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
subprojects { subprojects {
apply plugin: 'elasticsearch.base-internal-es-plugin' apply plugin: 'elasticsearch.base-internal-es-plugin'
apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.legacy-yaml-rest-test'
esplugin { esplugin {
name it.name name it.name

View file

@ -1,7 +1,7 @@
import org.elasticsearch.gradle.internal.info.BuildParams import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.util.GradleUtils import org.elasticsearch.gradle.util.GradleUtils
apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.legacy-java-rest-test'
apply plugin: 'elasticsearch.internal-es-plugin' apply plugin: 'elasticsearch.internal-es-plugin'
esplugin { esplugin {

View file

@ -169,7 +169,11 @@ public class ReproduceInfoPrinter extends RunListener {
appendOpt("tests.locale", Locale.getDefault().toLanguageTag()); appendOpt("tests.locale", Locale.getDefault().toLanguageTag());
appendOpt("tests.timezone", TimeZone.getDefault().getID()); appendOpt("tests.timezone", TimeZone.getDefault().getID());
appendOpt("tests.distribution", System.getProperty("tests.distribution")); appendOpt("tests.distribution", System.getProperty("tests.distribution"));
appendOpt("runtime.java", Integer.toString(JavaVersion.current().getVersion().get(0)));
appendOpt(
"runtime.java",
System.getProperty("tests.runtime.java.version", Integer.toString(JavaVersion.current().getVersion().get(0)))
);
appendOpt("license.key", System.getProperty("licence.key")); appendOpt("license.key", System.getProperty("licence.key"));
appendOpt(ESTestCase.FIPS_SYSPROP, System.getProperty(ESTestCase.FIPS_SYSPROP)); appendOpt(ESTestCase.FIPS_SYSPROP, System.getProperty(ESTestCase.FIPS_SYSPROP));
return this; return this;

View file

@ -73,7 +73,9 @@ public final class Features {
} }
private static boolean isSupported(String feature) { private static boolean isSupported(String feature) {
if (feature.equals(SPI_ON_CLASSPATH_SINCE_JDK_9) && JavaVersion.current().compareTo(JavaVersion.parse("9")) >= 0) { String runtimeJavaProp = System.getProperty("tests.runtime.java.version");
JavaVersion runtimeJava = runtimeJavaProp != null ? JavaVersion.parse(runtimeJavaProp) : JavaVersion.current();
if (feature.equals(SPI_ON_CLASSPATH_SINCE_JDK_9) && runtimeJava.compareTo(JavaVersion.parse("9")) >= 0) {
return true; return true;
} }
return SUPPORTED.contains(feature); return SUPPORTED.contains(feature);

View file

@ -0,0 +1,19 @@
apply plugin: 'elasticsearch.java'
apply plugin: 'com.github.johnrengelman.shadow'
dependencies {
shadow("junit:junit:${versions.junit}") {
exclude module: 'hamcrest-core'
}
shadow "org.apache.logging.log4j:log4j-api:${versions.log4j}"
implementation files("$rootDir/build-tools/reaper/build/libs/reaper.jar")
}
// We use updated APIs here and since this project is only used for REST testing it's ok to run with > Java 8
sourceCompatibility = 17
targetCompatibility = 17
tasks.named("processResources").configure {
from(new File(rootDir, "build-tools-internal/version.properties"))
}

View file

@ -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.test.cluster;
public interface ClusterFactory<S extends ClusterSpec, H extends ClusterHandle> {
H create(S spec);
}

View file

@ -0,0 +1,45 @@
/*
* 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;
import java.io.Closeable;
/**
* A handle to an {@link ElasticsearchCluster}.
*/
public interface ClusterHandle extends Closeable {
/**
* Starts the cluster. This method will block until all nodes are started and cluster is ready to serve requests.
*/
void start();
/**
* Stops the cluster. This method will block until all cluster node processes have exited. This method is thread-safe and subsequent
* calls will wait for the exiting termination to complete.
*
* @param forcibly whether to forcibly terminate the cluster
*/
void stop(boolean forcibly);
/**
* Whether the cluster is started or not. This method makes no guarantees on cluster availability, only that the node processes have
* been started.
*
* @return whether the cluster has been started
*/
boolean isStarted();
/**
* Returns a comma-separated list of HTTP transport endpoints for cluster. If this method is called on an unstarted cluster, the cluster
* will be started. This method is thread-safe and subsequent calls will wait for cluster start and availability.
*
* @return cluster node HTTP transport addresses
*/
String getHttpAddresses();
}

View file

@ -0,0 +1,11 @@
/*
* 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;
public interface ClusterSpec {}

View file

@ -0,0 +1,35 @@
/*
* 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;
import org.elasticsearch.test.cluster.local.DefaultLocalClusterSpecBuilder;
import org.elasticsearch.test.cluster.local.LocalClusterSpecBuilder;
import org.junit.rules.TestRule;
/**
* <p>A JUnit test rule for orchestrating an Elasticsearch cluster for local integration testing. New clusters can be created via one of the
* various static builder methods. For example:</p>
* <pre>
* &#064;ClassRule
* public static ElasticsearchCluster myCluster = ElasticsearchCluster.local().build();
* </pre>
*/
public interface ElasticsearchCluster extends TestRule, ClusterHandle {
/**
* Creates a new {@link DefaultLocalClusterSpecBuilder} for defining a locally orchestrated cluster. Local clusters use a locally built
* Elasticsearch distribution.
*
* @return a builder for a local cluster
*/
static LocalClusterSpecBuilder local() {
return new DefaultLocalClusterSpecBuilder();
}
}

View file

@ -0,0 +1,30 @@
/*
* 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;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import java.util.Map;
/**
* Functional interface for supplying environment variables to an Elasticsearch node. This interface is designed to be implemented by tests
* and fixtures wanting to provide settings to an {@link ElasticsearchCluster} in a dynamic fashion. Instances are evaluated lazily at
* cluster start time.
*/
public interface EnvironmentProvider {
/**
* Returns a collection of environment variables to apply to an Elasticsearch cluster node. This method is called when the cluster is
* started so implementors can return dynamic environment values that may or may not be based on the given node spec.
*
* @param nodeSpec the specification for the given node to apply settings to
* @return environment variables to add to the node
*/
Map<String, String> get(LocalNodeSpec nodeSpec);
}

View file

@ -0,0 +1,29 @@
/*
* 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;
import org.elasticsearch.test.cluster.util.Version;
/**
* Elasticsearch feature flags. Used in conjunction with {@link org.elasticsearch.test.cluster.local.LocalSpecBuilder#feature(FeatureFlag)}
* to indicate that this feature is required and should be enabled when appropriate.
*/
public enum FeatureFlag {
TIME_SERIES_MODE("es.index_mode_feature_flag_registered=true", Version.fromString("8.0.0"), null);
public final String systemProperty;
public final Version from;
public final Version until;
FeatureFlag(String systemProperty, Version from, Version until) {
this.systemProperty = systemProperty;
this.from = from;
this.until = until;
}
}

View file

@ -0,0 +1,31 @@
/*
* 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;
import org.elasticsearch.test.cluster.local.LocalClusterSpec;
import java.util.HashMap;
import java.util.Map;
public class MutableSettingsProvider implements SettingsProvider {
private final Map<String, String> settings = new HashMap<>();
@Override
public Map<String, String> get(LocalClusterSpec.LocalNodeSpec nodeSpec) {
return settings;
}
public void put(String setting, String value) {
settings.put(setting, value);
}
public void clear() {
settings.clear();
}
}

View file

@ -0,0 +1,30 @@
/*
* 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;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import java.util.Map;
/**
* Functional interface for supplying settings to an Elasticsearch node. This interface is designed to be implemented by tests and fixtures
* wanting to provide settings to an {@link ElasticsearchCluster} in a dynamic fashion. Instances are evaluated lazily at cluster
* start time.
*/
public interface SettingsProvider {
/**
* Returns a collection of settings to apply to an Elasticsearch cluster node. This method is called when the cluster is started so
* implementors can return dynamic setting values that may or may not be based on the given node spec.
*
* @param nodeSpec the specification for the given node to apply settings to
* @return settings to add to the node
*/
Map<String, String> get(LocalNodeSpec nodeSpec);
}

View file

@ -0,0 +1,159 @@
/*
* 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;
import org.elasticsearch.test.cluster.EnvironmentProvider;
import org.elasticsearch.test.cluster.FeatureFlag;
import org.elasticsearch.test.cluster.SettingsProvider;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
public abstract class AbstractLocalSpecBuilder<T extends LocalSpecBuilder<?>> implements LocalSpecBuilder<T> {
private final AbstractLocalSpecBuilder<?> parent;
private final List<SettingsProvider> settingsProviders = new ArrayList<>();
private final Map<String, String> settings = new HashMap<>();
private final List<EnvironmentProvider> environmentProviders = new ArrayList<>();
private final Map<String, String> environment = new HashMap<>();
private final Set<String> modules = new HashSet<>();
private final Set<String> plugins = new HashSet<>();
private final Set<FeatureFlag> features = new HashSet<>();
private DistributionType distributionType;
protected AbstractLocalSpecBuilder(AbstractLocalSpecBuilder<?> parent) {
this.parent = parent;
}
@Override
public T settings(SettingsProvider settingsProvider) {
this.settingsProviders.add(settingsProvider);
return cast(this);
}
List<SettingsProvider> getSettingsProviders() {
return inherit(() -> parent.getSettingsProviders(), settingsProviders);
}
@Override
public T setting(String setting, String value) {
this.settings.put(setting, value);
return cast(this);
}
Map<String, String> getSettings() {
return inherit(() -> parent.getSettings(), settings);
}
@Override
public T environment(EnvironmentProvider environmentProvider) {
this.environmentProviders.add(environmentProvider);
return cast(this);
}
List<EnvironmentProvider> getEnvironmentProviders() {
return inherit(() -> parent.getEnvironmentProviders(), environmentProviders);
}
@Override
public T environment(String key, String value) {
this.environment.put(key, value);
return cast(this);
}
Map<String, String> getEnvironment() {
return inherit(() -> parent.getEnvironment(), environment);
}
@Override
public T distribution(DistributionType type) {
this.distributionType = type;
return cast(this);
}
DistributionType getDistributionType() {
return inherit(() -> parent.getDistributionType(), distributionType);
}
@Override
public T module(String moduleName) {
this.modules.add(moduleName);
return cast(this);
}
Set<String> getModules() {
return inherit(() -> parent.getModules(), modules);
}
@Override
public T plugin(String pluginName) {
this.plugins.add(pluginName);
return cast(this);
}
Set<String> getPlugins() {
return inherit(() -> parent.getPlugins(), plugins);
}
@Override
public T feature(FeatureFlag feature) {
this.features.add(feature);
return cast(this);
}
Set<FeatureFlag> getFeatures() {
return inherit(() -> parent.getFeatures(), features);
}
private <T> List<T> inherit(Supplier<List<T>> parent, List<T> child) {
List<T> combinedList = new ArrayList<>();
if (this.parent != null) {
combinedList.addAll(parent.get());
}
combinedList.addAll(child);
return combinedList;
}
private <T> Set<T> inherit(Supplier<Set<T>> parent, Set<T> child) {
Set<T> combinedSet = new HashSet<>();
if (this.parent != null) {
combinedSet.addAll(parent.get());
}
combinedSet.addAll(child);
return combinedSet;
}
private <K, V> Map<K, V> inherit(Supplier<Map<K, V>> parent, Map<K, V> child) {
Map<K, V> combinedMap = new HashMap<>();
if (this.parent != null) {
combinedMap.putAll(parent.get());
}
combinedMap.putAll(child);
return combinedMap;
}
private <T> T inherit(Supplier<T> parent, T child) {
T value = null;
if (this.parent != null) {
value = parent.get();
}
return child == null ? value : child;
}
@SuppressWarnings("unchecked")
private static <T> T cast(Object o) {
return (T) o;
}
}

View file

@ -0,0 +1,39 @@
/*
* 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;
import org.elasticsearch.test.cluster.EnvironmentProvider;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import org.elasticsearch.test.cluster.util.Version;
import java.util.HashMap;
import java.util.Map;
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";
@Override
public Map<String, String> get(LocalNodeSpec nodeSpec) {
Map<String, String> environment = new HashMap<>();
// 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));
}
// Override the system hostname variables for testing
environment.put("HOSTNAME", HOSTNAME_OVERRIDE);
environment.put("COMPUTERNAME", COMPUTERNAME_OVERRIDE);
return environment;
}
}

View file

@ -0,0 +1,151 @@
/*
* 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;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import org.elasticsearch.test.cluster.local.model.User;
import org.elasticsearch.test.cluster.util.Version;
import org.elasticsearch.test.cluster.util.resource.TextResource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public class DefaultLocalClusterSpecBuilder extends AbstractLocalSpecBuilder<LocalClusterSpecBuilder> implements LocalClusterSpecBuilder {
private String name = "test-cluster";
private final List<DefaultLocalNodeSpecBuilder> nodeBuilders = new ArrayList<>();
private final List<User> users = new ArrayList<>();
private final List<TextResource> roleFiles = new ArrayList<>();
public DefaultLocalClusterSpecBuilder() {
super(null);
this.settings(new DefaultSettingsProvider());
this.environment(new DefaultEnvironmentProvider());
this.rolesFile(TextResource.fromClasspath("default_test_roles.yml"));
}
@Override
public DefaultLocalClusterSpecBuilder name(String name) {
this.name = name;
return this;
}
@Override
public DefaultLocalClusterSpecBuilder apply(LocalClusterConfigProvider configProvider) {
configProvider.apply(this);
return this;
}
@Override
public DefaultLocalClusterSpecBuilder nodes(int nodes) {
if (nodes < nodeBuilders.size()) {
throw new IllegalArgumentException(
"Cannot shrink cluster to " + nodes + ". " + nodeBuilders.size() + " nodes already configured"
);
}
int newNodes = nodes - nodeBuilders.size();
for (int i = 0; i < newNodes; i++) {
nodeBuilders.add(new DefaultLocalNodeSpecBuilder(this));
}
return this;
}
@Override
public DefaultLocalClusterSpecBuilder withNode(Consumer<? super LocalNodeSpecBuilder> config) {
DefaultLocalNodeSpecBuilder builder = new DefaultLocalNodeSpecBuilder(this);
config.accept(builder);
nodeBuilders.add(builder);
return this;
}
@Override
public DefaultLocalClusterSpecBuilder node(int index, Consumer<? super LocalNodeSpecBuilder> config) {
try {
DefaultLocalNodeSpecBuilder builder = nodeBuilders.get(index);
config.accept(builder);
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"No node at index + " + index + " exists. Only " + nodeBuilders.size() + " nodes have been configured"
);
}
return this;
}
@Override
public DefaultLocalClusterSpecBuilder user(String username, String password) {
this.users.add(new User(username, password));
return this;
}
@Override
public DefaultLocalClusterSpecBuilder user(String username, String password, String role) {
this.users.add(new User(username, password, role));
return this;
}
@Override
public DefaultLocalClusterSpecBuilder rolesFile(TextResource rolesFile) {
this.roleFiles.add(rolesFile);
return this;
}
@Override
public ElasticsearchCluster build() {
LocalClusterSpec clusterSpec = new LocalClusterSpec(name, users, roleFiles);
List<LocalNodeSpec> 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 new LocalElasticsearchCluster(clusterSpec);
}
public static class DefaultLocalNodeSpecBuilder extends AbstractLocalSpecBuilder<LocalNodeSpecBuilder> implements LocalNodeSpecBuilder {
private String name;
protected DefaultLocalNodeSpecBuilder(AbstractLocalSpecBuilder<?> parent) {
super(parent);
}
@Override
public DefaultLocalNodeSpecBuilder name(String name) {
this.name = name;
return this;
}
private LocalNodeSpec build(LocalClusterSpec cluster) {
return new LocalNodeSpec(
cluster,
name,
Version.CURRENT,
getSettingsProviders(),
getSettings(),
getEnvironmentProviders(),
getEnvironment(),
getModules(),
getPlugins(),
Optional.ofNullable(getDistributionType()).orElse(DistributionType.INTEG_TEST),
getFeatures()
);
}
}
}

View file

@ -0,0 +1,72 @@
/*
* 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;
import org.elasticsearch.test.cluster.SettingsProvider;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class DefaultSettingsProvider implements SettingsProvider {
@Override
public Map<String, String> get(LocalNodeSpec nodeSpec) {
Map<String, String> settings = new HashMap<>();
settings.put("node.name", nodeSpec.getName());
settings.put("node.attr.testattr", "test");
settings.put("node.portsfile", "true");
settings.put("http.port", "0");
settings.put("transport.port", "0");
if (nodeSpec.getDistributionType() == DistributionType.DEFAULT) {
// Disable deprecation indexing which is enabled by default in 7.16
if (nodeSpec.getVersion().onOrAfter("7.16.0")) {
settings.put("cluster.deprecation_indexing.enabled", "false");
}
}
// Default the watermarks to absurdly low to prevent the tests from failing on nodes without enough disk space
settings.put("cluster.routing.allocation.disk.watermark.low", "1b");
settings.put("cluster.routing.allocation.disk.watermark.high", "1b");
settings.put("cluster.routing.allocation.disk.watermark.flood_stage", "1b");
// increase script compilation limit since tests can rapid-fire script compilations
if (nodeSpec.getVersion().onOrAfter("7.9.0")) {
settings.put("script.disable_max_compilations_rate", "true");
} else {
settings.put("script.max_compilations_rate", "2048/1m");
}
// 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");
// 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");
if (nodeSpec.getVersion().getMajor() >= 8) {
settings.put("cluster.service.slow_task_logging_threshold", "5s");
settings.put("cluster.service.slow_master_task_logging_threshold", "5s");
}
settings.put("action.destructive_requires_name", "false");
// Setup cluster discovery
String nodeNames = nodeSpec.getCluster().getNodes().stream().map(LocalNodeSpec::getName).collect(Collectors.joining(","));
settings.put("cluster.initial_master_nodes", "[" + nodeNames + "]");
settings.put("discovery.seed_providers", "file");
settings.put("discovery.seed_hosts", "[]");
return settings;
}
}

View file

@ -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.test.cluster.local;
public interface LocalClusterConfigProvider {
void apply(LocalClusterSpecBuilder builder);
}

View file

@ -0,0 +1,507 @@
/*
* 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;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.test.cluster.ClusterFactory;
import org.elasticsearch.test.cluster.local.LocalClusterSpec.LocalNodeSpec;
import org.elasticsearch.test.cluster.local.distribution.DistributionDescriptor;
import org.elasticsearch.test.cluster.local.distribution.DistributionResolver;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import org.elasticsearch.test.cluster.local.model.User;
import org.elasticsearch.test.cluster.util.IOUtils;
import org.elasticsearch.test.cluster.util.OS;
import org.elasticsearch.test.cluster.util.Pair;
import org.elasticsearch.test.cluster.util.ProcessReaper;
import org.elasticsearch.test.cluster.util.ProcessUtils;
import org.elasticsearch.test.cluster.util.Retry;
import org.elasticsearch.test.cluster.util.Version;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class LocalClusterFactory implements ClusterFactory<LocalClusterSpec, LocalClusterHandle> {
private static final Logger LOGGER = LogManager.getLogger(LocalClusterFactory.class);
private static final Duration NODE_UP_TIMEOUT = Duration.ofMinutes(2);
private static final Map<Pair<Version, DistributionType>, DistributionDescriptor> TEST_DISTRIBUTIONS = new ConcurrentHashMap<>();
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";
public static final Pattern BUNDLE_ARTIFACT_PATTERN = Pattern.compile("(.+)(?:-\\d\\.\\d\\.\\d-SNAPSHOT\\.zip)?");
private final Path baseWorkingDir;
private final DistributionResolver distributionResolver;
public LocalClusterFactory(Path baseWorkingDir, DistributionResolver distributionResolver) {
this.baseWorkingDir = baseWorkingDir;
this.distributionResolver = distributionResolver;
}
@Override
public LocalClusterHandle create(LocalClusterSpec spec) {
return new LocalClusterHandle(spec.getName(), spec.getNodes().stream().map(Node::new).toList());
}
public class Node {
private final LocalNodeSpec spec;
private final Path workingDir;
private final Path distributionDir;
private final Path snapshotsDir;
private final Path dataDir;
private final Path logsDir;
private final Path configDir;
private final Path tempDir;
private boolean initialized = false;
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.snapshotsDir = workingDir.resolve("repo");
this.dataDir = workingDir.resolve("data");
this.logsDir = workingDir.resolve("logs");
this.configDir = workingDir.resolve("config");
this.tempDir = workingDir.resolve("tmp"); // elasticsearch temporary directory
}
public synchronized void start() {
LOGGER.info("Starting Elasticsearch node '{}'", spec.getName());
if (initialized == false) {
LOGGER.info("Creating installation for node '{}' in {}", spec.getName(), workingDir);
distributionDescriptor = resolveDistribution();
LOGGER.info("Distribution for node '{}': {}", spec.getName(), distributionDescriptor);
initializeWorkingDirectory();
writeConfiguration();
createKeystore();
configureSecurity();
installPlugins();
if (spec.getDistributionType() == DistributionType.INTEG_TEST) {
installModules();
}
initialized = true;
}
startElasticsearch();
}
public synchronized void stop(boolean forcibly) {
if (process != null) {
ProcessUtils.stopHandle(process.toHandle(), forcibly);
ProcessReaper.instance().unregister(getServiceName());
}
}
public void waitForExit() {
if (process != null) {
ProcessUtils.waitForExit(process.toHandle());
}
}
public String getHttpAddress() {
Path portFile = workingDir.resolve("logs").resolve("http.ports");
if (Files.notExists(portFile)) {
waitUntilReady();
}
return readPortsFile(portFile).get(0);
}
public String getTransportEndpoint() {
Path portsFile = workingDir.resolve("logs").resolve("transport.ports");
if (Files.notExists(portsFile)) {
waitUntilReady();
}
return readPortsFile(portsFile).get(0);
}
public LocalNodeSpec getSpec() {
return spec;
}
Path getWorkingDir() {
return workingDir;
}
public void waitUntilReady() {
try {
Retry.retryUntilTrue(NODE_UP_TIMEOUT, Duration.ofMillis(500), () -> {
if (process.isAlive() == false) {
throw new RuntimeException(
"Elasticsearch process died while waiting for ports file. See console output for details."
);
}
Path httpPorts = workingDir.resolve("logs").resolve("http.ports");
Path transportPorts = workingDir.resolve("logs").resolve("transport.ports");
return Files.exists(httpPorts) && Files.exists(transportPorts);
});
} catch (TimeoutException e) {
throw new RuntimeException("Timed out after " + NODE_UP_TIMEOUT + " waiting for ports files for: " + this);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while waiting for ports file for: " + this, e);
}
}
private List<String> readPortsFile(Path file) {
try (Stream<String> lines = Files.lines(file, StandardCharsets.UTF_8)) {
return lines.map(String::trim).collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException("Unable to read ports file: " + file, e);
}
}
private void initializeWorkingDirectory() {
try {
IOUtils.deleteWithRetry(workingDir);
try {
IOUtils.syncWithLinks(distributionDescriptor.getDistributionDir(), distributionDir);
} catch (IOUtils.LinkCreationException e) {
// Note does not work for network drives, e.g. Vagrant
LOGGER.info("Failed to create working dir using hard links. Falling back to copy", e);
// ensure we get a clean copy
IOUtils.deleteWithRetry(distributionDir);
IOUtils.syncWithCopy(distributionDescriptor.getDistributionDir(), distributionDir);
}
Files.createDirectories(configDir);
Files.createDirectories(snapshotsDir);
Files.createDirectories(dataDir);
Files.createDirectories(logsDir);
Files.createDirectories(tempDir);
} catch (IOException e) {
throw new UncheckedIOException("Failed to create working directory for node '" + spec.getName() + "'", e);
}
}
private DistributionDescriptor resolveDistribution() {
return TEST_DISTRIBUTIONS.computeIfAbsent(
Pair.of(spec.getVersion(), spec.getDistributionType()),
key -> distributionResolver.resolve(key.left, key.right)
);
}
private void writeConfiguration() {
Path configFile = configDir.resolve("elasticsearch.yml");
Path jvmOptionsFile = configDir.resolve("jvm.options");
try {
// Write settings to elasticsearch.yml
Map<String, String> pathSettings = new HashMap<>();
pathSettings.put("path.repo", workingDir.resolve("repo").toString());
pathSettings.put("path.data", workingDir.resolve("data").toString());
pathSettings.put("path.logs", workingDir.resolve("logs").toString());
Files.writeString(
configFile,
Stream.concat(spec.resolveSettings().entrySet().stream(), pathSettings.entrySet().stream())
.map(entry -> entry.getKey() + ": " + entry.getValue())
.collect(Collectors.joining("\n")),
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.CREATE
);
// Copy additional configuration from distribution
try (Stream<Path> configFiles = Files.list(distributionDir.resolve("config"))) {
for (Path file : configFiles.toList()) {
Path dest = configFile.getParent().resolve(file.getFileName());
if (Files.exists(dest) == false) {
Files.copy(file, dest);
}
}
}
// Patch jvm.options file to update paths
String content = Files.readString(jvmOptionsFile);
Map<String, String> expansions = getJvmOptionsReplacements();
for (String key : expansions.keySet()) {
if (content.contains(key) == false) {
throw new IOException("Template property '" + key + "' not found in template.");
}
content = content.replace(key, expansions.get(key));
}
Files.writeString(jvmOptionsFile, content);
} catch (IOException e) {
throw new UncheckedIOException("Could not write config file: " + configFile, e);
}
}
private void createKeystore() {
try {
ProcessUtils.exec(
workingDir,
OS.conditional(
c -> c.onWindows(() -> distributionDir.resolve("bin").resolve("elasticsearch-keystore.bat"))
.onUnix(() -> distributionDir.resolve("bin").resolve("elasticsearch-keystore"))
),
getEnvironmentVariables(),
false,
"-v",
"create"
).waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private void configureSecurity() {
if (spec.isSecurityEnabled()) {
if (spec.getUsers().isEmpty() == false) {
LOGGER.info("Setting up roles.yml for node '{}'", spec.getName());
Path destination = workingDir.resolve("config").resolve("roles.yml");
spec.getRolesFiles().forEach(rolesFile -> {
try {
Files.writeString(
destination,
rolesFile.getText() + System.lineSeparator(),
StandardCharsets.UTF_8,
StandardOpenOption.APPEND
);
} catch (IOException e) {
throw new UncheckedIOException("Failed to append roles file " + rolesFile + " to " + destination, e);
}
});
}
LOGGER.info("Creating users for node '{}'", spec.getName());
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);
}
}
}
}
private void installPlugins() {
if (spec.getPlugins().isEmpty() == false) {
LOGGER.info("Installing plugins {} into node '{}", spec.getPlugins(), spec.getName());
List<Path> pluginPaths = Arrays.stream(System.getProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP).split(File.pathSeparator))
.map(Path::of)
.toList();
List<String> 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"
+ " clusterModules "
+ "project(':plugins:"
+ pluginName
+ "')"
+ "\n}"
);
})
)
.map(p -> p.toUri().toString())
.toList();
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);
}
} else {
toInstall.forEach(plugin -> {
try {
ProcessUtils.exec(workingDir, pluginCommand, getEnvironmentVariables(), false, "install", "--batch", plugin)
.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
}
}
private void installModules() {
if (spec.getModules().isEmpty() == false) {
LOGGER.info("Installing modules {} into node '{}", spec.getModules(), spec.getName());
List<Path> modulePaths = Arrays.stream(System.getProperty(TESTS_CLUSTER_MODULES_PATH_SYSPROP).split(File.pathSeparator))
.map(Path::of)
.toList();
spec.getModules().forEach(module -> installModule(module, modulePaths));
}
}
private void installModule(String moduleName, List<Path> modulePaths) {
Path destination = distributionDir.resolve("modules").resolve(moduleName);
if (Files.notExists(destination)) {
Path modulePath = modulePaths.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(':'));
String moduleDependency = moduleName.startsWith("x-pack")
? "project(xpackModule('" + moduleName.substring(7) + "'))"
: "project(':modules:" + moduleName + "')";
throw new RuntimeException(
"Unable to locate module '"
+ moduleName
+ "'. Ensure you've added the following to the build script for project '"
+ project
+ "':\n\n"
+ "dependencies {\n"
+ " clusterModules "
+ moduleDependency
+ "\n}"
);
});
IOUtils.syncWithCopy(modulePath.getParent(), destination);
// Install any extended plugins
Properties pluginProperties = new Properties();
try (
InputStream in = new BufferedInputStream(
new FileInputStream(modulePath.resolve("plugin-descriptor.properties").toFile())
)
) {
pluginProperties.load(in);
String extendedProperty = pluginProperties.getProperty("extended.plugins");
if (extendedProperty != null) {
String[] extendedPlugins = extendedProperty.split(",");
for (String plugin : extendedPlugins) {
installModule(plugin, modulePaths);
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
private void startElasticsearch() {
process = ProcessUtils.exec(
workingDir,
OS.conditional(
c -> c.onWindows(() -> distributionDir.resolve("bin").resolve("elasticsearch.bat"))
.onUnix(() -> distributionDir.resolve("bin").resolve("elasticsearch"))
),
getEnvironmentVariables(),
true
);
ProcessReaper.instance().registerPid(getServiceName(), process.pid());
}
private Map<String, String> getEnvironmentVariables() {
Map<String, String> environment = new HashMap<>(spec.resolveEnvironment());
environment.put("ES_PATH_CONF", workingDir.resolve("config").toString());
environment.put("ES_TMPDIR", workingDir.resolve("tmp").toString());
// Windows requires this as it defaults to `c:\windows` despite ES_TMPDIR
environment.put("TMP", workingDir.resolve("tmp").toString());
String featureFlagProperties = "";
if (spec.getFeatures().isEmpty() == false && distributionDescriptor.isSnapshot() == false) {
featureFlagProperties = spec.getFeatures()
.stream()
.filter(f -> spec.getVersion().onOrAfter(f.from) && (f.until == null || spec.getVersion().before(f.until)))
.map(f -> "-D" + f.systemProperty)
.collect(Collectors.joining(" "));
}
String heapSize = System.getProperty("tests.heap.size", "512m");
environment.put("ES_JAVA_OPTS", "-Xms" + heapSize + " -Xmx" + heapSize + " -ea -esa "
// Support passing in additional JVM arguments
+ System.getProperty("tests.jvm.argline", "")
+ " "
+ featureFlagProperties);
return environment;
}
private Map<String, String> 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")
);
}
private String getServiceName() {
return baseWorkingDir.getFileName() + "-" + spec.getCluster().getName() + "-" + spec.getName();
}
@Override
public String toString() {
return "{ cluster: '" + spec.getCluster().getName() + "', node: '" + spec.getName() + "' }";
}
}
}

View file

@ -0,0 +1,157 @@
/*
* 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;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.test.cluster.ClusterHandle;
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 java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
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;
public class LocalClusterHandle implements ClusterHandle {
private static final Logger LOGGER = LogManager.getLogger(LocalClusterHandle.class);
private static final Duration CLUSTER_UP_TIMEOUT = Duration.ofSeconds(30);
public final ForkJoinPool executor = new ForkJoinPool(
Math.max(Runtime.getRuntime().availableProcessors(), 4),
new ForkJoinPool.ForkJoinWorkerThreadFactory() {
private final AtomicLong counter = new AtomicLong(0);
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
ForkJoinWorkerThread thread = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
thread.setName(name + "-node-executor-" + counter.getAndIncrement());
return thread;
}
},
null,
false
);
private final AtomicBoolean started = new AtomicBoolean(false);
private final String name;
private final List<Node> nodes;
public LocalClusterHandle(String name, List<Node> nodes) {
this.name = name;
this.nodes = nodes;
}
@Override
public void start() {
if (started.getAndSet(true) == false) {
LOGGER.info("Starting Elasticsearch test cluster '{}'", name);
execute(() -> nodes.parallelStream().forEach(Node::start));
}
waitUntilReady();
}
@Override
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)));
} else {
// Make sure the process is stopped, otherwise wait
execute(() -> nodes.forEach(n -> n.waitForExit()));
}
}
@Override
public boolean isStarted() {
return started.get();
}
@Override
public void close() {
stop(false);
executor.shutdownNow();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public String getHttpAddresses() {
start();
return execute(() -> nodes.parallelStream().map(Node::getHttpAddress).collect(Collectors.joining(",")));
}
private void waitUntilReady() {
writeUnicastHostsFile();
try {
Retry.retryUntilTrue(CLUSTER_UP_TIMEOUT, Duration.ZERO, () -> {
Node node = nodes.get(0);
String scheme = node.getSpec().isSettingTrue("xpack.security.http.ssl.enabled") ? "https" : "http";
WaitForHttpResource wait = new WaitForHttpResource(scheme, node.getHttpAddress(), nodes.size());
if (node.getSpec().getUsers().isEmpty() == false) {
User credentials = node.getSpec().getUsers().get(0);
wait.setUsername(credentials.getUsername());
wait.setPassword(credentials.getPassword());
}
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) {
throw new RuntimeException("An error occurred while checking cluster '" + name + "' status.", e);
}
}
private void writeUnicastHostsFile() {
String transportUris = execute(() -> nodes.parallelStream().map(Node::getTransportEndpoint).collect(Collectors.joining("\n")));
nodes.forEach(node -> {
try {
Path hostsFile = node.getWorkingDir().resolve("config").resolve("unicast_hosts.txt");
if (Files.notExists(hostsFile)) {
Files.writeString(hostsFile, transportUris);
}
} catch (IOException e) {
throw new UncheckedIOException("Failed to write unicast_hosts for: " + node, e);
}
});
}
private <T> T execute(Callable<T> task) {
try {
return executor.submit(task).get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred orchestrating test cluster.", ExceptionUtils.findRootCause(e));
}
}
private void execute(Runnable task) {
execute(() -> {
task.run();
return true;
});
}
}

View file

@ -0,0 +1,190 @@
/*
* 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;
import org.elasticsearch.test.cluster.ClusterSpec;
import org.elasticsearch.test.cluster.EnvironmentProvider;
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.local.model.User;
import org.elasticsearch.test.cluster.util.Version;
import org.elasticsearch.test.cluster.util.resource.TextResource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class LocalClusterSpec implements ClusterSpec {
private final String name;
private final List<User> users;
private final List<TextResource> roleFiles;
private List<LocalNodeSpec> nodes;
public LocalClusterSpec(String name, List<User> users, List<TextResource> roleFiles) {
this.name = name;
this.users = users;
this.roleFiles = roleFiles;
}
public String getName() {
return name;
}
public List<User> getUsers() {
return users;
}
public List<TextResource> getRoleFiles() {
return roleFiles;
}
public List<LocalNodeSpec> getNodes() {
return nodes;
}
public void setNodes(List<LocalNodeSpec> nodes) {
this.nodes = nodes;
}
void validate() {
// Ensure we don't have nodes with duplicate names
List<String> nodeNames = nodes.stream().map(LocalNodeSpec::getName).collect(Collectors.toList());
Set<String> uniqueNames = nodes.stream().map(LocalNodeSpec::getName).collect(Collectors.toSet());
uniqueNames.forEach(name -> nodeNames.remove(nodeNames.indexOf(name)));
if (nodeNames.isEmpty() == false) {
throw new IllegalArgumentException("Cluster cannot contain nodes with duplicates names: " + nodeNames);
}
}
public static class LocalNodeSpec {
private final LocalClusterSpec cluster;
private final String name;
private final Version version;
private final List<SettingsProvider> settingsProviders;
private final Map<String, String> settings;
private final List<EnvironmentProvider> environmentProviders;
private final Map<String, String> environment;
private final Set<String> modules;
private final Set<String> plugins;
private final DistributionType distributionType;
private final Set<FeatureFlag> features;
public LocalNodeSpec(
LocalClusterSpec cluster,
String name,
Version version,
List<SettingsProvider> settingsProviders,
Map<String, String> settings,
List<EnvironmentProvider> environmentProviders,
Map<String, String> environment,
Set<String> modules,
Set<String> plugins,
DistributionType distributionType,
Set<FeatureFlag> features
) {
this.cluster = cluster;
this.name = name;
this.version = version;
this.settingsProviders = settingsProviders;
this.settings = settings;
this.environmentProviders = environmentProviders;
this.environment = environment;
this.modules = modules;
this.plugins = plugins;
this.distributionType = distributionType;
this.features = features;
}
public LocalClusterSpec getCluster() {
return cluster;
}
public String getName() {
return name == null ? cluster.getName() + "-" + cluster.getNodes().indexOf(this) : name;
}
public Version getVersion() {
return version;
}
public List<User> getUsers() {
return cluster.getUsers();
}
public List<TextResource> getRolesFiles() {
return cluster.getRoleFiles();
}
public DistributionType getDistributionType() {
return distributionType;
}
public Set<String> getModules() {
return modules;
}
public Set<String> getPlugins() {
return plugins;
}
public Set<FeatureFlag> getFeatures() {
return features;
}
public boolean isSecurityEnabled() {
return Boolean.parseBoolean(
resolveSettings().getOrDefault("xpack.security.enabled", getVersion().onOrAfter("8.0.0") ? "true" : "false")
);
}
public boolean isSettingTrue(String setting) {
return Boolean.parseBoolean(resolveSettings().getOrDefault(setting, "false"));
}
/**
* Resolve node settings. Order of precedence is as follows:
* <ol>
* <li>Settings from cluster configured {@link SettingsProvider}</li>
* <li>Settings from node configured {@link SettingsProvider}</li>
* <li>Explicit cluster settings</li>
* <li>Explicit node settings</li>
* </ol>
*
* @return resolved settings for node
*/
public Map<String, String> resolveSettings() {
Map<String, String> resolvedSettings = new HashMap<>();
settingsProviders.forEach(p -> resolvedSettings.putAll(p.get(this)));
resolvedSettings.putAll(settings);
return resolvedSettings;
}
/**
* Resolve node environment variables. Order of precedence is as follows:
* <ol>
* <li>Environment variables from cluster configured {@link EnvironmentProvider}</li>
* <li>Environment variables from node configured {@link EnvironmentProvider}</li>
* <li>Environment variables cluster settings</li>
* <li>Environment variables node settings</li>
* </ol>
*
* @return resolved environment variables for node
*/
public Map<String, String> resolveEnvironment() {
Map<String, String> resolvedEnvironment = new HashMap<>();
environmentProviders.forEach(p -> resolvedEnvironment.putAll(p.get(this)));
resolvedEnvironment.putAll(environment);
return resolvedEnvironment;
}
}
}

View file

@ -0,0 +1,58 @@
/*
* 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;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.cluster.util.resource.TextResource;
import java.util.function.Consumer;
public interface LocalClusterSpecBuilder extends LocalSpecBuilder<LocalClusterSpecBuilder> {
/**
* Sets the node name. By default, "test-cluster" is used.
*/
LocalClusterSpecBuilder name(String name);
LocalClusterSpecBuilder apply(LocalClusterConfigProvider configProvider);
/**
* Sets the number of nodes for the cluster.
*/
LocalClusterSpecBuilder nodes(int nodes);
/**
* Adds a new node to the cluster and configures the node.
*/
LocalClusterSpecBuilder withNode(Consumer<? super LocalNodeSpecBuilder> config);
/**
* Configures an existing node.
*
* @param index the index of the node to configure
* @param config configuration to apply to the node
*/
LocalClusterSpecBuilder node(int index, Consumer<? super LocalNodeSpecBuilder> config);
/**
* Register a user using the default test role.
*/
LocalClusterSpecBuilder user(String username, String password);
/**
* Register a user using the given role.
*/
LocalClusterSpecBuilder user(String username, String password, String role);
/**
* Register a roles file with cluster via the supplied {@link TextResource}.
*/
LocalClusterSpecBuilder rolesFile(TextResource rolesFile);
ElasticsearchCluster build();
}

Some files were not shown because too many files have changed in this diff Show more