CORDA-892: Make cordform test use new network bootstrapper logic (#2307)

* Make cordform test use new network bootstrapper logic

* Fixing review comments

* Fix issue with backwards compatibility

* Fix issue with setup not being called from CordformDefinitions

* Make sure node dir is created (as CordformDefinition uses it directly if setup is overridden
Make sure tmp dir is created

* Don't crash if node dir is already created

* Stop overwriting errors
This commit is contained in:
Anthony Keenan 2018-01-05 09:21:59 +00:00 committed by GitHub
parent 00a02b30fe
commit 1661cea816
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 72 deletions

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=3.0.2
gradlePluginsVersion=3.0.3
kotlinVersion=1.1.60
platformVersion=2
guavaVersion=21.0

View File

@ -22,6 +22,7 @@ import java.util.jar.JarInputStream
@Suppress("unused")
open class Cordform : DefaultTask() {
private companion object {
val nodeJarName = "corda.jar"
private val defaultDirectory: Path = Paths.get("build", "nodes")
}
@ -132,9 +133,26 @@ open class Cordform : DefaultTask() {
fun build() {
project.logger.info("Running Cordform task")
initializeConfiguration()
nodes.forEach(Node::installConfig)
installCordaJar()
installRunScript()
nodes.forEach(Node::build)
bootstrapNetwork()
nodes.forEach(Node::build)
}
/**
* Installs the corda fat JAR to the root directory, for the network bootstrapper to use.
*/
private fun installCordaJar() {
val cordaJar = Cordformation.verifyAndGetRuntimeJar(project, "corda")
project.copy {
it.apply {
from(cordaJar)
into(directory)
rename(cordaJar.name, nodeJarName)
fileMode = Cordformation.executableFileMode
}
}
}
private fun initializeConfiguration() {
@ -150,8 +168,8 @@ open class Cordform : DefaultTask() {
cd.nodeConfigurers.forEach {
val node = node { }
it.accept(node)
node.additionalCordapps.addAll(cordapps)
node.rootDir(directory)
node.installCordapps(cordapps)
}
cd.setup { nodeName -> project.projectDir.toPath().resolve(getNodeByName(nodeName)!!.nodeDir.toPath()) }
} else {

View File

@ -20,14 +20,35 @@ class Cordformation : Plugin<Project> {
* @return A file handle to the file in the JAR.
*/
fun getPluginFile(project: Project, filePathInJar: String): File {
val archive: File? = project.rootProject.buildscript.configurations
val archive = project.rootProject.buildscript.configurations
.single { it.name == "classpath" }
.find { it.name.contains("cordformation") }
.first { it.name.contains("cordformation") }
return project.rootProject.resources.text
.fromArchiveEntry(archive, filePathInJar)
.asFile()
}
/**
* Gets a current built corda jar file
*
* @param project The project environment this plugin executes in.
* @param jarName The name of the JAR you wish to access.
* @return A file handle to the file in the JAR.
*/
fun verifyAndGetRuntimeJar(project: Project, jarName: String): File {
val releaseVersion = project.rootProject.ext<String>("corda_release_version")
val maybeJar = project.configuration("runtime").filter {
"$jarName-$releaseVersion.jar" in it.toString() || "$jarName-enterprise-$releaseVersion.jar" in it.toString()
}
if (maybeJar.isEmpty) {
throw IllegalStateException("No $jarName JAR found. Have you deployed the Corda project to Maven? Looked for \"$jarName-$releaseVersion.jar\"")
} else {
val jar = maybeJar.singleFile
require(jar.isFile)
return jar
}
}
val executableFileMode = "0755".toInt(8)
}

View File

@ -15,8 +15,6 @@ import java.nio.file.Path
*/
class Node(private val project: Project) : CordformNode() {
companion object {
@JvmStatic
val nodeJarName = "corda.jar"
@JvmStatic
val webJarName = "corda-webserver.jar"
private val configFileProperty = "configFile"
@ -30,10 +28,11 @@ class Node(private val project: Project) : CordformNode() {
* @note Type is any due to gradle's use of "GStrings" - each value will have "toString" called on it
*/
var cordapps = mutableListOf<Any>()
private val releaseVersion = project.rootProject.ext<String>("corda_release_version")
var additionalCordapps = mutableListOf<File>()
internal lateinit var nodeDir: File
private set
internal lateinit var rootDir: File
private set
/**
* Sets whether this node will use HTTPS communication.
@ -65,16 +64,12 @@ class Node(private val project: Project) : CordformNode() {
}
internal fun build() {
configureProperties()
installCordaJar()
if (config.hasPath("webAddress")) {
installWebserverJar()
}
installAgentJar()
installBuiltCordapp()
installCordapps()
installConfig()
appendOptionalConfig()
}
internal fun rootDir(rootDir: Path) {
@ -86,7 +81,9 @@ class Node(private val project: Project) : CordformNode() {
// with loading our custom X509EdDSAEngine.
val organizationName = name.trim().split(",").firstOrNull { it.startsWith("O=") }?.substringAfter("=")
val dirName = organizationName ?: name
nodeDir = File(rootDir.toFile(), dirName)
this.rootDir = rootDir.toFile()
nodeDir = File(this.rootDir, dirName)
Files.createDirectories(nodeDir.toPath())
}
private fun configureProperties() {
@ -99,26 +96,11 @@ class Node(private val project: Project) : CordformNode() {
}
}
/**
* Installs the corda fat JAR to the node directory.
*/
private fun installCordaJar() {
val cordaJar = verifyAndGetRuntimeJar("corda")
project.copy {
it.apply {
from(cordaJar)
into(nodeDir)
rename(cordaJar.name, nodeJarName)
fileMode = Cordformation.executableFileMode
}
}
}
/**
* Installs the corda webserver JAR to the node directory
*/
private fun installWebserverJar() {
val webJar = verifyAndGetRuntimeJar("corda-webserver")
val webJar = Cordformation.verifyAndGetRuntimeJar(project, "corda-webserver")
project.copy {
it.apply {
from(webJar)
@ -141,19 +123,6 @@ class Node(private val project: Project) : CordformNode() {
}
}
/**
* Installs other cordapps to this node's cordapps directory.
*/
internal fun installCordapps(cordapps: Collection<File> = getCordappList()) {
val cordappsDir = File(nodeDir, "cordapps")
project.copy {
it.apply {
from(cordapps)
into(cordappsDir)
}
}
}
/**
* Installs the jolokia monitoring agent JAR to the node/drivers directory
*/
@ -177,10 +146,7 @@ class Node(private val project: Project) : CordformNode() {
}
}
/**
* Installs the configuration file to this node's directory and detokenises it.
*/
private fun installConfig() {
private fun createTempConfigFile(): File {
val options = ConfigRenderOptions
.defaults()
.setOriginComments(false)
@ -188,16 +154,26 @@ class Node(private val project: Project) : CordformNode() {
.setFormatted(true)
.setJson(false)
val configFileText = config.root().render(options).split("\n").toList()
// Need to write a temporary file first to use the project.copy, which resolves directories correctly.
val tmpDir = File(project.buildDir, "tmp")
val tmpConfFile = File(tmpDir, "node.conf")
Files.createDirectories(tmpDir.toPath())
var fileName = "${nodeDir.getName()}.conf"
val tmpConfFile = File(tmpDir, fileName)
Files.write(tmpConfFile.toPath(), configFileText, StandardCharsets.UTF_8)
return tmpConfFile
}
/**
* Installs the configuration file to the root directory and detokenises it.
*/
internal fun installConfig() {
configureProperties()
val tmpConfFile = createTempConfigFile()
appendOptionalConfig(tmpConfFile)
project.copy {
it.apply {
from(tmpConfFile)
into(nodeDir)
into(rootDir)
}
}
}
@ -205,7 +181,7 @@ class Node(private val project: Project) : CordformNode() {
/**
* Appends installed config file with properties from an optional file.
*/
private fun appendOptionalConfig() {
private fun appendOptionalConfig(confFile: File) {
val optionalConfig: File? = when {
project.findProperty(configFileProperty) != null -> //provided by -PconfigFile command line property when running Gradle task
File(project.findProperty(configFileProperty) as String)
@ -217,28 +193,22 @@ class Node(private val project: Project) : CordformNode() {
if (!optionalConfig.exists()) {
project.logger.error("$configFileProperty '$optionalConfig' not found")
} else {
val confFile = File(project.buildDir.path + "/../" + nodeDir, "node.conf")
confFile.appendBytes(optionalConfig.readBytes())
}
}
}
/**
* Find the given JAR amongst the dependencies
* @param jarName JAR name without the version part, for example for corda-2.0-SNAPSHOT.jar provide only "corda" as jarName
*
* @return A file representing found JAR
* Installs other cordapps to this node's cordapps directory.
*/
private fun verifyAndGetRuntimeJar(jarName: String): File {
val maybeJar = project.configuration("runtime").filter {
"$jarName-$releaseVersion.jar" in it.toString() || "$jarName-enterprise-$releaseVersion.jar" in it.toString()
internal fun installCordapps() {
additionalCordapps.addAll(getCordappList())
val cordappsDir = File(nodeDir, "cordapps")
project.copy {
it.apply {
from(additionalCordapps)
into(cordappsDir)
}
if (maybeJar.isEmpty) {
throw IllegalStateException("No $jarName JAR found. Have you deployed the Corda project to Maven? Looked for \"$jarName-$releaseVersion.jar\"")
} else {
val jar = maybeJar.singleFile
require(jar.isFile)
return jar
}
}

View File

@ -83,16 +83,20 @@ class NetworkBootstrapper {
for (confFile in confFiles) {
val nodeName = confFile.fileName.toString().removeSuffix(".conf")
println("Generating directory for $nodeName")
val nodeDir = (directory / nodeName).createDirectory()
confFile.moveTo(nodeDir / "node.conf")
Files.copy(cordaJar, (nodeDir / "corda.jar"))
val nodeDir = (directory / nodeName)
if (!nodeDir.exists()) { nodeDir.createDirectory() }
confFile.moveTo(nodeDir / "node.conf", StandardCopyOption.REPLACE_EXISTING)
Files.copy(cordaJar, (nodeDir / "corda.jar"), StandardCopyOption.REPLACE_EXISTING)
}
Files.delete(cordaJar)
}
private fun extractCordaJarTo(directory: Path): Path {
val cordaJarPath = (directory / "corda.jar")
if (!cordaJarPath.exists()) {
println("No corda jar found in root directory. Extracting from jar")
Thread.currentThread().contextClassLoader.getResourceAsStream("corda.jar").copyTo(cordaJarPath)
}
return cordaJarPath
}