Skip to content

Commit

Permalink
Avoid copying test cluster distributions when possible (#93486)
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-vieira committed Feb 7, 2023
1 parent 4e8a77e commit fc78668
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import org.elasticsearch.gradle.Architecture
import org.elasticsearch.gradle.OS
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.internal.test.rest.RestTestBasePlugin
import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask

// gradle has an open issue of failing applying plugins in
// precompiled script plugins (see https://github.com/gradle/gradle/issues/17004)
Expand Down Expand Up @@ -42,4 +44,13 @@ configure(allprojects) {
}
}
}

project.plugins.withType(RestTestBasePlugin) {
tasks.withType(StandaloneRestIntegTestTask).configureEach {
if (BuildParams.getIsRuntimeJavaHomeSet() == false) {
dependsOn(project.jdks.provisioned_runtime)
nonInputProperties.systemProperty("tests.runtime.java", "${-> project.jdks.provisioned_runtime.javaHomePath}")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.elasticsearch.test.cluster.local.distribution.DistributionType.DEFAULT;
import static org.elasticsearch.test.cluster.util.OS.WINDOWS;

public class LocalClusterFactory implements ClusterFactory<LocalClusterSpec, LocalClusterHandle> {
private static final Logger LOGGER = LogManager.getLogger(LocalClusterFactory.class);
private static final Duration NODE_UP_TIMEOUT = Duration.ofMinutes(2);
Expand Down Expand Up @@ -110,11 +113,6 @@ public synchronized void start(Version version) {
LOGGER.info("Creating installation for node '{}' in {}", spec.getName(), workingDir);
distributionDescriptor = resolveDistribution();
LOGGER.info("Distribution for node '{}': {}", spec.getName(), distributionDescriptor);
distributionDir = OS.conditional(
// Use per-version distribution directories on Windows to avoid cleanup failures
c -> c.onWindows(() -> workingDir.resolve("distro").resolve(distributionDescriptor.getVersion().toString()))
.onUnix(() -> workingDir.resolve("distro"))
);
initializeWorkingDirectory(currentVersion != null);
createConfigDirectory();
copyExtraConfigFiles(); // extra config files might be needed for running cli tools like plugin install
Expand Down Expand Up @@ -230,19 +228,32 @@ private List<String> readPortsFile(Path file) {

private void initializeWorkingDirectory(boolean preserveWorkingDirectory) {
try {
if (preserveWorkingDirectory) {
IOUtils.deleteWithRetry(distributionDir);
} else {
if (preserveWorkingDirectory == false) {
IOUtils.deleteWithRetry(workingDir);
}
try {
IOUtils.syncWithLinks(distributionDescriptor.getDistributionDir(), distributionDir);
} catch (IOUtils.LinkCreationException e) {
// Note does not work for network drives, e.g. Vagrant
LOGGER.info("Failed to create working dir using hard links. Falling back to copy", e);
// ensure we get a clean copy
IOUtils.deleteWithRetry(distributionDir);
IOUtils.syncWithCopy(distributionDescriptor.getDistributionDir(), distributionDir);

if (canUseSharedDistribution()) {
distributionDir = distributionDescriptor.getDistributionDir();
} else {
distributionDir = OS.conditional(
// Use per-version distribution directories on Windows to avoid cleanup failures
c -> c.onWindows(() -> workingDir.resolve("distro").resolve(distributionDescriptor.getVersion().toString()))
.onUnix(() -> workingDir.resolve("distro"))
);

if (Files.exists(distributionDir)) {
IOUtils.deleteWithRetry(distributionDir);
}

try {
IOUtils.syncWithLinks(distributionDescriptor.getDistributionDir(), distributionDir);
} catch (IOUtils.LinkCreationException e) {
// Note does not work for network drives, e.g. Vagrant
LOGGER.info("Failed to create working dir using hard links. Falling back to copy", e);
// ensure we get a clean copy
IOUtils.deleteWithRetry(distributionDir);
IOUtils.syncWithCopy(distributionDescriptor.getDistributionDir(), distributionDir);
}
}
Files.createDirectories(repoDir);
Files.createDirectories(dataDir);
Expand All @@ -253,6 +264,16 @@ private void initializeWorkingDirectory(boolean preserveWorkingDirectory) {
}
}

/*
* We can "share" a distribution directory across clusters so long as we aren't modifying it. That means we aren't installing any
* additional plugins, modules, or jars. This avoids having to copy the test distribution unnecessarily.
*/
private boolean canUseSharedDistribution() {
return OS.current() != WINDOWS // Issues with long file paths on Windows in CI
&& System.getProperty(TESTS_CLUSTER_FIPS_JAR_PATH_SYSPROP) == null
&& (distributionDescriptor.getType() == DEFAULT || (getSpec().getPlugins().isEmpty() && getSpec().getModules().isEmpty()));
}

private void copyExtraJarFiles() {
String fipsJarsPath = System.getProperty(TESTS_CLUSTER_FIPS_JAR_PATH_SYSPROP);
if (fipsJarsPath != null) {
Expand Down Expand Up @@ -490,7 +511,7 @@ private void installModule(String moduleName, List<Path> modulePaths) {

});

IOUtils.syncWithCopy(modulePath.getParent(), destination);
IOUtils.syncWithCopy(modulePath, destination);

// Install any extended plugins
Properties pluginProperties = new Properties();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public class DefaultDistributionDescriptor implements DistributionDescriptor {
private final Path distributionDir;
private final DistributionType type;

public DefaultDistributionDescriptor(Version version, boolean snapshot, Path distributionDir, DistributionType type) {
public DefaultDistributionDescriptor(Version version, boolean snapshot, Path extractedDir, DistributionType type) {
this.version = version;
this.snapshot = snapshot;
this.distributionDir = distributionDir;
this.distributionDir = extractedDir;
this.type = type;
}

Expand All @@ -34,7 +34,7 @@ public boolean isSnapshot() {
}

public Path getDistributionDir() {
return distributionDir;
return distributionDir.resolve("elasticsearch-" + version + (snapshot ? "-SNAPSHOT" : ""));
}

public DistributionType getType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,6 @@ private static void sync(Path sourceRoot, Path destinationRoot, BiConsumer<Path,
try (Stream<Path> stream = Files.walk(sourceRoot)) {
stream.forEach(source -> {
Path relativeDestination = sourceRoot.relativize(source);
if (relativeDestination.getNameCount() <= 1) {
return;
}
// Throw away the first name as the archives have everything in a single top level folder we are not interested in
relativeDestination = relativeDestination.subpath(1, relativeDestination.getNameCount());

Path destination = destinationRoot.resolve(relativeDestination);
if (Files.isDirectory(source)) {
Expand Down

0 comments on commit fc78668

Please sign in to comment.