2019-03-12 14:18:22 +00:00
|
|
|
evaluationDependsOn(":node:capsule")
|
2018-11-20 13:38:44 +00:00
|
|
|
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
import com.github.dockerjava.api.model.Identifier
|
|
|
|
import net.corda.build.docker.DockerImage
|
|
|
|
import net.corda.build.docker.DockerUtils
|
|
|
|
import net.corda.build.docker.ObjectInputStreamWithCustomClassLoader
|
|
|
|
|
|
|
|
import java.nio.file.Files
|
|
|
|
import java.nio.file.StandardCopyOption
|
2018-11-20 13:38:44 +00:00
|
|
|
import java.time.LocalDateTime
|
|
|
|
import java.time.format.DateTimeFormatter
|
2020-11-20 10:21:53 +00:00
|
|
|
import java.util.stream.Collectors
|
|
|
|
import java.util.stream.Stream
|
2018-11-20 13:38:44 +00:00
|
|
|
|
|
|
|
apply plugin: 'kotlin'
|
|
|
|
apply plugin: 'application'
|
2019-09-05 12:02:51 +00:00
|
|
|
|
2018-11-20 13:38:44 +00:00
|
|
|
// We need to set mainClassName before applying the shadow plugin.
|
|
|
|
mainClassName = 'net.corda.core.ConfigExporterMain'
|
|
|
|
apply plugin: 'com.github.johnrengelman.shadow'
|
|
|
|
|
|
|
|
dependencies{
|
|
|
|
compile project(':node')
|
|
|
|
}
|
|
|
|
|
|
|
|
shadowJar {
|
|
|
|
baseName = 'config-exporter'
|
|
|
|
classifier = null
|
|
|
|
version = null
|
|
|
|
zip64 true
|
2019-10-21 12:31:09 +00:00
|
|
|
exclude '**/Log4j2Plugins.dat'
|
2018-11-20 13:38:44 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
enum ImageVariant {
|
|
|
|
UBUNTU_ZULU("zulu", "Dockerfile", "1.8"),
|
|
|
|
UBUNTU_ZULU_11("zulu", "Dockerfile11", "11"),
|
|
|
|
AL_CORRETTO("corretto", "DockerfileAL", "1.8"),
|
|
|
|
OFFICIAL(UBUNTU_ZULU)
|
|
|
|
|
|
|
|
String knownAs
|
|
|
|
String dockerFile
|
|
|
|
String javaVersion
|
|
|
|
|
|
|
|
String versionString(String baseTag, String version) {
|
|
|
|
return "${baseTag}-${knownAs}" +
|
|
|
|
(knownAs.isEmpty() ? "" : "-") +
|
|
|
|
"java${javaVersion}-" + version
|
2018-12-03 16:25:34 +00:00
|
|
|
}
|
2018-11-20 13:38:44 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
ImageVariant(ImageVariant other) {
|
|
|
|
this.knownAs = other.knownAs
|
|
|
|
this.dockerFile = other.dockerFile
|
|
|
|
this.javaVersion = other.javaVersion
|
|
|
|
}
|
2019-12-16 14:34:51 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
ImageVariant(String knownAs, String dockerFile, String javaVersion) {
|
|
|
|
this.knownAs = knownAs
|
|
|
|
this.dockerFile = dockerFile
|
|
|
|
this.javaVersion = javaVersion
|
2019-12-16 14:34:51 +00:00
|
|
|
}
|
2020-11-20 10:21:53 +00:00
|
|
|
|
|
|
|
static final String getRepository(Project project) {
|
|
|
|
return project.properties.getOrDefault("docker.image.repository", "corda/corda")
|
2018-11-20 13:38:44 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
static private final String runTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
|
2018-12-03 16:25:34 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
def getName(Project project) {
|
|
|
|
return versionString(getRepository(project), project.version.toString().toLowerCase())
|
|
|
|
}
|
2018-12-03 16:25:34 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
Set<Identifier> buildTags(Project project) {
|
|
|
|
final String suffix = project.version.toString().toLowerCase().contains("snapshot") ? runTime : "RELEASE"
|
|
|
|
return [suffix, "latest"].stream().map {
|
|
|
|
toAppend -> "${getName(project)}:${toAppend}".toString()
|
|
|
|
}.map(Identifier.&fromCompoundString).collect(Collectors.toSet())
|
|
|
|
}
|
2019-09-18 09:26:26 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
static Set<ImageVariant> toBeBuilt = Arrays.stream(values()).collect(Collectors.toSet())
|
2018-12-06 11:42:07 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
class BuildDockerFolderTask extends DefaultTask {
|
2018-12-06 11:42:07 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
@Option(option = "image", description = "Docker image variants that will be built")
|
|
|
|
void setVariants(List<ImageVariant> variants) {
|
|
|
|
ImageVariant.toBeBuilt = new HashSet<>(variants)
|
|
|
|
}
|
|
|
|
|
|
|
|
@OptionValues("image")
|
|
|
|
Collection<ImageVariant> allVariants() {
|
|
|
|
return EnumSet.allOf(ImageVariant.class)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Input
|
|
|
|
Iterable<ImageVariant> variantsToBuild() {
|
|
|
|
return ImageVariant.toBeBuilt
|
|
|
|
}
|
|
|
|
|
|
|
|
@InputFiles
|
|
|
|
FileCollection getDockerBuildFiles() {
|
|
|
|
return project.fileTree("${project.projectDir}/src/docker/build")
|
|
|
|
}
|
|
|
|
|
|
|
|
@InputFiles
|
|
|
|
FileCollection getShellScripts() {
|
|
|
|
return project.fileTree("${project.projectDir}/src/bash")
|
|
|
|
}
|
|
|
|
|
|
|
|
@Lazy
|
|
|
|
private File cordaJar = project.findProject(":node:capsule").tasks.buildCordaJAR.outputs.files.singleFile
|
|
|
|
|
|
|
|
@Lazy
|
|
|
|
private File configExporter = project.tasks.shadowJar.outputs.files.singleFile
|
|
|
|
|
|
|
|
@Lazy
|
|
|
|
private File dbMigrator = project.findProject(":tools:dbmigration").tasks.shadowJar.outputs.files.singleFile
|
|
|
|
|
|
|
|
@InputFiles
|
|
|
|
private FileCollection getRequiredArtifacts() {
|
|
|
|
FileCollection res = project.tasks.shadowJar.outputs.files
|
|
|
|
def capsuleProject = project.findProject(":node:capsule")
|
|
|
|
def capsuleTaksOutput = capsuleProject.tasks.buildCordaJAR.outputs.files
|
|
|
|
res += capsuleTaksOutput
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
@OutputFiles
|
|
|
|
FileCollection getDockerFiles() {
|
|
|
|
return project.objects.fileCollection().from(ImageVariant.toBeBuilt.stream().map {
|
|
|
|
new File(dockerBuildDir, it.dockerFile)
|
|
|
|
}.collect(Collectors.toList()))
|
|
|
|
}
|
|
|
|
|
|
|
|
@OutputDirectory
|
|
|
|
final File dockerBuildDir = project.file("${project.buildDir}/docker/build")
|
|
|
|
|
|
|
|
@TaskAction
|
|
|
|
def run() {
|
|
|
|
for(ImageVariant imageVariant : ImageVariant.toBeBuilt) {
|
|
|
|
def sourceFile = project.projectDir.toPath().resolve("src/docker/${imageVariant.dockerFile}")
|
|
|
|
def destinationFile = dockerBuildDir.toPath().resolve(imageVariant.dockerFile)
|
|
|
|
Files.copy(sourceFile, destinationFile, StandardCopyOption.REPLACE_EXISTING)
|
|
|
|
}
|
|
|
|
Files.copy(cordaJar.toPath(), dockerBuildDir.toPath().resolve("corda.jar"), StandardCopyOption.REPLACE_EXISTING)
|
|
|
|
Files.copy(configExporter.toPath(), dockerBuildDir.toPath().resolve("config-exporter.jar"), StandardCopyOption.REPLACE_EXISTING)
|
2018-12-06 11:42:07 +00:00
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
["src/bash/run-corda.sh",
|
|
|
|
"src/config/starting-node.conf",
|
|
|
|
"src/bash/generate-config.sh"].forEach {
|
|
|
|
def source = project.file(it).toPath()
|
|
|
|
Files.copy(source, dockerBuildDir.toPath().resolve(source.fileName), StandardCopyOption.REPLACE_EXISTING)
|
|
|
|
}
|
|
|
|
}
|
2019-09-18 09:26:26 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
|
|
|
|
class BuildDockerImageTask extends DefaultTask {
|
|
|
|
|
|
|
|
@Option(option = "image", description = "Docker image variants that will be built")
|
|
|
|
void setVariants(List<ImageVariant> variants) {
|
|
|
|
ImageVariant.toBeBuilt = new HashSet<>(variants)
|
|
|
|
}
|
|
|
|
|
|
|
|
@OptionValues("image")
|
|
|
|
Collection<ImageVariant> allVariants() {
|
|
|
|
return EnumSet.allOf(ImageVariant.class)
|
|
|
|
}
|
|
|
|
|
|
|
|
final File dockerBuildDir = project.file("${project.buildDir}/docker/build")
|
|
|
|
|
|
|
|
@OutputDirectory
|
|
|
|
final File dockerBuiltImageDir = project.file("${project.buildDir}/docker/images")
|
|
|
|
|
|
|
|
@Input
|
|
|
|
String getRepository() {
|
|
|
|
return ImageVariant.getRepository(project)
|
|
|
|
}
|
|
|
|
|
|
|
|
@InputFiles
|
|
|
|
FileCollection dockerFiles
|
|
|
|
|
|
|
|
private Map<ImageVariant, DockerImage> images
|
|
|
|
|
|
|
|
@OutputFiles
|
|
|
|
FileCollection getImageFiles() {
|
|
|
|
return project.objects.fileCollection().from(ImageVariant.toBeBuilt.stream().map { imageVariant ->
|
|
|
|
dockerBuiltImageDir.toPath().resolve(imageVariant.toString()).toFile()
|
|
|
|
}.collect(Collectors.toList()))
|
|
|
|
}
|
|
|
|
|
|
|
|
void from(BuildDockerFolderTask buildDockerFolderTask) {
|
|
|
|
dockerFiles = buildDockerFolderTask.outputs.files
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
Task configure(Closure closure) {
|
|
|
|
return super.configure(closure)
|
|
|
|
}
|
|
|
|
|
|
|
|
@TaskAction
|
|
|
|
def run() {
|
|
|
|
this.@images = ImageVariant.toBeBuilt.stream().map { imageVariant ->
|
|
|
|
new Tuple2<>(imageVariant, new DockerImage(
|
|
|
|
baseDir: dockerBuildDir,
|
|
|
|
dockerFile: imageVariant.dockerFile,
|
|
|
|
tags: imageVariant.buildTags(project)))
|
|
|
|
}.collect(Collectors.toMap({it.first}, {it.second}))
|
|
|
|
DockerUtils.buildImages(project, this.@images.values())
|
|
|
|
images.entrySet().forEach { entry ->
|
|
|
|
ImageVariant imageVariant = entry.key
|
|
|
|
def destinationFile = dockerBuiltImageDir.toPath().resolve(imageVariant.toString())
|
|
|
|
new ObjectOutputStream(Files.newOutputStream(destinationFile)).withStream {
|
|
|
|
it.writeObject(entry.value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-18 09:26:26 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
class PushDockerImage extends DefaultTask {
|
|
|
|
@Option(option = "image", description = "Docker image variants that will be built")
|
|
|
|
void setVariants(List<ImageVariant> variants) {
|
|
|
|
ImageVariant.toBeBuilt = new HashSet<>(variants)
|
|
|
|
}
|
|
|
|
|
|
|
|
@OptionValues("image")
|
|
|
|
Collection<ImageVariant> allVariants() {
|
|
|
|
return EnumSet.allOf(ImageVariant.class)
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String registryURL
|
|
|
|
|
|
|
|
@Option(option = "registry-url", description = "Docker image registry where images will be pushed, defaults to DockerHub")
|
|
|
|
void setRegistryURL(String registryURL) {
|
|
|
|
PushDockerImage.registryURL = registryURL
|
|
|
|
}
|
|
|
|
|
|
|
|
@InputFiles
|
|
|
|
FileCollection imageFiles
|
|
|
|
|
|
|
|
def from(BuildDockerImageTask buildDockerImageTask) {
|
|
|
|
imageFiles = buildDockerImageTask.outputs.files
|
|
|
|
}
|
|
|
|
|
|
|
|
@TaskAction
|
|
|
|
def run() {
|
|
|
|
def classLoader = DockerImage.class.classLoader
|
|
|
|
Stream<DockerImage> imageStream = imageFiles.files.stream().filter{
|
|
|
|
it.isFile()
|
|
|
|
}.map {
|
|
|
|
new ObjectInputStreamWithCustomClassLoader(Files.newInputStream(it.toPath()), classLoader).withStream {
|
|
|
|
DockerImage image = it.readObject()
|
|
|
|
if(PushDockerImage.registryURL) {
|
|
|
|
image.destination = PushDockerImage.registryURL
|
|
|
|
}
|
|
|
|
image
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DockerUtils.pushImages(project, imageStream)
|
|
|
|
}
|
2018-12-03 16:25:34 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
def buildDockerFolderTask = tasks.register("buildDockerFolder", BuildDockerFolderTask)
|
|
|
|
def buildDockerImageTask = tasks.register("buildDockerImage", BuildDockerImageTask) {
|
|
|
|
from(buildDockerFolderTask.get())
|
2018-12-03 16:25:34 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:21:53 +00:00
|
|
|
tasks.register("pushDockerImage", PushDockerImage) {
|
|
|
|
from(buildDockerImageTask.get())
|
|
|
|
}
|