From b5fc72fdad852155ae1085d7ecf43ac7585a215f Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Fri, 27 Sep 2024 16:13:34 +0100 Subject: [PATCH] Add jvm option to enable test features (#113108) The option is only enabled for test clusters, and turns on features that are only present in tests --- .../src/main/groovy/elasticsearch.ide.gradle | 1 + .../internal/ElasticsearchTestBasePlugin.java | 1 + .../features/ClusterFeaturesIT.java | 1 + .../elasticsearch/features/FeatureData.java | 18 +++++++++++++++++- .../FeatureInfrastructureFeatures.java | 5 +++++ .../elasticsearch/features/FeatureService.java | 1 + .../features/FeatureSpecification.java | 10 ++++++++++ .../local/DefaultLocalClusterSpecBuilder.java | 4 +++- 8 files changed, 39 insertions(+), 2 deletions(-) diff --git a/build-tools-internal/src/main/groovy/elasticsearch.ide.gradle b/build-tools-internal/src/main/groovy/elasticsearch.ide.gradle index d4bb0c1189e8d..d3209ff27ce06 100644 --- a/build-tools-internal/src/main/groovy/elasticsearch.ide.gradle +++ b/build-tools-internal/src/main/groovy/elasticsearch.ide.gradle @@ -169,6 +169,7 @@ if (providers.systemProperty('idea.active').getOrNull() == 'true') { '-ea', '-Djava.security.manager=allow', '-Djava.locale.providers=CLDR', + '-Dtests.testfeatures.enabled=true', '-Des.nativelibs.path="' + testLibraryPath + '"', // TODO: only open these for mockito when it is modularized '--add-opens=java.base/java.security.cert=ALL-UNNAMED', diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java index 19ab49a851907..3fd59dc7a95f1 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java @@ -108,6 +108,7 @@ public void execute(Task t) { "-Xmx" + System.getProperty("tests.heap.size", "512m"), "-Xms" + System.getProperty("tests.heap.size", "512m"), "-Djava.security.manager=allow", + "-Dtests.testfeatures.enabled=true", "--add-opens=java.base/java.util=ALL-UNNAMED", // TODO: only open these for mockito when it is modularized "--add-opens=java.base/java.security.cert=ALL-UNNAMED", diff --git a/server/src/internalClusterTest/java/org/elasticsearch/features/ClusterFeaturesIT.java b/server/src/internalClusterTest/java/org/elasticsearch/features/ClusterFeaturesIT.java index 48009676ee6b7..74fd945ed3779 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/features/ClusterFeaturesIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/features/ClusterFeaturesIT.java @@ -31,6 +31,7 @@ public void testClusterHasFeatures() { FeatureService service = internalCluster().getCurrentMasterNodeInstance(FeatureService.class); assertThat(service.getNodeFeatures(), hasKey(FeatureService.FEATURES_SUPPORTED.id())); + assertThat(service.getNodeFeatures(), hasKey(FeatureService.TEST_FEATURES_ENABLED.id())); // check the nodes all have a feature in their cluster state (there should always be features_supported) var response = clusterAdmin().state(new ClusterStateRequest(TEST_REQUEST_TIMEOUT).clear().nodes(true)).actionGet(); diff --git a/server/src/main/java/org/elasticsearch/features/FeatureData.java b/server/src/main/java/org/elasticsearch/features/FeatureData.java index f2fdac937fc96..991bb4d82be3d 100644 --- a/server/src/main/java/org/elasticsearch/features/FeatureData.java +++ b/server/src/main/java/org/elasticsearch/features/FeatureData.java @@ -11,6 +11,8 @@ import org.elasticsearch.Version; import org.elasticsearch.common.Strings; +import org.elasticsearch.logging.LogManager; +import org.elasticsearch.logging.Logger; import java.util.Collections; import java.util.HashMap; @@ -28,6 +30,16 @@ * features for the consumption of {@link FeatureService} */ public class FeatureData { + + private static final Logger Log = LogManager.getLogger(FeatureData.class); + private static final boolean INCLUDE_TEST_FEATURES = System.getProperty("tests.testfeatures.enabled", "").equals("true"); + + static { + if (INCLUDE_TEST_FEATURES) { + Log.warn("WARNING: Test features are enabled. This should ONLY be used in automated tests."); + } + } + private final NavigableMap> historicalFeatures; private final Map nodeFeatures; @@ -43,7 +55,11 @@ public static FeatureData createFromSpecifications(List> historicalFeatures = new TreeMap<>(Map.of(Version.V_EMPTY, Set.of())); Map nodeFeatures = new HashMap<>(); for (FeatureSpecification spec : specs) { - var specFeatures = spec.getFeatures(); + Set specFeatures = spec.getFeatures(); + if (INCLUDE_TEST_FEATURES) { + specFeatures = new HashSet<>(specFeatures); + specFeatures.addAll(spec.getTestFeatures()); + } for (var hfe : spec.getHistoricalFeatures().entrySet()) { FeatureSpecification existing = allFeatures.putIfAbsent(hfe.getKey().id(), spec); diff --git a/server/src/main/java/org/elasticsearch/features/FeatureInfrastructureFeatures.java b/server/src/main/java/org/elasticsearch/features/FeatureInfrastructureFeatures.java index 53eaef369778f..76afb5eba8a47 100644 --- a/server/src/main/java/org/elasticsearch/features/FeatureInfrastructureFeatures.java +++ b/server/src/main/java/org/elasticsearch/features/FeatureInfrastructureFeatures.java @@ -24,4 +24,9 @@ public class FeatureInfrastructureFeatures implements FeatureSpecification { public Set getFeatures() { return Set.of(FeatureService.FEATURES_SUPPORTED); } + + @Override + public Set getTestFeatures() { + return Set.of(FeatureService.TEST_FEATURES_ENABLED); + } } diff --git a/server/src/main/java/org/elasticsearch/features/FeatureService.java b/server/src/main/java/org/elasticsearch/features/FeatureService.java index 250a4541b0869..1d911a75a4838 100644 --- a/server/src/main/java/org/elasticsearch/features/FeatureService.java +++ b/server/src/main/java/org/elasticsearch/features/FeatureService.java @@ -30,6 +30,7 @@ public class FeatureService { * A feature indicating that node features are supported. */ public static final NodeFeature FEATURES_SUPPORTED = new NodeFeature("features_supported"); + public static final NodeFeature TEST_FEATURES_ENABLED = new NodeFeature("test_features_enabled"); private static final Logger logger = LogManager.getLogger(FeatureService.class); diff --git a/server/src/main/java/org/elasticsearch/features/FeatureSpecification.java b/server/src/main/java/org/elasticsearch/features/FeatureSpecification.java index db69ef00756b8..03f0dd89f172e 100644 --- a/server/src/main/java/org/elasticsearch/features/FeatureSpecification.java +++ b/server/src/main/java/org/elasticsearch/features/FeatureSpecification.java @@ -40,6 +40,16 @@ default Set getFeatures() { return Set.of(); } + /** + * Returns a set of test features that this node supports. + *

+ * These features will only be exposed if the {@code tests.testfeatures.enabled} system property is set. + * This should only be used when deploying test clusters. + */ + default Set getTestFeatures() { + return Set.of(); + } + /** * Returns information on historical features that should be deemed to be present on all nodes * on or above the {@link Version} specified. diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java index 9bc58dd64404e..1d7cc76be165b 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterSpecBuilder.java @@ -19,7 +19,9 @@ public final class DefaultLocalClusterSpecBuilder extends AbstractLocalClusterSp public DefaultLocalClusterSpecBuilder() { super(); - this.apply(c -> c.systemProperty("ingest.geoip.downloader.enabled.default", "false")); + this.apply( + c -> c.systemProperty("ingest.geoip.downloader.enabled.default", "false").systemProperty("tests.testfeatures.enabled", "true") + ); this.apply(new FipsEnabledClusterConfigProvider()); this.settings(new DefaultSettingsProvider()); this.environment(new DefaultEnvironmentProvider());