Skip to content

Commit bba0330

Browse files
authored
[Gradle/BWC] Patch bundled OpenJdk17 with Adoptium Jdk17 for older ES Distros (elastic#135300) (elastic#135360)
Bundled OpenJDK 17 is incompatible with newer versions of Ubuntu 24.04 (Kernel 6.14.x). We fix our bwc testing on ubuntu 24.04 to explicitly use adoptium jdk 17 in cases where the bundled JDK is older than 21 which is not affected.
1 parent 8552488 commit bba0330

File tree

7 files changed

+224
-22
lines changed

7 files changed

+224
-22
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,14 @@
4444
import org.gradle.api.file.FileCollection;
4545
import org.gradle.api.file.FileTree;
4646
import org.gradle.api.internal.artifacts.dependencies.ProjectDependencyInternal;
47+
import org.gradle.api.plugins.JvmToolchainsPlugin;
4748
import org.gradle.api.provider.ProviderFactory;
4849
import org.gradle.api.tasks.ClasspathNormalizer;
4950
import org.gradle.api.tasks.PathSensitivity;
5051
import org.gradle.api.tasks.util.PatternFilterable;
52+
import org.gradle.jvm.toolchain.JavaLanguageVersion;
53+
import org.gradle.jvm.toolchain.JavaToolchainService;
54+
import org.gradle.jvm.toolchain.JvmVendorSpec;
5155

5256
import java.util.Collection;
5357
import java.util.Iterator;
@@ -59,6 +63,7 @@
5963
import javax.inject.Inject;
6064

6165
import static org.elasticsearch.gradle.internal.util.ParamsUtils.loadBuildParams;
66+
import static org.elasticsearch.gradle.util.OsUtils.jdkIsIncompatibleWithOS;
6267

6368
/**
6469
* Base plugin used for wiring up build tasks to REST testing tasks using new JUnit rule-based test clusters framework.
@@ -93,6 +98,7 @@ public RestTestBasePlugin(ProviderFactory providerFactory) {
9398
public void apply(Project project) {
9499
project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
95100
project.getPluginManager().apply(InternalDistributionDownloadPlugin.class);
101+
project.getPluginManager().apply(JvmToolchainsPlugin.class);
96102
var bwcVersions = loadBuildParams(project).get().getBwcVersions();
97103

98104
// Register integ-test and default distributions
@@ -226,6 +232,17 @@ public Void call(Object... args) {
226232
String versionString = version.toString();
227233
ElasticsearchDistribution bwcDistro = createDistribution(project, "bwc_" + versionString, versionString);
228234

235+
if (jdkIsIncompatibleWithOS(Version.fromString(versionString))) {
236+
var toolChainService = project.getExtensions().getByType(JavaToolchainService.class);
237+
var fallbackJdk17Launcher = toolChainService.launcherFor(spec -> {
238+
spec.getVendor().set(JvmVendorSpec.ADOPTIUM);
239+
spec.getLanguageVersion().set(JavaLanguageVersion.of(17));
240+
});
241+
task.environment(
242+
"ES_FALLBACK_JAVA_HOME",
243+
fallbackJdk17Launcher.get().getMetadata().getInstallationPath().getAsFile().getPath()
244+
);
245+
}
229246
task.dependsOn(bwcDistro);
230247
registerDistributionInputs(task, bwcDistro);
231248

build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99

1010
package org.elasticsearch.gradle
1111

12-
import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
13-
import org.gradle.testkit.runner.GradleRunner
1412
import spock.lang.IgnoreIf
1513
import spock.lang.Unroll
14+
import spock.util.environment.RestoreSystemProperties
15+
16+
import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
17+
import org.gradle.testkit.runner.GradleRunner
1618

17-
import static org.elasticsearch.gradle.fixtures.DistributionDownloadFixture.withChangedClasspathMockedDistributionDownload
18-
import static org.elasticsearch.gradle.fixtures.DistributionDownloadFixture.withChangedConfigMockedDistributionDownload
19-
import static org.elasticsearch.gradle.fixtures.DistributionDownloadFixture.withMockedDistributionDownload
19+
import static org.elasticsearch.gradle.fixtures.DistributionDownloadFixture.*
2020

2121
/**
2222
* We do not have coverage for the test cluster startup on windows yet.
@@ -108,8 +108,8 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
108108
def runningClosure = { GradleRunner r -> r.build() }
109109
withMockedDistributionDownload(runner, runningClosure)
110110
def result = inputProperty == "distributionClasspath" ?
111-
withChangedClasspathMockedDistributionDownload(runner, runningClosure) :
112-
withChangedConfigMockedDistributionDownload(runner, runningClosure)
111+
withChangedClasspathMockedDistributionDownload(runner, runningClosure) :
112+
withChangedConfigMockedDistributionDownload(runner, runningClosure)
113113

114114
then:
115115
result.output.contains("Task ':myTask' is not up-to-date because:\n Input property 'clusters.myCluster\$0.nodes.\$0.$inputProperty'")
@@ -166,18 +166,24 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
166166
}
167167

168168
then:
169-
result.output.contains("Task ':myTask' is not up-to-date because:\n" +
170-
" Input property 'clusters.myCluster\$0.$propertyName'")
169+
result.output.contains(
170+
"Task ':myTask' is not up-to-date because:\n" +
171+
" Input property 'clusters.myCluster\$0.$propertyName'"
172+
)
171173
result.output.contains("elasticsearch-keystore script executed!")
172174
assertEsOutputContains("myCluster", "Starting Elasticsearch process")
173175
assertEsOutputContains("myCluster", "Stopping node")
174176

175177
where:
176178
pluginType | propertyName | fileChange
177-
'module' | "installedFiles" | { def testClazz -> testClazz.file("test-module/src/main/plugin-metadata/someAddedConfig.txt") << "new resource file" }
178-
'plugin' | "installedFiles" | { def testClazz -> testClazz.file("test-plugin/src/main/plugin-metadata/someAddedConfig.txt") << "new resource file" }
179-
'module' | "installedClasspath" | { def testClazz -> testClazz.file("test-module/src/main/java/SomeClass.java") << "class SomeClass {}" }
180-
'plugin' | "installedClasspath" | { def testClazz -> testClazz.file("test-plugin/src/main/java/SomeClass.java") << "class SomeClass {}" }
179+
'module' | "installedFiles" |
180+
{ def testClazz -> testClazz.file("test-module/src/main/plugin-metadata/someAddedConfig.txt") << "new resource file" }
181+
'plugin' | "installedFiles" |
182+
{ def testClazz -> testClazz.file("test-plugin/src/main/plugin-metadata/someAddedConfig.txt") << "new resource file" }
183+
'module' | "installedClasspath" |
184+
{ def testClazz -> testClazz.file("test-module/src/main/java/SomeClass.java") << "class SomeClass {}" }
185+
'plugin' | "installedClasspath" |
186+
{ def testClazz -> testClazz.file("test-plugin/src/main/java/SomeClass.java") << "class SomeClass {}" }
181187
}
182188

183189
def "can declare test cluster in lazy evaluated task configuration block"() {
@@ -232,9 +238,51 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
232238
assertCustomDistro('myCluster')
233239
}
234240

241+
@RestoreSystemProperties
242+
def "override jdk usage via ES_JAVA_HOME for known jdk os incompatibilities"() {
243+
given:
244+
245+
settingsFile.text = """
246+
plugins {
247+
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
248+
}
249+
""" + settingsFile.text
250+
251+
buildFile << """
252+
testClusters {
253+
myCluster {
254+
testDistribution = 'default'
255+
version = '8.10.4'
256+
}
257+
}
258+
259+
// Force linux platform to trigger jdk override
260+
elasticsearch_distributions.forEach { d ->
261+
d.platform = org.elasticsearch.gradle.ElasticsearchDistribution.Platform.LINUX
262+
}
263+
264+
tasks.register('myTask', SomeClusterAwareTask) {
265+
useCluster testClusters.myCluster
266+
}
267+
"""
268+
when:
269+
def result = withMockedDistributionDownload(
270+
"8.10.4",
271+
ElasticsearchDistribution.Platform.LINUX,
272+
gradleRunner("myTask", '-Dos.name=Linux', '-Dos.version=6.14.0-1015-gcp', '-i')
273+
) {
274+
build()
275+
}
276+
277+
then:
278+
result.output.lines().anyMatch { line -> line.startsWith("Running") && line.split().find { it.startsWith("ES_JAVA_HOME=") }.contains("eclipse_adoptium-17") }
279+
}
280+
235281
boolean assertEsOutputContains(String testCluster, String expectedOutput) {
236-
assert new File(testProjectDir.root,
237-
"build/testclusters/${testCluster}-0/logs/es.out").text.contains(expectedOutput)
282+
assert new File(
283+
testProjectDir.root,
284+
"build/testclusters/${testCluster}-0/logs/es.out"
285+
).text.contains(expectedOutput)
238286
true
239287
}
240288

build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.gradle.api.tasks.TaskProvider;
3838
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
3939
import org.gradle.api.tasks.bundling.Zip;
40+
import org.gradle.jvm.toolchain.JavaLauncher;
4041
import org.gradle.process.ExecOperations;
4142

4243
import java.io.File;
@@ -84,6 +85,7 @@ public class ElasticsearchCluster implements TestClusterConfiguration, Named {
8485
private int nodeIndex = 0;
8586

8687
private final ConfigurableFileCollection pluginAndModuleConfiguration;
88+
private final Provider<JavaLauncher> jdk17FallbackLauncher;
8789

8890
private boolean shared = false;
8991

@@ -101,7 +103,8 @@ public ElasticsearchCluster(
101103
FileOperations fileOperations,
102104
File workingDirBase,
103105
Provider<File> runtimeJava,
104-
Function<Version, Boolean> isReleasedVersion
106+
Function<Version, Boolean> isReleasedVersion,
107+
Provider<JavaLauncher> jdk17FallbackLauncher
105108
) {
106109
this.path = path;
107110
this.clusterName = clusterName;
@@ -117,6 +120,7 @@ public ElasticsearchCluster(
117120
this.isReleasedVersion = isReleasedVersion;
118121
this.nodes = project.container(ElasticsearchNode.class);
119122
this.pluginAndModuleConfiguration = project.getObjects().fileCollection();
123+
this.jdk17FallbackLauncher = jdk17FallbackLauncher;
120124
this.nodes.add(
121125
new ElasticsearchNode(
122126
safeName(clusterName),
@@ -131,7 +135,8 @@ public ElasticsearchCluster(
131135
fileOperations,
132136
workingDirBase,
133137
runtimeJava,
134-
isReleasedVersion
138+
isReleasedVersion,
139+
jdk17FallbackLauncher
135140
)
136141
);
137142

@@ -189,7 +194,8 @@ public void setNumberOfNodes(int numberOfNodes) {
189194
fileOperations,
190195
workingDirBase,
191196
runtimeJava,
192-
isReleasedVersion
197+
isReleasedVersion,
198+
jdk17FallbackLauncher
193199
)
194200
);
195201
}

build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.gradle.api.tasks.TaskProvider;
5050
import org.gradle.api.tasks.bundling.Zip;
5151
import org.gradle.api.tasks.util.PatternFilterable;
52+
import org.gradle.jvm.toolchain.JavaLauncher;
5253
import org.gradle.process.ExecOperations;
5354

5455
import java.io.ByteArrayInputStream;
@@ -94,6 +95,7 @@
9495

9596
import static java.util.Objects.requireNonNull;
9697
import static java.util.Optional.ofNullable;
98+
import static org.elasticsearch.gradle.util.OsUtils.jdkIsIncompatibleWithOS;
9799

98100
public class ElasticsearchNode implements TestClusterConfiguration {
99101

@@ -166,6 +168,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
166168
private final Path tmpDir;
167169
private final Provider<File> runtimeJava;
168170
private final Function<Version, Boolean> isReleasedVersion;
171+
private final Provider<JavaLauncher> jdk17FallbackLauncher;
169172
private final List<ElasticsearchDistribution> distributions = new ArrayList<>();
170173
private int currentDistro = 0;
171174
private TestDistribution testDistribution;
@@ -190,7 +193,8 @@ public class ElasticsearchNode implements TestClusterConfiguration {
190193
FileOperations fileOperations,
191194
File workingDirBase,
192195
Provider<File> runtimeJava,
193-
Function<Version, Boolean> isReleasedVersion
196+
Function<Version, Boolean> isReleasedVersion,
197+
Provider<JavaLauncher> jdk17FallbackLauncher
194198
) {
195199
this.path = path;
196200
this.name = name;
@@ -203,6 +207,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
203207
this.fileOperations = fileOperations;
204208
this.runtimeJava = runtimeJava;
205209
this.isReleasedVersion = isReleasedVersion;
210+
this.jdk17FallbackLauncher = jdk17FallbackLauncher;
206211
workingDir = workingDirBase.toPath().resolve(safeName(name)).toAbsolutePath();
207212
confPathRepo = workingDir.resolve("repo");
208213
configFile = workingDir.resolve("config/elasticsearch.yml");
@@ -793,7 +798,19 @@ private Map<String, String> getESEnvironment() {
793798
if (getTestDistribution() == TestDistribution.INTEG_TEST || getVersion().equals(VersionProperties.getElasticsearchVersion())) {
794799
defaultEnv.put("ES_JAVA_HOME", runtimeJava.get().getAbsolutePath());
795800
}
801+
// Older distributions ship with openjdk versions that are not compatible with newer kernels of ubuntu 24.04 and later
802+
// Therefore we pass explicitly the runtime java to use the adoptium jdk that is maintained longer and compatible
803+
// with newer kernels.
804+
// 8.10.4 is the last version shipped with jdk < 21. We configure these cluster to run with jdk 17 adoptium as 17 was
805+
// the last LTS release before 21
806+
else if (jdkIsIncompatibleWithOS(getVersion())) {
807+
defaultEnv.put(
808+
"ES_JAVA_HOME",
809+
jdk17FallbackLauncher.map(j -> j.getMetadata().getInstallationPath().getAsFile().getAbsolutePath()).get()
810+
);
811+
}
796812
defaultEnv.put("ES_PATH_CONF", configFile.getParent().toString());
813+
797814
String systemPropertiesString = "";
798815
if (systemProperties.isEmpty() == false) {
799816
systemPropertiesString = " " + systemProperties.entrySet().stream().peek(entry -> {

build-tools/src/main/java/org/elasticsearch/gradle/testclusters/TestClustersPlugin.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@
2626
import org.gradle.api.invocation.Gradle;
2727
import org.gradle.api.logging.Logger;
2828
import org.gradle.api.logging.Logging;
29+
import org.gradle.api.plugins.JvmToolchainsPlugin;
2930
import org.gradle.api.provider.Property;
3031
import org.gradle.api.provider.Provider;
3132
import org.gradle.api.provider.ProviderFactory;
3233
import org.gradle.api.services.BuildService;
3334
import org.gradle.api.services.BuildServiceParameters;
3435
import org.gradle.build.event.BuildEventsListenerRegistry;
3536
import org.gradle.internal.jvm.Jvm;
37+
import org.gradle.jvm.toolchain.JavaLanguageVersion;
38+
import org.gradle.jvm.toolchain.JavaLauncher;
39+
import org.gradle.jvm.toolchain.JavaToolchainService;
40+
import org.gradle.jvm.toolchain.JvmVendorSpec;
3641
import org.gradle.process.ExecOperations;
3742
import org.gradle.tooling.events.FinishEvent;
3843
import org.gradle.tooling.events.OperationCompletionListener;
@@ -99,11 +104,19 @@ public void setIsReleasedVersion(Function<Version, Boolean> isReleasedVersion) {
99104
@Override
100105
public void apply(Project project) {
101106
project.getPlugins().apply(DistributionDownloadPlugin.class);
107+
project.getPlugins().apply(JvmToolchainsPlugin.class);
102108
project.getRootProject().getPluginManager().apply(ReaperPlugin.class);
103109
Provider<ReaperService> reaperServiceProvider = GradleUtils.getBuildService(
104110
project.getGradle().getSharedServices(),
105111
ReaperPlugin.REAPER_SERVICE_NAME
106112
);
113+
114+
JavaToolchainService toolChainService = project.getExtensions().getByType(JavaToolchainService.class);
115+
Provider<JavaLauncher> fallbackJdk17Launcher = toolChainService.launcherFor(spec -> {
116+
spec.getVendor().set(JvmVendorSpec.ADOPTIUM);
117+
spec.getLanguageVersion().set(JavaLanguageVersion.of(17));
118+
});
119+
107120
runtimeJavaProvider = providerFactory.provider(
108121
() -> System.getenv("RUNTIME_JAVA_HOME") == null ? Jvm.current().getJavaHome() : new File(System.getenv("RUNTIME_JAVA_HOME"))
109122
);
@@ -117,7 +130,8 @@ public void apply(Project project) {
117130
NamedDomainObjectContainer<ElasticsearchCluster> container = createTestClustersContainerExtension(
118131
project,
119132
testClustersRegistryProvider,
120-
reaperServiceProvider
133+
reaperServiceProvider,
134+
fallbackJdk17Launcher
121135
);
122136

123137
// provide a task to be able to list defined clusters.
@@ -154,7 +168,8 @@ private void configureArtifactTransforms(Project project) {
154168
private NamedDomainObjectContainer<ElasticsearchCluster> createTestClustersContainerExtension(
155169
Project project,
156170
Provider<TestClustersRegistry> testClustersRegistryProvider,
157-
Provider<ReaperService> reaper
171+
Provider<ReaperService> reaper,
172+
Provider<JavaLauncher> fallbackJdk17Launcher
158173
) {
159174
// Create an extensions that allows describing clusters
160175
NamedDomainObjectContainer<ElasticsearchCluster> container = project.container(
@@ -171,7 +186,8 @@ private NamedDomainObjectContainer<ElasticsearchCluster> createTestClustersConta
171186
getFileOperations(),
172187
new File(project.getBuildDir(), "testclusters"),
173188
runtimeJavaProvider,
174-
isReleasedVersion
189+
isReleasedVersion,
190+
fallbackJdk17Launcher
175191
)
176192
);
177193
project.getExtensions().add(EXTENSION_NAME, container);

0 commit comments

Comments
 (0)