in plugins/docker/base-image/src/main/java/co/elastic/gradle/dockerbase/DockerBaseImageBuildPlugin.java [70:254]
public void apply(@NotNull Project target) {
target.getPluginManager().apply(JFrogPlugin.class);
final BaseImageExtension extension = target.getExtensions().create("dockerBaseImage", BaseImageExtension.class);
final Map<Architecture, Configuration> osPackageConfigurations = Arrays.stream(Architecture.values())
.collect(Collectors.toMap(
Function.identity(),
each -> target.getConfigurations().create("_osPackageRepo_" + each.dockerName())
));
registerPullTask(target, extension);
final Configuration dockerEphemeralConfiguration = target.getConfigurations().create("dockerEphemeral");
Arrays.stream(Architecture.values()).forEach( arch -> {
target.getTasks().register(
BUILD_TASK_NAME + dockerNameIfNotCurrent(arch),
DockerBaseImageBuildTask.class
).configure(task -> {
task.getArchitecture().set(arch);
task.getOSDistribution().set(extension.getOSDistribution());
task.getMirrorRepositories().set(extension.getMirrorRepositories());
task.getLockFile().set(extension.getLockFile());
task.getDockerEphemeralMount().set(extension.getDockerEphemeralMount());
task.getInputInstructions().set(extension.getInstructions());
task.getMaxOutputSizeMB().set(extension.getMaxOutputSizeMB());
task.getInputInstructions().set(
instructionsFilteredForArch(target, extension, arch)
);
task.onlyIf(runningOnSupportedArchitecture(extension));
task.getDockerEphemeralConfiguration().set(dockerEphemeralConfiguration);
task.getOSPackagesConfiguration().set(osPackageConfigurations.get(arch));
task.dependsOn(osPackageConfigurations.get(arch));
});
});
TaskProvider<DockerBaseImageBuildTask> dockerBaseImageBuild = target.getTasks()
.withType(DockerBaseImageBuildTask.class)
.named(BUILD_TASK_NAME);
MultiArchLifecyclePlugin.assembleForPlatform(target, dockerBaseImageBuild);
Arrays.stream(Architecture.values()).forEach( arch -> {
registerLocalImportTask(
target, arch,
extension,
target.getTasks()
.withType(DockerBaseImageBuildTask.class)
.named(BUILD_TASK_NAME + dockerNameIfNotCurrent(arch))
);
});
registerCleanTask(target, extension);
registerPushTask(target, extension, dockerBaseImageBuild);
Arrays.stream(Architecture.values()).forEach( arch -> {
target.getTasks().register(
LOCKFILE_TASK_NAME + dockerNameIfNotCurrent(arch),
DockerLockfileTask.class,
task -> {
task.getArchitecture().set(arch);
task.getInputInstructions().set(instructionsFilteredForArch(target, extension, arch));
}
);
}
);
target.getTasks().register(LOCKFILE_TASK_NAME + "AllWithEmulation", task -> {
task.dependsOn(target.getTasks().withType(DockerLockfileTask.class));
});
target.getTasks().withType(DockerLockfileTask.class).configureEach(task -> {
task.setGroup("containers");
task.setDescription("Generates a new lockfile with the latest version of all packages");
task.getOSDistribution().set(extension.getOSDistribution());
task.getLockFileLocation().set(extension.getLockFileLocation());
task.getDockerEphemeralMount().set(extension.getDockerEphemeralMount());
task.getOsPackageRepository().set(extension.getOsPackageRepository());
task.getMirrorRepositories().set(extension.getMirrorRepositories());
task.getDockerEphemeralConfiguration().set(dockerEphemeralConfiguration);
// Map the configuration to the architecture of the task
task.getOSPackagesConfiguration().set(task.getArchitecture().map(osPackageConfigurations::get));
// hard code Linux here, because we are using it inside a docker container
task.getJFrogCli().set(JFrogPlugin.getExecutable(target, OS.LINUX));
task.onlyIf(runningOnSupportedArchitecture(extension));
}
);
GradleUtils.registerOrGet(target, "dockerBuild").configure(task -> {
task.dependsOn(dockerBaseImageBuild);
task.setGroup("containers");
});
GradleUtils.registerOrGet(target, "dockerLocalImport").configure(task -> {
task.dependsOn(target.getTasks().named("dockerBaseImageLocalImport"));
task.setGroup("containers");
});
target.getGradle().getTaskGraph().whenReady(graph -> {
final String separator = target.getPath().endsWith(":") ? "" : ":";
final String lockfileTaskPath = target.getPath() + separator + LOCKFILE_TASK_NAME;
final String buildTaskPath = target.getPath() + separator + BUILD_TASK_NAME;
if (graph.hasTask(lockfileTaskPath) && graph.hasTask(buildTaskPath)
) {
throw new GradleException("Generating the lockfile and building an image using it in the same invocation" +
" is not supported. The lockfile should be generated and checked in. It can be " +
"re-generated periodically to update dependencies, but doing at the same time" +
"defeats the purpose of having a lockfile.");
}
});
target.afterEvaluate(p -> {
// Assign dependencies to local image builds in other projects
extension.getInstructions().stream()
.filter(each -> each instanceof FromLocalImageBuild)
.map(each -> (FromLocalImageBuild) each)
.map(FromLocalImageBuild::otherProjectPath)
.forEach(otherProjectPath -> {
dockerBaseImageBuild.configure(task ->
task.dependsOn(otherProjectPath + ":" + LOCAL_IMPORT_TASK_NAME)
);
Arrays.stream(Architecture.values()).forEach( arch -> {
target.getTasks().withType(DockerLockfileTask.class)
.named(LOCKFILE_TASK_NAME + dockerNameIfNotCurrent(arch)).configure(task -> {
task.dependsOn(otherProjectPath + ":" + LOCAL_IMPORT_TASK_NAME + dockerNameIfNotCurrent(arch));
// We don't force lock-files to be updated at the same time, but if they are, we need to order them for correct results
task.mustRunAfter(otherProjectPath + ":" + LOCKFILE_TASK_NAME + dockerNameIfNotCurrent(arch));
});
});
});
// assign copy specs to the build tasks to correctly evaluate build avoidance
dockerBaseImageBuild.configure(task ->
InstructionCopySpecMapper.assignCopySpecs(
extension.getInstructions(), ((ImageBuildable) task).getRootCopySpec()
)
);
target.getTasks().withType(DockerLockfileTask.class).configureEach(task ->
InstructionCopySpecMapper.assignCopySpecs(
extension.getInstructions(),
((ImageBuildable) task).getRootCopySpec())
);
if (extension.getOsPackageRepository().isPresent()) {
final URL repoUrl = extension.getOsPackageRepository().get();
Action<? super PasswordCredentials> credentialsAction =
(repoUrl.getUserInfo() != null) ?
config -> {
final String[] userinfo = repoUrl.getUserInfo().split(":");
config.setUsername(userinfo[0]);
config.setPassword(userinfo[1]);
} : null;
target.getRepositories().ivy(repo -> {
osPackageConfigurations.values().stream()
.map(Configuration::getName)
.forEach(configurationName -> configureRepoForConfiguration(
repoUrl, credentialsAction, repo, configurationName
));
});
}
final Path lockfilePath = RegularFileUtils.toPath(extension.getLockFileLocation());
if (Files.exists(lockfilePath)) {
try {
final BaseLockfile lockfile = BaseLockfile.parse(
Files.newBufferedReader(lockfilePath)
);
// Add all packages to a configuration to make verification data easier
final Map<Architecture, Packages> lockfilePackages = lockfile.getPackages();
for (Map.Entry<Architecture, Configuration> configuration : osPackageConfigurations.entrySet()) {
if (lockfilePackages.containsKey(configuration.getKey())) {
lockfilePackages.get(configuration.getKey()).getPackages()
.stream()
.forEach(pkg -> addPackageAsDependency(target, extension, configuration, pkg));
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
});
}