() {
@Override
public void execute(Task task) {
if (expectedOutputFile.exists() == false) {
- Path relativeOutputPath = project.getRootDir().toPath().relativize(expectedOutputFile.toPath());
+ Path relativeOutputPath = rootDir.toPath().relativize(expectedOutputFile.toPath());
final String message = "Building %s didn't generate expected artifact [%s]. The working branch may be "
+ "out-of-date - try merging in the latest upstream changes to the branch.";
throw new InvalidUserDataException(message.formatted(bwcVersion.get(), relativeOutputPath));
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionDownloadPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionDownloadPlugin.java
index 16c7bf6d32862..f92789f701049 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionDownloadPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionDownloadPlugin.java
@@ -23,16 +23,17 @@
import org.elasticsearch.gradle.internal.info.GlobalBuildInfoPlugin;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.GradleException;
-import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.provider.Provider;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.function.Function;
-import static org.elasticsearch.gradle.util.GradleUtils.projectDependency;
-
/**
* An internal elasticsearch build plugin that registers additional
* distribution resolution strategies to the 'elasticsearch.download-distribution' plugin
@@ -64,18 +65,18 @@ public void apply(Project project) {
*
* BWC versions are resolved as project to projects under `:distribution:bwc`.
*/
- private void registerInternalDistributionResolutions(NamedDomainObjectContainer resolutions) {
- resolutions.register("localBuild", distributionResolution -> distributionResolution.setResolver((project, distribution) -> {
+ private void registerInternalDistributionResolutions(List resolutions) {
+ resolutions.add(new DistributionResolution("local-build", (project, distribution) -> {
if (isCurrentVersion(distribution)) {
// non-external project, so depend on local build
return new ProjectBasedDistributionDependency(
- config -> projectDependency(project, distributionProjectPath(distribution), config)
+ config -> projectDependency(project.getDependencies(), distributionProjectPath(distribution), config)
);
}
return null;
}));
- resolutions.register("bwc", distributionResolution -> distributionResolution.setResolver((project, distribution) -> {
+ resolutions.add(new DistributionResolution("bwc", (project, distribution) -> {
BwcVersions.UnreleasedVersionInfo unreleasedInfo = BuildParams.getBwcVersions()
.unreleasedInfo(Version.fromString(distribution.getVersion()));
if (unreleasedInfo != null) {
@@ -89,7 +90,7 @@ private void registerInternalDistributionResolutions(NamedDomainObjectContainer<
}
String projectConfig = getProjectConfig(distribution, unreleasedInfo);
return new ProjectBasedDistributionDependency(
- (config) -> projectDependency(project, unreleasedInfo.gradleProjectPath(), projectConfig)
+ (config) -> projectDependency(project.getDependencies(), unreleasedInfo.gradleProjectPath(), projectConfig)
);
}
return null;
@@ -116,6 +117,13 @@ private static String getProjectConfig(ElasticsearchDistribution distribution, B
}
}
+ private static Dependency projectDependency(DependencyHandler dependencyHandler, String projectPath, String projectConfig) {
+ Map depConfig = new HashMap<>();
+ depConfig.put("path", projectPath);
+ depConfig.put("configuration", projectConfig);
+ return dependencyHandler.project(depConfig);
+ }
+
private static String distributionProjectPath(ElasticsearchDistribution distribution) {
String projectPath = ":distribution";
if (distribution.getType() == ElasticsearchDistributionTypes.INTEG_TEST_ZIP) {
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/NoticeTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/NoticeTask.java
index 1e2506908d108..751ac92512dad 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/NoticeTask.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/NoticeTask.java
@@ -16,11 +16,11 @@
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.file.SourceDirectorySet;
import org.gradle.api.internal.file.FileOperations;
-import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
@@ -43,7 +43,7 @@
* A task to create a notice file which includes dependencies' notices.
*/
@CacheableTask
-public class NoticeTask extends DefaultTask {
+public abstract class NoticeTask extends DefaultTask {
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
@@ -57,19 +57,17 @@ public class NoticeTask extends DefaultTask {
/**
* Directories to include notices from
*/
- private final ListProperty licensesDirs;
+ @Internal
+ abstract ListProperty getLicenseDirs();
private final FileOperations fileOperations;
- private ObjectFactory objectFactory;
@Inject
- public NoticeTask(BuildLayout buildLayout, ProjectLayout projectLayout, FileOperations fileOperations, ObjectFactory objectFactory) {
- this.objectFactory = objectFactory;
+ public NoticeTask(BuildLayout buildLayout, ProjectLayout projectLayout, FileOperations fileOperations) {
this.fileOperations = fileOperations;
setDescription("Create a notice file from dependencies");
// Default licenses directory is ${projectDir}/licenses (if it exists)
- licensesDirs = objectFactory.listProperty(File.class);
- licensesDirs.add(projectLayout.getProjectDirectory().dir("licenses").getAsFile());
+ getLicenseDirs().add(projectLayout.getProjectDirectory().dir("licenses").getAsFile());
inputFile = new File(buildLayout.getRootDirectory(), "NOTICE.txt");
outputFile = projectLayout.getBuildDirectory().dir("notices/" + getName()).get().file("NOTICE.txt").getAsFile();
}
@@ -78,7 +76,7 @@ public NoticeTask(BuildLayout buildLayout, ProjectLayout projectLayout, FileOper
* Add notices from the specified directory.
*/
public void licensesDir(File licensesDir) {
- licensesDirs.add(licensesDir);
+ getLicenseDirs().add(licensesDir);
}
public void source(Object source) {
@@ -185,7 +183,7 @@ public FileCollection getNoticeFiles() {
}
private List existingLicenseDirs() {
- return licensesDirs.get().stream().filter(d -> d.exists()).collect(Collectors.toList());
+ return getLicenseDirs().get().stream().filter(d -> d.exists()).collect(Collectors.toList());
}
@InputFiles
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java
index b32c566363e88..cafa02941d77c 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java
@@ -28,22 +28,14 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
ListMultimap, String> map = ArrayListMultimap.create(1, 200);
map.put(LegacyRestTestBasePlugin.class, ":docs");
map.put(LegacyRestTestBasePlugin.class, ":distribution:docker");
- map.put(LegacyRestTestBasePlugin.class, ":modules:analysis-common");
- map.put(LegacyRestTestBasePlugin.class, ":modules:ingest-attachment");
- map.put(LegacyRestTestBasePlugin.class, ":modules:ingest-common");
- map.put(LegacyRestTestBasePlugin.class, ":modules:ingest-user-agent");
- map.put(LegacyRestTestBasePlugin.class, ":modules:kibana");
map.put(LegacyRestTestBasePlugin.class, ":modules:lang-expression");
map.put(LegacyRestTestBasePlugin.class, ":modules:lang-mustache");
- map.put(LegacyRestTestBasePlugin.class, ":modules:lang-painless");
map.put(LegacyRestTestBasePlugin.class, ":modules:mapper-extras");
map.put(LegacyRestTestBasePlugin.class, ":modules:parent-join");
map.put(LegacyRestTestBasePlugin.class, ":modules:percolator");
map.put(LegacyRestTestBasePlugin.class, ":modules:rank-eval");
map.put(LegacyRestTestBasePlugin.class, ":modules:reindex");
- map.put(LegacyRestTestBasePlugin.class, ":modules:repository-s3");
map.put(LegacyRestTestBasePlugin.class, ":modules:repository-url");
- map.put(LegacyRestTestBasePlugin.class, ":modules:runtime-fields-common");
map.put(LegacyRestTestBasePlugin.class, ":modules:transport-netty4");
map.put(LegacyRestTestBasePlugin.class, ":plugins:analysis-icu");
map.put(LegacyRestTestBasePlugin.class, ":plugins:analysis-kuromoji");
@@ -74,14 +66,13 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":qa:system-indices");
map.put(LegacyRestTestBasePlugin.class, ":qa:unconfigured-node-name");
map.put(LegacyRestTestBasePlugin.class, ":qa:verify-version-constants");
+ map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-apm-integration");
map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-delayed-aggs");
map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-die-with-dignity");
- map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-apm-integration");
map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-error-query");
map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-latency-simulating-directory");
map.put(LegacyRestTestBasePlugin.class, ":test:external-modules:test-seek-tracking-directory");
map.put(LegacyRestTestBasePlugin.class, ":test:yaml-rest-runner");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin");
map.put(LegacyRestTestBasePlugin.class, ":distribution:archives:integ-test-zip");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:core");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ent-search");
@@ -92,17 +83,13 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:mapper-version");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:vector-tile");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:wildcard");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:kerberos-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:mixed-tier-cluster");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:password-protected-keystore");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:reindex-tests-with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:repository-old-versions");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:rolling-upgrade");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:rolling-upgrade-basic");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:rolling-upgrade-multi-cluster");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:runtime-fields:core-with-mapped");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:runtime-fields:core-with-search");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:saml-idp-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:security-example-spi-extension");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:security-setup-password-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:smoke-test-plugins");
@@ -115,12 +102,10 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:multi-cluster-search-security:legacy-with-basic-license");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:multi-cluster-search-security:legacy-with-full-license");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:multi-cluster-search-security:legacy-with-restricted-trust");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:runtime-fields:with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:third-party:jira");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:third-party:pagerduty");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:qa:third-party:slack");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:async-search:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:async-search:qa:security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:autoscaling:qa:rest");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ccr:qa:downgrade-to-basic-license");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ccr:qa:multi-cluster");
@@ -130,7 +115,6 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ccr:qa:security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:deprecation:qa:early-deprecation-rest");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:deprecation:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:downsample:qa:rest");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:downsample:qa:with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:enrich:qa:rest");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:enrich:qa:rest-with-advanced-security");
@@ -139,55 +123,40 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:eql:qa:ccs-rolling-upgrade");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:eql:qa:correctness");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:eql:qa:mixed-node");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:eql:qa:multi-cluster-with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:esql:qa:security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:esql:qa:server:multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:esql:qa:server:single-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:fleet:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:graph:qa:with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:identity-provider:qa:idp-rest-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ilm:qa:multi-cluster");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ilm:qa:multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ilm:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ilm:qa:with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:basic-multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:disabled");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:ml-with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:multi-cluster-tests-with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:native-multi-node-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:single-node-tests");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:repositories-metering-api:qa:s3");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:hdfs");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:minio");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:s3");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:url");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:operator-privileges-tests");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:profile");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:security-disabled");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:smoke-test-all-realms");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:tls-basic");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:shutdown:qa:multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:shutdown:qa:rolling-upgrade");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:slm:qa:multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:slm:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:slm:qa:with-security");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-based-recoveries:qa:fs");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-based-recoveries:qa:license-enforcing");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-based-recoveries:qa:s3");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:hdfs");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:minio");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:s3");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:multi-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:no-sql");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:single-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:security:with-ssl");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:security:without-ssl");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:mixed-node");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:server:multi-cluster-with-security");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:server:multi-node");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:server:single-node");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:server:security:with-ssl");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:server:security:without-ssl");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:stack:qa:rest");
@@ -197,8 +166,8 @@ private static ListMultimap, String> createLegacyRestTestBasePluginUsag
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:transform:qa:single-node-tests");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:vector-tile:qa:multi-cluster");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:watcher:qa:rest");
- map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:watcher:qa:with-monitoring");
map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:watcher:qa:with-security");
+ map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:esql:qa:server:mixed-cluster");
return map;
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java
index bb0b8dcf04437..d69a355a3595d 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java
@@ -10,6 +10,7 @@
import de.thetaphi.forbiddenapis.Checker;
import de.thetaphi.forbiddenapis.Constants;
+import de.thetaphi.forbiddenapis.ForbiddenApiException;
import de.thetaphi.forbiddenapis.Logger;
import de.thetaphi.forbiddenapis.ParseException;
import groovy.lang.Closure;
@@ -43,6 +44,7 @@
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.TaskAction;
+import org.gradle.api.tasks.VerificationException;
import org.gradle.api.tasks.VerificationTask;
import org.gradle.api.tasks.util.PatternFilterable;
import org.gradle.api.tasks.util.PatternSet;
@@ -469,6 +471,8 @@ public void execute() {
}
checker.run();
writeMarker(getParameters().getSuccessMarker().getAsFile().get());
+ } catch (ForbiddenApiException e) {
+ throw new VerificationException("Forbidden API verification failed", e);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ThirdPartyAuditTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ThirdPartyAuditTask.java
index a25ad34a241d4..d2ba86bb99cf2 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ThirdPartyAuditTask.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ThirdPartyAuditTask.java
@@ -218,7 +218,8 @@ public void runThirdPartyAudit() throws IOException {
if (bogousExcludesCount != 0 && bogousExcludesCount == missingClassExcludes.size() + violationsExcludes.size()) {
logForbiddenAPIsOutput(forbiddenApisOutput);
throw new IllegalStateException(
- "All excluded classes seem to have no issues. This is sometimes an indication that the check silently failed"
+ "All excluded classes seem to have no issues. This is sometimes an indication that the check silently failed "
+ + "or that exclusions are configured unnecessarily"
);
}
assertNoPointlessExclusions("are not missing", missingClassExcludes, missingClasses);
@@ -261,10 +262,6 @@ private void logForbiddenAPIsOutput(String forbiddenApisOutput) {
getLogger().error("Forbidden APIs output:\n{}==end of forbidden APIs==", forbiddenApisOutput);
}
- private void throwNotConfiguredCorrectlyException() {
- throw new IllegalArgumentException("Audit of third party dependencies is not configured correctly");
- }
-
/**
* Ideally we would do unpacking already via artifact transform and keep unpacked jars across builds.
* At the moment transform target folder is not configurable and forbidden CLI only takes one common
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/DistroTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/DistroTestPlugin.java
index bcbe1740630ce..42d3a770dbbcc 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/DistroTestPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/DistroTestPlugin.java
@@ -101,7 +101,7 @@ public void apply(Project project) {
addDistributionSysprop(t, DISTRIBUTION_SYSPROP, distribution::getFilepath);
addDistributionSysprop(t, EXAMPLE_PLUGIN_SYSPROP, () -> examplePlugin.getSingleFile().toString());
t.exclude("**/PackageUpgradeTests.class");
- }, distribution.getArchiveDependencies(), examplePlugin.getDependencies());
+ }, distribution, examplePlugin.getDependencies());
if (distribution.getPlatform() == Platform.WINDOWS) {
windowsTestTasks.add(destructiveTask);
@@ -235,6 +235,7 @@ private static ElasticsearchDistribution createDistro(
d.setBundledJdk(bundledJdk);
}
d.setVersion(version);
+ d.setPreferArchive(true);
});
// Allow us to gracefully omit building Docker distributions if Docker is not available on the system.
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataPlugin.java
new file mode 100644
index 0000000000000..bd9df6d3903ca
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataPlugin.java
@@ -0,0 +1,59 @@
+/*
+ * 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;
+
+import org.elasticsearch.gradle.dependencies.CompileOnlyResolvePlugin;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.TaskProvider;
+
+import java.util.Map;
+
+/**
+ * Extracts historical feature metadata into a machine-readable format for use in backward compatibility testing.
+ */
+public class HistoricalFeaturesMetadataPlugin implements Plugin {
+ public static final String HISTORICAL_FEATURES_JSON = "historical-features.json";
+ public static final String FEATURES_METADATA_TYPE = "features-metadata-json";
+ public static final String FEATURES_METADATA_CONFIGURATION = "featuresMetadata";
+
+ @Override
+ public void apply(Project project) {
+ Configuration featureMetadataExtractorConfig = project.getConfigurations().create("featuresMetadataExtractor", c -> {
+ // Don't bother adding this dependency if the project doesn't exist which simplifies testing
+ if (project.findProject(":test:metadata-extractor") != null) {
+ c.defaultDependencies(d -> d.add(project.getDependencies().project(Map.of("path", ":test:metadata-extractor"))));
+ }
+ });
+
+ SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
+ SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
+
+ TaskProvider generateTask = project.getTasks()
+ .register("generateHistoricalFeaturesMetadata", HistoricalFeaturesMetadataTask.class, task -> {
+ task.setClasspath(
+ featureMetadataExtractorConfig.plus(mainSourceSet.getRuntimeClasspath())
+ .plus(project.getConfigurations().getByName(CompileOnlyResolvePlugin.RESOLVEABLE_COMPILE_ONLY_CONFIGURATION_NAME))
+ );
+ task.getOutputFile().convention(project.getLayout().getBuildDirectory().file(HISTORICAL_FEATURES_JSON));
+ });
+
+ Configuration featuresMetadataArtifactConfig = project.getConfigurations().create(FEATURES_METADATA_CONFIGURATION, c -> {
+ c.setCanBeResolved(false);
+ c.setCanBeConsumed(true);
+ c.attributes(a -> { a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FEATURES_METADATA_TYPE); });
+ });
+
+ project.getArtifacts().add(featuresMetadataArtifactConfig.getName(), generateTask);
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataTask.java
new file mode 100644
index 0000000000000..0891225d1e1ef
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/HistoricalFeaturesMetadataTask.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import org.elasticsearch.gradle.LoggedExec;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.CacheableTask;
+import org.gradle.api.tasks.Classpath;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.process.ExecOperations;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
+import org.gradle.workers.WorkerExecutor;
+
+import javax.inject.Inject;
+
+@CacheableTask
+public abstract class HistoricalFeaturesMetadataTask extends DefaultTask {
+ private FileCollection classpath;
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputFile();
+
+ @Classpath
+ public FileCollection getClasspath() {
+ return classpath;
+ }
+
+ public void setClasspath(FileCollection classpath) {
+ this.classpath = classpath;
+ }
+
+ @Inject
+ public abstract WorkerExecutor getWorkerExecutor();
+
+ @TaskAction
+ public void execute() {
+ getWorkerExecutor().noIsolation().submit(HistoricalFeaturesMetadataWorkAction.class, params -> {
+ params.getClasspath().setFrom(getClasspath());
+ params.getOutputFile().set(getOutputFile());
+ });
+ }
+
+ public interface HistoricalFeaturesWorkParameters extends WorkParameters {
+ ConfigurableFileCollection getClasspath();
+
+ RegularFileProperty getOutputFile();
+ }
+
+ public abstract static class HistoricalFeaturesMetadataWorkAction implements WorkAction {
+ private final ExecOperations execOperations;
+
+ @Inject
+ public HistoricalFeaturesMetadataWorkAction(ExecOperations execOperations) {
+ this.execOperations = execOperations;
+ }
+
+ @Override
+ public void execute() {
+ LoggedExec.javaexec(execOperations, spec -> {
+ spec.getMainClass().set("org.elasticsearch.extractor.features.HistoricalFeaturesMetadataExtractor");
+ spec.classpath(getParameters().getClasspath());
+ spec.args(getParameters().getOutputFile().get().getAsFile().getAbsolutePath());
+ });
+ }
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java
index eacc5da6220ab..b29efbfab069f 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java
@@ -22,9 +22,12 @@
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
+import org.gradle.api.Task;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.ProviderFactory;
+import org.gradle.api.specs.NotSpec;
+import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Sync;
import org.gradle.api.tasks.bundling.Zip;
@@ -47,6 +50,7 @@ public class LegacyRestTestBasePlugin implements Plugin {
private static final String TESTS_CLUSTER_REMOTE_ACCESS = "tests.cluster.remote_access";
private ProviderFactory providerFactory;
+ private Project project;
@Inject
public LegacyRestTestBasePlugin(ProviderFactory providerFactory) {
@@ -55,6 +59,7 @@ public LegacyRestTestBasePlugin(ProviderFactory providerFactory) {
@Override
public void apply(Project project) {
+ this.project = project;
Provider serviceProvider = project.getGradle()
.getSharedServices()
.registerIfAbsent("restrictedBuildAPI", RestrictedBuildApiService.class, spec -> {
@@ -118,9 +123,26 @@ public void apply(Project project) {
t.getClusters().forEach(c -> c.plugin(bundle));
}
});
+ configureCacheability(t);
});
}
+ private void configureCacheability(StandaloneRestIntegTestTask testTask) {
+ Spec taskSpec = task -> testTask.getClusters().stream().anyMatch(ElasticsearchCluster::isShared);
+ testTask.getOutputs()
+ .doNotCacheIf(
+ "Caching disabled for this task since it uses a cluster shared by other tasks",
+ /*
+ * Look for any other tasks which use the same cluster as this task. Since tests often have side effects for the cluster
+ * they execute against, this state can cause issues when trying to cache tests results of tasks that share a cluster. To
+ * avoid any undesired behavior we simply disable the cache if we detect that this task uses a cluster shared between
+ * multiple tasks.
+ */
+ taskSpec
+ );
+ testTask.getOutputs().upToDateWhen(new NotSpec(taskSpec));
+ }
+
private String systemProperty(String propName) {
return providerFactory.systemProperty(propName).getOrNull();
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
index 524f3dfedf95f..833c7ad546a4a 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
@@ -85,7 +85,7 @@ public void apply(Project project) {
NamedDomainObjectContainer clusters = (NamedDomainObjectContainer) project
.getExtensions()
.getByName(TestClustersPlugin.EXTENSION_NAME);
- clusters.all(c -> {
+ clusters.configureEach(c -> {
if (BuildParams.isInFipsJvm()) {
c.setting("xpack.security.transport.ssl.key", "test-node.key");
c.keystore("xpack.security.transport.ssl.secure_key_passphrase", "test-node-key-password");
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java
index c602a50c2adb8..a7e72b55f9117 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java
@@ -21,6 +21,7 @@
import org.elasticsearch.gradle.internal.ElasticsearchTestBasePlugin;
import org.elasticsearch.gradle.internal.InternalDistributionDownloadPlugin;
import org.elasticsearch.gradle.internal.info.BuildParams;
+import org.elasticsearch.gradle.internal.test.HistoricalFeaturesMetadataPlugin;
import org.elasticsearch.gradle.plugin.BasePluginBuildPlugin;
import org.elasticsearch.gradle.plugin.PluginBuildPlugin;
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension;
@@ -35,9 +36,12 @@
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
import org.gradle.api.attributes.Attribute;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.tasks.ClasspathNormalizer;
@@ -72,6 +76,9 @@ public class RestTestBasePlugin implements Plugin {
private static final String PLUGINS_CONFIGURATION = "clusterPlugins";
private static final String EXTRACTED_PLUGINS_CONFIGURATION = "extractedPlugins";
private static final Attribute CONFIGURATION_ATTRIBUTE = Attribute.of("test-cluster-artifacts", String.class);
+ private static final String FEATURES_METADATA_CONFIGURATION = "featuresMetadataDeps";
+ private static final String DEFAULT_DISTRO_FEATURES_METADATA_CONFIGURATION = "defaultDistrofeaturesMetadataDeps";
+ private static final String TESTS_FEATURES_METADATA_PATH = "tests.features.metadata.path";
private final ProviderFactory providerFactory;
@@ -105,6 +112,36 @@ public void apply(Project project) {
extractedPluginsConfiguration.extendsFrom(pluginsConfiguration);
configureArtifactTransforms(project);
+ // Create configuration for aggregating historical feature metadata
+ FileCollection featureMetadataConfig = project.getConfigurations().create(FEATURES_METADATA_CONFIGURATION, c -> {
+ c.setCanBeConsumed(false);
+ c.setCanBeResolved(true);
+ c.attributes(
+ a -> a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, HistoricalFeaturesMetadataPlugin.FEATURES_METADATA_TYPE)
+ );
+ c.defaultDependencies(d -> d.add(project.getDependencies().project(Map.of("path", ":server"))));
+ c.withDependencies(dependencies -> {
+ // We can't just use Configuration#extendsFrom() here as we'd inherit the wrong project configuration
+ copyDependencies(project, dependencies, modulesConfiguration);
+ copyDependencies(project, dependencies, pluginsConfiguration);
+ });
+ });
+
+ FileCollection defaultDistroFeatureMetadataConfig = project.getConfigurations()
+ .create(DEFAULT_DISTRO_FEATURES_METADATA_CONFIGURATION, c -> {
+ c.setCanBeConsumed(false);
+ c.setCanBeResolved(true);
+ c.attributes(
+ a -> a.attribute(
+ ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE,
+ HistoricalFeaturesMetadataPlugin.FEATURES_METADATA_TYPE
+ )
+ );
+ c.defaultDependencies(
+ d -> d.add(project.getDependencies().project(Map.of("path", ":distribution", "configuration", "featuresMetadata")))
+ );
+ });
+
// 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())) {
@@ -122,6 +159,10 @@ public void apply(Project project) {
task.dependsOn(integTestDistro, modulesConfiguration);
registerDistributionInputs(task, integTestDistro);
+ // Pass feature metadata on to tests
+ task.getInputs().files(featureMetadataConfig).withPathSensitivity(PathSensitivity.NONE);
+ nonInputSystemProperties.systemProperty(TESTS_FEATURES_METADATA_PATH, () -> featureMetadataConfig.getAsPath());
+
// Enable parallel execution for these tests since each test gets its own cluster
task.setMaxParallelForks(task.getProject().getGradle().getStartParameter().getMaxWorkerCount() / 2);
nonInputSystemProperties.systemProperty(TESTS_MAX_PARALLEL_FORKS_SYSPROP, () -> String.valueOf(task.getMaxParallelForks()));
@@ -134,16 +175,20 @@ public void apply(Project project) {
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);
+ var modulePath = project.getObjects().fileCollection().from(modulesConfiguration);
+ nonInputSystemProperties.systemProperty(TESTS_CLUSTER_MODULES_PATH_SYSPROP, modulePath::getAsPath);
+ registerConfigurationInputs(task, modulesConfiguration.getName(), modulePath);
+ var pluginPath = project.getObjects().fileCollection().from(pluginsConfiguration);
+ nonInputSystemProperties.systemProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP, pluginPath::getAsPath);
+ registerConfigurationInputs(
+ task,
+ extractedPluginsConfiguration.getName(),
+ project.getObjects().fileCollection().from(extractedPluginsConfiguration)
+ );
// Wire up integ-test distribution by default for all test tasks
- nonInputSystemProperties.systemProperty(
- INTEG_TEST_DISTRIBUTION_SYSPROP,
- () -> integTestDistro.getExtracted().getSingleFile().getPath()
- );
+ FileCollection extracted = integTestDistro.getExtracted();
+ nonInputSystemProperties.systemProperty(INTEG_TEST_DISTRIBUTION_SYSPROP, () -> extracted.getSingleFile().getPath());
nonInputSystemProperties.systemProperty(TESTS_RUNTIME_JAVA_SYSPROP, BuildParams.getRuntimeJavaHome());
// Add `usesDefaultDistribution()` extension method to test tasks to indicate they require the default distro
@@ -157,6 +202,11 @@ public Void call(Object... args) {
DEFAULT_DISTRIBUTION_SYSPROP,
providerFactory.provider(() -> defaultDistro.getExtracted().getSingleFile().getPath())
);
+
+ // If we are using the default distribution we need to register all module feature metadata
+ task.getInputs().files(defaultDistroFeatureMetadataConfig).withPathSensitivity(PathSensitivity.NONE);
+ nonInputSystemProperties.systemProperty(TESTS_FEATURES_METADATA_PATH, defaultDistroFeatureMetadataConfig::getAsPath);
+
return null;
}
});
@@ -192,6 +242,14 @@ public Void call(Object... args) {
});
}
+ private void copyDependencies(Project project, DependencySet dependencies, Configuration configuration) {
+ configuration.getDependencies()
+ .stream()
+ .filter(d -> d instanceof ProjectDependency)
+ .map(d -> project.getDependencies().project(Map.of("path", ((ProjectDependency) d).getDependencyProject().getPath())))
+ .forEach(dependencies::add);
+ }
+
private ElasticsearchDistribution createDistribution(Project project, String name, String version) {
return createDistribution(project, name, version, null);
}
@@ -216,15 +274,15 @@ private FileTree getDistributionFiles(ElasticsearchDistribution distribution, Ac
return distribution.getExtracted().getAsFileTree().matching(patternFilter);
}
- private void registerConfigurationInputs(Task task, Configuration configuration) {
+ private void registerConfigurationInputs(Task task, String configurationName, ConfigurableFileCollection configuration) {
task.getInputs()
.files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar") == false)))
- .withPropertyName(configuration.getName() + "-files")
+ .withPropertyName(configurationName + "-files")
.withPathSensitivity(PathSensitivity.RELATIVE);
task.getInputs()
.files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar"))))
- .withPropertyName(configuration.getName() + "-classpath")
+ .withPropertyName(configurationName + "-classpath")
.withNormalizer(ClasspathNormalizer.class);
}
diff --git a/build-tools-internal/src/main/resources/fips_java.policy b/build-tools-internal/src/main/resources/fips_java.policy
index 4ef62e03c2546..bbfc1caf7593a 100644
--- a/build-tools-internal/src/main/resources/fips_java.policy
+++ b/build-tools-internal/src/main/resources/fips_java.policy
@@ -1,6 +1,10 @@
grant {
permission java.security.SecurityPermission "putProviderProperty.BCFIPS";
permission java.security.SecurityPermission "putProviderProperty.BCJSSE";
+ permission java.security.SecurityPermission "getProperty.keystore.type.compat";
+ permission java.security.SecurityPermission "getProperty.jdk.tls.disabledAlgorithms";
+ permission java.security.SecurityPermission "getProperty.jdk.certpath.disabledAlgorithms";
+ permission java.security.SecurityPermission "getProperty.jdk.tls.server.defaultDHEParameters";
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.util.PropertyPermission "java.runtime.name", "read";
permission org.bouncycastle.crypto.CryptoServicesPermission "tlsAlgorithmsEnabled";
diff --git a/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt b/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
index 34f39bbc4ca54..48c888acd35e2 100644
--- a/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
+++ b/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
@@ -158,6 +158,8 @@ org.elasticsearch.cluster.ClusterState#compatibilityVersions()
@defaultMessage ClusterFeatures#nodeFeatures is for internal use only. Use FeatureService#clusterHasFeature to determine if a feature is present on the cluster.
org.elasticsearch.cluster.ClusterFeatures#nodeFeatures()
+@defaultMessage ClusterFeatures#allNodeFeatures is for internal use only. Use FeatureService#clusterHasFeature to determine if a feature is present on the cluster.
+org.elasticsearch.cluster.ClusterFeatures#allNodeFeatures()
@defaultMessage ClusterFeatures#clusterHasFeature is for internal use only. Use FeatureService#clusterHasFeature to determine if a feature is present on the cluster.
org.elasticsearch.cluster.ClusterFeatures#clusterHasFeature(org.elasticsearch.features.NodeFeature)
diff --git a/build-tools-internal/version.properties b/build-tools-internal/version.properties
index dc43523b747b3..98d3ad1eff10b 100644
--- a/build-tools-internal/version.properties
+++ b/build-tools-internal/version.properties
@@ -20,10 +20,9 @@ google_oauth_client = 1.34.1
antlr4 = 4.11.1
# when updating this version, you need to ensure compatibility with:
-# - modules/ingest-attachment (transitive dependency, check the upstream POM)
# - distribution/tools/plugin-cli
# - x-pack/plugin/security
-bouncycastle=1.64
+bouncycastle=1.76
# used by security and idp (need to be in sync due to cross-dependency in testing)
opensaml = 4.3.0
@@ -42,6 +41,12 @@ junit5 = 5.7.1
hamcrest = 2.1
mocksocket = 1.2
+# test container dependencies
+testcontainer = 1.19.2
+dockerJava = 3.3.4
+ductTape = 1.0.8
+commonsCompress = 1.24.0
+
# benchmark dependencies
jmh = 1.26
diff --git a/build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy b/build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy
index 6b662b8165034..22efa8d08d3e7 100644
--- a/build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy
+++ b/build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy
@@ -34,7 +34,7 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
id 'elasticsearch.testclusters'
}
- class SomeClusterAwareTask extends DefaultTask implements TestClustersAware {
+ abstract class SomeClusterAwareTask extends DefaultTask implements TestClustersAware {
private Collection clusters = new HashSet<>();
@@ -166,7 +166,7 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
then:
result.output.contains("Task ':myTask' is not up-to-date because:\n" +
- " Input property 'clusters.myCluster\$0.nodes.\$0.$propertyName'")
+ " Input property 'clusters.myCluster\$0.$propertyName'")
result.output.contains("elasticsearch-keystore script executed!")
assertEsOutputContains("myCluster", "Starting Elasticsearch process")
assertEsOutputContains("myCluster", "Stopping node")
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java
index d08dc469e5ba5..fb8416b24d052 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java
@@ -11,6 +11,7 @@
import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes;
import org.elasticsearch.gradle.transform.SymbolicLinkPreservingUntarTransform;
import org.elasticsearch.gradle.transform.UnzipTransform;
+import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
@@ -22,7 +23,8 @@
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
-import java.util.Comparator;
+import java.util.ArrayList;
+import java.util.List;
import javax.inject.Inject;
@@ -42,9 +44,10 @@ public class DistributionDownloadPlugin implements Plugin {
private static final String DOWNLOAD_REPO_NAME = "elasticsearch-downloads";
private static final String SNAPSHOT_REPO_NAME = "elasticsearch-snapshots";
public static final String DISTRO_EXTRACTED_CONFIG_PREFIX = "es_distro_extracted_";
+ public static final String DISTRO_CONFIG_PREFIX = "es_distro_file_";
private NamedDomainObjectContainer distributionsContainer;
- private NamedDomainObjectContainer distributionsResolutionStrategiesContainer;
+ private List distributionsResolutionStrategies;
private Property dockerAvailability;
@@ -76,8 +79,9 @@ public void apply(Project project) {
}
private void setupDistributionContainer(Project project, Property dockerAvailable) {
+
distributionsContainer = project.container(ElasticsearchDistribution.class, name -> {
- Configuration fileConfiguration = project.getConfigurations().create("es_distro_file_" + name);
+ Configuration fileConfiguration = project.getConfigurations().create(DISTRO_CONFIG_PREFIX + name);
Configuration extractedConfiguration = project.getConfigurations().create(DISTRO_EXTRACTED_CONFIG_PREFIX + name);
extractedConfiguration.getAttributes()
.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE);
@@ -85,21 +89,17 @@ private void setupDistributionContainer(Project project, Property docke
name,
project.getObjects(),
dockerAvailability,
- fileConfiguration,
- extractedConfiguration,
- (dist) -> finalizeDistributionDependencies(project, dist)
+ project.getObjects().fileCollection().from(fileConfiguration),
+ project.getObjects().fileCollection().from(extractedConfiguration),
+ new FinalizeDistributionAction(distributionsResolutionStrategies, project)
);
});
project.getExtensions().add(CONTAINER_NAME, distributionsContainer);
}
private void setupResolutionsContainer(Project project) {
- distributionsResolutionStrategiesContainer = project.container(DistributionResolution.class);
- // We want this ordered in the same resolution strategies are added
- distributionsResolutionStrategiesContainer.whenObjectAdded(
- resolveDependencyNotation -> resolveDependencyNotation.setPriority(distributionsResolutionStrategiesContainer.size())
- );
- project.getExtensions().add(RESOLUTION_CONTAINER_NAME, distributionsResolutionStrategiesContainer);
+ distributionsResolutionStrategies = new ArrayList<>();
+ project.getExtensions().add(RESOLUTION_CONTAINER_NAME, distributionsResolutionStrategies);
}
@SuppressWarnings("unchecked")
@@ -108,30 +108,8 @@ public static NamedDomainObjectContainer getContainer
}
@SuppressWarnings("unchecked")
- public static NamedDomainObjectContainer getRegistrationsContainer(Project project) {
- return (NamedDomainObjectContainer) project.getExtensions().getByName(RESOLUTION_CONTAINER_NAME);
- }
-
- private void finalizeDistributionDependencies(Project project, ElasticsearchDistribution distribution) {
- DependencyHandler dependencies = project.getDependencies();
- // for the distribution as a file, just depend on the artifact directly
- DistributionDependency distributionDependency = resolveDependencyNotation(project, distribution);
- dependencies.add(distribution.configuration.getName(), distributionDependency.getDefaultNotation());
- // no extraction needed for rpm, deb or docker
- if (distribution.getType().shouldExtract()) {
- // The extracted configuration depends on the artifact directly but has
- // an artifact transform registered to resolve it as an unpacked folder.
- dependencies.add(distribution.getExtracted().getName(), distributionDependency.getExtractedNotation());
- }
- }
-
- private DistributionDependency resolveDependencyNotation(Project p, ElasticsearchDistribution distribution) {
- return distributionsResolutionStrategiesContainer.stream()
- .sorted(Comparator.comparingInt(DistributionResolution::getPriority))
- .map(r -> r.getResolver().resolve(p, distribution))
- .filter(d -> d != null)
- .findFirst()
- .orElseGet(() -> DistributionDependency.of(dependencyNotation(distribution)));
+ public static List getRegistrationsContainer(Project project) {
+ return (List) project.getExtensions().getByName(RESOLUTION_CONTAINER_NAME);
}
private static void addIvyRepo(Project project, String name, String url, String group) {
@@ -155,22 +133,53 @@ private static void setupDownloadServiceRepo(Project project) {
addIvyRepo(project, SNAPSHOT_REPO_NAME, "https://snapshots-no-kpi.elastic.co", FAKE_SNAPSHOT_IVY_GROUP);
}
- /**
- * Returns a dependency object representing the given distribution.
- *
- * The returned object is suitable to be passed to {@link DependencyHandler}.
- * The concrete type of the object will be a set of maven coordinates as a {@link String}.
- * Maven coordinates point to either the integ-test-zip coordinates on maven central, or a set of artificial
- * coordinates that resolve to the Elastic download service through an ivy repository.
- */
- private String dependencyNotation(ElasticsearchDistribution distribution) {
- if (distribution.getType() == ElasticsearchDistributionTypes.INTEG_TEST_ZIP) {
- return "org.elasticsearch.distribution.integ-test-zip:elasticsearch:" + distribution.getVersion() + "@zip";
+ private record FinalizeDistributionAction(List resolutionList, Project project)
+ implements
+ Action {
+ @Override
+
+ public void execute(ElasticsearchDistribution distro) {
+ finalizeDistributionDependencies(project, distro);
+ }
+
+ private void finalizeDistributionDependencies(Project project, ElasticsearchDistribution distribution) {
+ // for the distribution as a file, just depend on the artifact directly
+ DistributionDependency distributionDependency = resolveDependencyNotation(project, distribution);
+ project.getDependencies().add(DISTRO_CONFIG_PREFIX + distribution.getName(), distributionDependency.getDefaultNotation());
+ // no extraction needed for rpm, deb or docker
+ if (distribution.getType().shouldExtract()) {
+ // The extracted configuration depends on the artifact directly but has
+ // an artifact transform registered to resolve it as an unpacked folder.
+ project.getDependencies()
+ .add(DISTRO_EXTRACTED_CONFIG_PREFIX + distribution.getName(), distributionDependency.getExtractedNotation());
+ }
+ }
+
+ private DistributionDependency resolveDependencyNotation(Project project, ElasticsearchDistribution distro) {
+ return resolutionList.stream()
+ .map(r -> r.getResolver().resolve(project, distro))
+ .filter(d -> d != null)
+ .findFirst()
+ .orElseGet(() -> DistributionDependency.of(dependencyNotation(distro)));
+ }
+
+ /**
+ * Returns a dependency object representing the given distribution.
+ *
+ * The returned object is suitable to be passed to {@link DependencyHandler}.
+ * The concrete type of the object will be a set of maven coordinates as a {@link String}.
+ * Maven coordinates point to either the integ-test-zip coordinates on maven central, or a set of artificial
+ * coordinates that resolve to the Elastic download service through an ivy repository.
+ */
+ private String dependencyNotation(ElasticsearchDistribution distribution) {
+ if (distribution.getType() == ElasticsearchDistributionTypes.INTEG_TEST_ZIP) {
+ return "org.elasticsearch.distribution.integ-test-zip:elasticsearch:" + distribution.getVersion() + "@zip";
+ }
+ Version distroVersion = Version.fromString(distribution.getVersion());
+ String extension = distribution.getType().getExtension(distribution.getPlatform());
+ String classifier = distribution.getType().getClassifier(distribution.getPlatform(), distroVersion);
+ String group = distribution.getVersion().endsWith("-SNAPSHOT") ? FAKE_SNAPSHOT_IVY_GROUP : FAKE_IVY_GROUP;
+ return group + ":elasticsearch" + ":" + distribution.getVersion() + classifier + "@" + extension;
}
- Version distroVersion = Version.fromString(distribution.getVersion());
- String extension = distribution.getType().getExtension(distribution.getPlatform());
- String classifier = distribution.getType().getClassifier(distribution.getPlatform(), distroVersion);
- String group = distribution.getVersion().endsWith("-SNAPSHOT") ? FAKE_SNAPSHOT_IVY_GROUP : FAKE_IVY_GROUP;
- return group + ":elasticsearch" + ":" + distribution.getVersion() + classifier + "@" + extension;
}
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionResolution.java b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionResolution.java
index 3b82c9f6975a0..0d8177dea5cb6 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionResolution.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionResolution.java
@@ -12,9 +12,14 @@
public class DistributionResolution {
private Resolver resolver;
- private String name;
+ private final String name;
private int priority;
+ public DistributionResolution(String name, Resolver resolver) {
+ this(name);
+ this.resolver = resolver;
+ }
+
public DistributionResolution(String name) {
this.name = name;
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/ElasticsearchDistribution.java b/build-tools/src/main/java/org/elasticsearch/gradle/ElasticsearchDistribution.java
index 5350b6698cb30..fab6926008d6c 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/ElasticsearchDistribution.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/ElasticsearchDistribution.java
@@ -11,7 +11,8 @@
import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes;
import org.gradle.api.Action;
import org.gradle.api.Buildable;
-import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.FileCollection;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.TaskDependency;
@@ -44,7 +45,7 @@ public String toString() {
private final String name;
private final Property dockerAvailability;
// pkg private so plugin can configure
- final Configuration configuration;
+ final FileCollection configuration;
private final Property architecture;
private final Property version;
@@ -52,16 +53,17 @@ public String toString() {
private final Property platform;
private final Property bundledJdk;
private final Property failIfUnavailable;
- private final Configuration extracted;
- private Action distributionFinalizer;
+ private final Property preferArchive;
+ private final ConfigurableFileCollection extracted;
+ private transient Action distributionFinalizer;
private boolean frozen = false;
ElasticsearchDistribution(
String name,
ObjectFactory objectFactory,
Property dockerAvailability,
- Configuration fileConfiguration,
- Configuration extractedConfiguration,
+ ConfigurableFileCollection fileConfiguration,
+ ConfigurableFileCollection extractedConfiguration,
Action distributionFinalizer
) {
this.name = name;
@@ -74,6 +76,7 @@ public String toString() {
this.platform = objectFactory.property(Platform.class);
this.bundledJdk = objectFactory.property(Boolean.class);
this.failIfUnavailable = objectFactory.property(Boolean.class).convention(true);
+ this.preferArchive = objectFactory.property(Boolean.class).convention(false);
this.extracted = extractedConfiguration;
this.distributionFinalizer = distributionFinalizer;
}
@@ -140,6 +143,14 @@ public void setFailIfUnavailable(boolean failIfUnavailable) {
this.failIfUnavailable.set(failIfUnavailable);
}
+ public boolean getPreferArchive() {
+ return preferArchive.get();
+ }
+
+ public void setPreferArchive(boolean preferArchive) {
+ this.preferArchive.set(preferArchive);
+ }
+
public void setArchitecture(Architecture architecture) {
this.architecture.set(architecture);
}
@@ -172,7 +183,7 @@ public String getFilepath() {
return configuration.getSingleFile().toString();
}
- public Configuration getExtracted() {
+ public ConfigurableFileCollection getExtracted() {
if (getType().shouldExtract() == false) {
throw new UnsupportedOperationException(
"distribution type [" + getType().getName() + "] for " + "elasticsearch distribution [" + name + "] cannot be extracted"
@@ -187,7 +198,9 @@ public TaskDependency getBuildDependencies() {
return task -> Collections.emptySet();
} else {
maybeFreeze();
- return getType().shouldExtract() ? extracted.getBuildDependencies() : configuration.getBuildDependencies();
+ return getType().shouldExtract() && (preferArchive.get() == false)
+ ? extracted.getBuildDependencies()
+ : configuration.getBuildDependencies();
}
}
@@ -252,13 +265,4 @@ void finalizeValues() {
type.finalizeValue();
bundledJdk.finalizeValue();
}
-
- public TaskDependency getArchiveDependencies() {
- if (skippingDockerDistributionBuild()) {
- return task -> Collections.emptySet();
- } else {
- maybeFreeze();
- return configuration.getBuildDependencies();
- }
- }
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/DefaultTestClustersTask.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/DefaultTestClustersTask.java
index 5c98ab3bf4364..e80d2ed64cabd 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/DefaultTestClustersTask.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/DefaultTestClustersTask.java
@@ -12,7 +12,7 @@
import java.util.Collection;
import java.util.HashSet;
-public class DefaultTestClustersTask extends DefaultTask implements TestClustersAware {
+public abstract class DefaultTestClustersTask extends DefaultTask implements TestClustersAware {
private Collection clusters = new HashSet<>();
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
index f6705bdb62faa..bf539efaf3c30 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
@@ -14,7 +14,11 @@
import org.gradle.api.Named;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
import org.gradle.api.file.ArchiveOperations;
+import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileSystemOperations;
import org.gradle.api.file.RegularFile;
@@ -22,10 +26,15 @@
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.provider.Provider;
+import org.gradle.api.tasks.Classpath;
+import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
+import org.gradle.api.tasks.PathSensitive;
+import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.Sync;
import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.bundling.Zip;
import org.gradle.process.ExecOperations;
@@ -35,6 +44,8 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.GeneralSecurityException;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -46,6 +57,9 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.EXPLODED_BUNDLE_CONFIG;
+import static org.elasticsearch.gradle.testclusters.TestClustersPlugin.BUNDLE_ATTRIBUTE;
+
public class ElasticsearchCluster implements TestClusterConfiguration, Named {
private static final Logger LOGGER = Logging.getLogger(ElasticsearchNode.class);
@@ -59,7 +73,7 @@ public class ElasticsearchCluster implements TestClusterConfiguration, Named {
private final FileOperations fileOperations;
private final File workingDirBase;
private final LinkedHashMap> waitConditions = new LinkedHashMap<>();
- private final Project project;
+ private final transient Project project;
private final Provider reaper;
private final FileSystemOperations fileSystemOperations;
private final ArchiveOperations archiveOperations;
@@ -68,6 +82,10 @@ public class ElasticsearchCluster implements TestClusterConfiguration, Named {
private final Function isReleasedVersion;
private int nodeIndex = 0;
+ private final ConfigurableFileCollection pluginAndModuleConfiguration;
+
+ private boolean shared = false;
+
public ElasticsearchCluster(
String path,
String clusterName,
@@ -93,6 +111,7 @@ public ElasticsearchCluster(
this.runtimeJava = runtimeJava;
this.isReleasedVersion = isReleasedVersion;
this.nodes = project.container(ElasticsearchNode.class);
+ this.pluginAndModuleConfiguration = project.getObjects().fileCollection();
this.nodes.add(
new ElasticsearchNode(
safeName(clusterName),
@@ -113,6 +132,29 @@ public ElasticsearchCluster(
addWaitForClusterHealth();
}
+ /**
+ * this cluster si marked as shared across TestClusterAware tasks
+ * */
+ @Internal
+ public boolean isShared() {
+ return shared;
+ }
+
+ protected void setShared(boolean shared) {
+ this.shared = shared;
+ }
+
+ @Classpath
+ public FileCollection getInstalledClasspath() {
+ return pluginAndModuleConfiguration.getAsFileTree().filter(f -> f.getName().endsWith(".jar"));
+ }
+
+ @InputFiles
+ @PathSensitive(PathSensitivity.RELATIVE)
+ public FileCollection getInstalledFiles() {
+ return pluginAndModuleConfiguration.getAsFileTree().filter(f -> f.getName().endsWith(".jar") == false);
+ }
+
public void setNumberOfNodes(int numberOfNodes) {
checkFrozen();
@@ -195,34 +237,70 @@ public void setTestDistribution(TestDistribution distribution) {
nodes.all(each -> each.setTestDistribution(distribution));
}
- @Override
- public void plugin(Provider plugin) {
- nodes.all(each -> each.plugin(plugin));
+ private void registerExtractedConfig(Provider pluginProvider) {
+ Dependency pluginDependency = this.project.getDependencies().create(project.files(pluginProvider));
+ Configuration extractedConfig = project.getConfigurations().detachedConfiguration(pluginDependency);
+ extractedConfig.getAttributes().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE);
+ extractedConfig.getAttributes().attribute(BUNDLE_ATTRIBUTE, true);
+ pluginAndModuleConfiguration.from(extractedConfig);
}
@Override
+ public void plugin(String pluginProjectPath) {
+ plugin(maybeCreatePluginOrModuleDependency(pluginProjectPath, "zip"));
+ }
+
public void plugin(TaskProvider plugin) {
- nodes.all(each -> each.plugin(plugin));
+ plugin(plugin.flatMap(AbstractArchiveTask::getArchiveFile));
}
@Override
- public void plugin(String pluginProjectPath) {
- nodes.all(each -> each.plugin(pluginProjectPath));
+ public void plugin(Provider plugin) {
+ registerExtractedConfig(plugin);
+ nodes.all(each -> each.plugin(plugin));
}
@Override
public void module(Provider module) {
+ registerExtractedConfig(module);
nodes.all(each -> each.module(module));
}
- @Override
public void module(TaskProvider module) {
- nodes.all(each -> each.module(module));
+ module(project.getLayout().file(module.map(Sync::getDestinationDir)));
}
@Override
public void module(String moduleProjectPath) {
- nodes.all(each -> each.module(moduleProjectPath));
+ module(maybeCreatePluginOrModuleDependency(moduleProjectPath, EXPLODED_BUNDLE_CONFIG));
+ }
+
+ private final Map pluginAndModuleConfigurations = new HashMap<>();
+
+ // package protected so only TestClustersAware can access
+ @Internal
+ Collection getPluginAndModuleConfigurations() {
+ return pluginAndModuleConfigurations.values();
+ }
+
+ // creates a configuration to depend on the given plugin project, then wraps that configuration
+ // to grab the zip as a file provider
+ private Provider maybeCreatePluginOrModuleDependency(String path, String consumingConfiguration) {
+ var configuration = pluginAndModuleConfigurations.computeIfAbsent(path, key -> {
+ var bundleDependency = this.project.getDependencies().project(Map.of("path", path, "configuration", consumingConfiguration));
+ return project.getConfigurations().detachedConfiguration(bundleDependency);
+ });
+
+ Provider fileProvider = configuration.getElements()
+ .map(
+ s -> s.stream()
+ .findFirst()
+ .orElseThrow(
+ () -> new IllegalStateException(consumingConfiguration + " configuration of project " + path + " had no files")
+ )
+ .getAsFile()
+ );
+ return project.getLayout().file(fileProvider);
}
@Override
@@ -579,4 +657,5 @@ public int hashCode() {
public String toString() {
return "cluster{" + path + ":" + clusterName + "}";
}
+
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
index f0ab67fe51a34..ce4fd7502f417 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
@@ -21,18 +21,12 @@
import org.elasticsearch.gradle.Version;
import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes;
-import org.elasticsearch.gradle.transform.UnzipTransform;
import org.elasticsearch.gradle.util.Pair;
import org.gradle.api.Action;
import org.gradle.api.Named;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
-import org.gradle.api.attributes.Attribute;
import org.gradle.api.file.ArchiveOperations;
-import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileSystemOperations;
import org.gradle.api.file.FileTree;
@@ -52,7 +46,6 @@
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.Sync;
import org.gradle.api.tasks.TaskProvider;
-import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.bundling.Zip;
import org.gradle.api.tasks.util.PatternFilterable;
import org.gradle.process.ExecOperations;
@@ -75,7 +68,6 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -98,7 +90,6 @@
import static java.util.Objects.requireNonNull;
import static java.util.Optional.ofNullable;
-import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.EXPLODED_BUNDLE_CONFIG;
public class ElasticsearchNode implements TestClusterConfiguration {
@@ -130,7 +121,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final String path;
private final String name;
- private final Project project;
+ transient private final Project project;
private final Provider reaperServiceProvider;
private final FileSystemOperations fileSystemOperations;
private final ArchiveOperations archiveOperations;
@@ -140,8 +131,6 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final Path workingDir;
private final LinkedHashMap> waitConditions = new LinkedHashMap<>();
- private final Map pluginAndModuleConfigurations = new HashMap<>();
- private final ConfigurableFileCollection pluginAndModuleConfiguration;
private final List> plugins = new ArrayList<>();
private final List> modules = new ArrayList<>();
private final LazyPropertyMap settings = new LazyPropertyMap<>("Settings", this);
@@ -151,6 +140,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final LazyPropertyMap systemProperties = new LazyPropertyMap<>("System properties", this);
private final LazyPropertyMap environment = new LazyPropertyMap<>("Environment", this);
private final LazyPropertyList jvmArgs = new LazyPropertyList<>("JVM arguments", this);
+ private final LazyPropertyList cliJvmArgs = new LazyPropertyList<>("CLI JVM arguments", this);
private final LazyPropertyMap extraConfigFiles = new LazyPropertyMap<>("Extra config files", this, FileEntry::new);
private final LazyPropertyList extraJarConfigurations = new LazyPropertyList<>("Extra jar files", this);
private final List