Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce explicit API for configure test cluster feature flags #83876

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.gradle.internal;

import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.internal.info.BuildParams;
import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
import org.gradle.api.Plugin;
Expand All @@ -31,6 +32,10 @@ public void apply(Project project) {
project.getRootProject().getPluginManager().apply(InternalReaperPlugin.class);
TestClustersPlugin testClustersPlugin = project.getPlugins().apply(TestClustersPlugin.class);
testClustersPlugin.setRuntimeJava(providerFactory.provider(() -> BuildParams.getRuntimeJavaHome()));
testClustersPlugin.setIsReleasedVersion(
version -> (version.equals(VersionProperties.getElasticsearchVersion()) && BuildParams.isSnapshotBuild() == false)
|| BuildParams.getBwcVersions().unreleasedInfo(version) == null
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"either it is the current version and we're running a release build OR it's not unreleased". That's a lot of double negatives, but I get it.

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
*/
package org.elasticsearch.gradle;

import java.io.Serializable;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Encapsulates comparison and printing logic for an x.y.z version.
*/
public final class Version implements Comparable<Version> {
public final class Version implements Comparable<Version>, Serializable {
private final int major;
private final int minor;
private final int revision;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.elasticsearch.gradle.FileSupplier;
import org.elasticsearch.gradle.PropertyNormalization;
import org.elasticsearch.gradle.ReaperService;
import org.elasticsearch.gradle.Version;
import org.gradle.api.Named;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
Expand Down Expand Up @@ -61,6 +62,7 @@ public class ElasticsearchCluster implements TestClusterConfiguration, Named {
private final ArchiveOperations archiveOperations;
private final ExecOperations execOperations;
private final Provider<File> runtimeJava;
private final Function<Version, Boolean> isReleasedVersion;
private int nodeIndex = 0;

public ElasticsearchCluster(
Expand All @@ -73,7 +75,8 @@ public ElasticsearchCluster(
ExecOperations execOperations,
FileOperations fileOperations,
File workingDirBase,
Provider<File> runtimeJava
Provider<File> runtimeJava,
Function<Version, Boolean> isReleasedVersion
) {
this.path = path;
this.clusterName = clusterName;
Expand All @@ -85,6 +88,7 @@ public ElasticsearchCluster(
this.fileOperations = fileOperations;
this.workingDirBase = workingDirBase;
this.runtimeJava = runtimeJava;
this.isReleasedVersion = isReleasedVersion;
this.nodes = project.container(ElasticsearchNode.class);
this.nodes.add(
new ElasticsearchNode(
Expand All @@ -98,7 +102,8 @@ public ElasticsearchCluster(
execOperations,
fileOperations,
workingDirBase,
runtimeJava
runtimeJava,
isReleasedVersion
)
);

Expand Down Expand Up @@ -131,7 +136,8 @@ public void setNumberOfNodes(int numberOfNodes) {
execOperations,
fileOperations,
workingDirBase,
runtimeJava
runtimeJava,
isReleasedVersion
)
);
}
Expand Down Expand Up @@ -401,6 +407,16 @@ public void rolesFile(File rolesYml) {
nodes.all(node -> node.rolesFile(rolesYml));
}

@Override
public void requiresFeature(String feature, Version from) {
nodes.all(node -> node.requiresFeature(feature, from));
}

@Override
public void requiresFeature(String feature, Version from, Version until) {
nodes.all(node -> node.requiresFeature(feature, from, until));
}

private void writeUnicastHostsFiles() {
String unicastUris = nodes.stream().flatMap(node -> node.getAllTransportPortURI().stream()).collect(Collectors.joining("\n"));
nodes.forEach(node -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final LazyPropertyList<FileCollection> extraJarConfigurations = new LazyPropertyList<>("Extra jar files", this);
private final List<Map<String, String>> credentials = new ArrayList<>();
private final List<File> roleFiles = new ArrayList<>();
private final List<FeatureFlag> featureFlags = new ArrayList<>();
final LinkedHashMap<String, String> defaultConfig = new LinkedHashMap<>();

private final Path confPathRepo;
Expand All @@ -159,6 +160,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final Path esStdinFile;
private final Path tmpDir;
private final Provider<File> runtimeJava;
private final Function<Version, Boolean> isReleasedVersion;

private int currentDistro = 0;
private TestDistribution testDistribution;
Expand All @@ -185,7 +187,8 @@ public class ElasticsearchNode implements TestClusterConfiguration {
ExecOperations execOperations,
FileOperations fileOperations,
File workingDirBase,
Provider<File> runtimeJava
Provider<File> runtimeJava,
Function<Version, Boolean> isReleasedVersion
) {
this.clusterName = clusterName;
this.path = path;
Expand All @@ -197,6 +200,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
this.execOperations = execOperations;
this.fileOperations = fileOperations;
this.runtimeJava = runtimeJava;
this.isReleasedVersion = isReleasedVersion;
workingDir = workingDirBase.toPath().resolve(safeName(name)).toAbsolutePath();
confPathRepo = workingDir.resolve("repo");
configFile = workingDir.resolve("config/elasticsearch.yml");
Expand Down Expand Up @@ -773,6 +777,16 @@ public void rolesFile(File rolesYml) {
roleFiles.add(rolesYml);
}

@Override
public void requiresFeature(String feature, Version from) {
featureFlags.add(new FeatureFlag(feature, from, null));
}

@Override
public void requiresFeature(String feature, Version from, Version until) {
featureFlags.add(new FeatureFlag(feature, from, until));
}

private void runElasticsearchBinScriptWithInput(String input, String tool, CharSequence... args) {
if (Files.exists(getDistroDir().resolve("bin").resolve(tool)) == false
&& Files.exists(getDistroDir().resolve("bin").resolve(tool + ".bat")) == false) {
Expand Down Expand Up @@ -820,19 +834,30 @@ private Map<String, String> getESEnvironment() {
defaultEnv.put("ES_PATH_CONF", configFile.getParent().toString());
String systemPropertiesString = "";
if (systemProperties.isEmpty() == false) {
systemPropertiesString = " "
+ systemProperties.entrySet()
.stream()
.map(entry -> "-D" + entry.getKey() + "=" + entry.getValue())
// ES_PATH_CONF is also set as an environment variable and for a reference to ${ES_PATH_CONF}
// to work ES_JAVA_OPTS, we need to make sure that ES_PATH_CONF before ES_JAVA_OPTS. Instead,
// we replace the reference with the actual value in other environment variables
.map(p -> p.replace("${ES_PATH_CONF}", configFile.getParent().toString()))
.collect(Collectors.joining(" "));
systemPropertiesString = " " + systemProperties.entrySet().stream().peek(entry -> {
if (entry.getKey().contains("feature_flag")) {
throw new TestClustersException("Invalid system property `" + entry.getKey() + "`. Use `requiresFeature` instead.");
}
})
.map(entry -> "-D" + entry.getKey() + "=" + entry.getValue())
// ES_PATH_CONF is also set as an environment variable and for a reference to ${ES_PATH_CONF}
// to work ES_JAVA_OPTS, we need to make sure that ES_PATH_CONF before ES_JAVA_OPTS. Instead,
// we replace the reference with the actual value in other environment variables
.map(p -> p.replace("${ES_PATH_CONF}", configFile.getParent().toString()))
.collect(Collectors.joining(" "));
}
if (systemProperties.containsKey("io.netty.leakDetection.level") == false) {
systemPropertiesString = systemPropertiesString + " -Dio.netty.leakDetection.level=paranoid";
}

String featureFlagsString = "";
if (featureFlags.isEmpty() == false && isReleasedVersion.apply(getVersion())) {
featureFlagsString = featureFlags.stream()
.filter(f -> getVersion().onOrAfter(f.getFrom()) && (f.getUntil() == null || getVersion().before(f.getUntil())))
.map(f -> "-D" + f.getFeature() + "=true")
.collect(Collectors.joining(" "));
}

String jvmArgsString = "";
if (jvmArgs.isEmpty() == false) {
jvmArgsString = " " + jvmArgs.stream().peek(argument -> {
Expand All @@ -846,8 +871,19 @@ private Map<String, String> getESEnvironment() {
String heapSize = System.getProperty("tests.heap.size", "512m");
defaultEnv.put(
"ES_JAVA_OPTS",
"-Xms" + heapSize + " -Xmx" + heapSize + " -ea -esa " + systemPropertiesString + " " + jvmArgsString + " " +
// Support passing in additional JVM arguments
"-Xms"
+ heapSize
+ " -Xmx"
+ heapSize
+ " -ea -esa "
+ systemPropertiesString
+ " "
+ featureFlagsString
+ " "
+ jvmArgsString
+ " "
+
// Support passing in additional JVM arguments
System.getProperty("tests.jvm.argline", "")
);
defaultEnv.put("ES_TMPDIR", tmpDir.toString());
Expand Down Expand Up @@ -1466,6 +1502,11 @@ public List<?> getExtraConfigFiles() {
return extraConfigFiles.getNormalizedCollection();
}

@Nested
public List<FeatureFlag> getFeatureFlags() {
return featureFlags;
}

@Override
@Internal
public boolean isProcessAlive() {
Expand Down Expand Up @@ -1599,6 +1640,34 @@ public CharSequence[] getArgs() {
}
}

private static class FeatureFlag {
private final String feature;
private final Version from;
private final Version until;

public FeatureFlag(String feature, Version from, Version until) {
this.feature = feature;
this.from = from;
this.until = until;
}

@Input
public String getFeature() {
return feature;
}

@Input
public Version getFrom() {
return from;
}

@Input
@Optional
public Version getUntil() {
return until;
}
}

private static class LinkCreationException extends UncheckedIOException {
LinkCreationException(String message, IOException cause) {
super(message, cause);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import org.elasticsearch.gradle.FileSupplier;
import org.elasticsearch.gradle.PropertyNormalization;
import org.elasticsearch.gradle.Version;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFile;
import org.gradle.api.logging.Logging;
Expand Down Expand Up @@ -97,6 +98,10 @@ public interface TestClusterConfiguration {

void rolesFile(File rolesYml);

void requiresFeature(String feature, Version from);

void requiresFeature(String feature, Version from, Version until);

String getHttpSocketURI();

String getTransportPortURI();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.elasticsearch.gradle.DistributionDownloadPlugin;
import org.elasticsearch.gradle.ReaperPlugin;
import org.elasticsearch.gradle.ReaperService;
import org.elasticsearch.gradle.Version;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
Expand All @@ -30,6 +31,7 @@
import org.gradle.process.ExecOperations;

import java.io.File;
import java.util.function.Function;

import javax.inject.Inject;

Expand All @@ -45,6 +47,7 @@ public class TestClustersPlugin implements Plugin<Project> {
private static final Logger logger = Logging.getLogger(TestClustersPlugin.class);
private final ProviderFactory providerFactory;
private Provider<File> runtimeJavaProvider;
private Function<Version, Boolean> isReleasedVersion = v -> true;

@Inject
protected FileSystemOperations getFileSystemOperations() {
Expand Down Expand Up @@ -75,6 +78,10 @@ public void setRuntimeJava(Provider<File> runtimeJava) {
this.runtimeJavaProvider = runtimeJava;
}

public void setIsReleasedVersion(Function<Version, Boolean> isReleasedVersion) {
this.isReleasedVersion = isReleasedVersion;
}

@Override
public void apply(Project project) {
project.getPlugins().apply(DistributionDownloadPlugin.class);
Expand Down Expand Up @@ -124,7 +131,8 @@ private NamedDomainObjectContainer<ElasticsearchCluster> createTestClustersConta
getExecOperations(),
getFileOperations(),
new File(project.getBuildDir(), "testclusters"),
runtimeJavaProvider
runtimeJavaProvider,
isReleasedVersion
);
});
project.getExtensions().add(EXTENSION_NAME, container);
Expand Down
9 changes: 3 additions & 6 deletions modules/data-streams/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.internal.info.BuildParams

apply plugin: 'elasticsearch.test-with-dependencies'
Expand Down Expand Up @@ -30,19 +31,15 @@ testClusters.configureEach {
setting 'xpack.security.enabled', 'true'
keystore 'bootstrap.password', 'x-pack-test-password'
user username: "x_pack_rest_user", password: "x-pack-test-password"
if (BuildParams.isSnapshotBuild() == false) {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
}

testClusters.matching { it.name == "javaRestTest" }.configureEach {
testDistribution = 'DEFAULT'
setting 'xpack.security.enabled', 'false'
// disable ILM history, since it disturbs tests using _all
setting 'indices.lifecycle.history_index_enabled', 'false'
if (BuildParams.isSnapshotBuild() == false) {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
}

if (BuildParams.inFipsJvm){
Expand Down
5 changes: 2 additions & 3 deletions modules/reindex/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.apache.tools.ant.taskdefs.condition.Os
import org.elasticsearch.gradle.Architecture
import org.elasticsearch.gradle.OS
import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.AntFixture
import org.elasticsearch.gradle.transform.UnzipTransform
Expand All @@ -32,9 +33,7 @@ testClusters.configureEach {
module ':modules:lang-painless'
// Whitelist reindexing from the local node so we can test reindex-from-remote.
setting 'reindex.remote.whitelist', '127.0.0.1:*'
if (BuildParams.isSnapshotBuild() == false) {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
}

dependencies {
Expand Down
Loading