Skip to content

Commit

Permalink
[Backport] Consolidate docker availability logic (#52656)
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-vieira committed Feb 23, 2020
1 parent 21eea3b commit 4a9aa95
Show file tree
Hide file tree
Showing 9 changed files with 578 additions and 507 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ import java.nio.charset.StandardCharsets
import java.nio.file.Files

import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
import static org.elasticsearch.gradle.tool.DockerUtils.assertDockerIsAvailable
import static org.elasticsearch.gradle.tool.DockerUtils.getDockerPath

/**
* Encapsulates build configuration for elasticsearch projects.
Expand Down Expand Up @@ -208,51 +206,6 @@ class BuildPlugin implements Plugin<Project> {
}
}

static void requireDocker(final Task task) {
final Project rootProject = task.project.rootProject
ExtraPropertiesExtension ext = rootProject.extensions.getByType(ExtraPropertiesExtension)

if (rootProject.hasProperty('requiresDocker') == false) {
/*
* This is our first time encountering a task that requires Docker. We will add an extension that will let us track the tasks
* that register as requiring Docker. We will add a delayed execution that when the task graph is ready if any such tasks are
* in the task graph, then we check two things:
* - the Docker binary is available
* - we can execute a Docker command that requires privileges
*
* If either of these fail, we fail the build.
*/

// check if the Docker binary exists and record its path
final String dockerBinary = getDockerPath().orElse(null)

final boolean buildDocker
final String buildDockerProperty = System.getProperty("build.docker")
if (buildDockerProperty == null) {
buildDocker = dockerBinary != null
} else if (buildDockerProperty == "true") {
buildDocker = true
} else if (buildDockerProperty == "false") {
buildDocker = false
} else {
throw new IllegalArgumentException(
"expected build.docker to be unset or one of \"true\" or \"false\" but was [" + buildDockerProperty + "]")
}

ext.set('buildDocker', buildDocker)
ext.set('requiresDocker', [])
rootProject.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
final List<String> tasks = taskGraph.allTasks.intersect(ext.get('requiresDocker') as List<Task>).collect { " ${it.path}".toString()}

if (tasks.isEmpty() == false) {
assertDockerIsAvailable(task.project, tasks)
}
}
}

(ext.get('requiresDocker') as List<Task>).add(task)
}

/** Add a check before gradle execution phase which ensures java home for the given java version is set. */
static void requireJavaHome(Task task, int version) {
// use root project for global accounting
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.elasticsearch.gradle.docker;

import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.plugins.ExtraPropertiesExtension;
import org.gradle.api.provider.Provider;

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

/**
* Plugin providing {@link DockerSupportService} for detecting Docker installations and determining requirements for Docker-based
* Elasticsearch build tasks.
* <p>
* Additionally registers a task graph listener used to assert a compatible Docker installation exists when task requiring Docker are
* scheduled for execution. Tasks may declare a Docker requirement via an extra property. If a compatible Docker installation is not
* available on the build system an exception will be thrown prior to task execution.
*
* <pre>
* task myDockerTask {
* ext.requiresDocker = true
* }
* </pre>
*/
public class DockerSupportPlugin implements Plugin<Project> {
public static final String DOCKER_SUPPORT_SERVICE_NAME = "dockerSupportService";
public static final String DOCKER_ON_LINUX_EXCLUSIONS_FILE = ".ci/dockerOnLinuxExclusions";
public static final String REQUIRES_DOCKER_ATTRIBUTE = "requiresDocker";

@Override
public void apply(Project project) {
if (project != project.getRootProject()) {
throw new IllegalStateException(this.getClass().getName() + " can only be applied to the root project.");
}

Provider<DockerSupportService> dockerSupportServiceProvider = project.getGradle()
.getSharedServices()
.registerIfAbsent(
DOCKER_SUPPORT_SERVICE_NAME,
DockerSupportService.class,
spec -> spec.parameters(
params -> { params.setExclusionsFile(new File(project.getRootDir(), DOCKER_ON_LINUX_EXCLUSIONS_FILE)); }
)
);

// Ensure that if any tasks declare they require docker, we assert an available Docker installation exists
project.getGradle().getTaskGraph().whenReady(graph -> {
List<String> dockerTasks = graph.getAllTasks().stream().filter(task -> {
ExtraPropertiesExtension ext = task.getExtensions().getExtraProperties();
return ext.has(REQUIRES_DOCKER_ATTRIBUTE) && (boolean) ext.get(REQUIRES_DOCKER_ATTRIBUTE);
}).map(Task::getPath).collect(Collectors.toList());

if (dockerTasks.isEmpty() == false) {
dockerSupportServiceProvider.get().failIfDockerUnavailable(dockerTasks);
}
});
}

}

0 comments on commit 4a9aa95

Please sign in to comment.