Gradle task to create a build/standalone folder suitable to demonstrate the capsule.io all in one jar

This commit is contained in:
Matthew Nesbit 2016-08-04 11:03:04 +01:00
parent 9deab37bed
commit 6b844c0e41
6 changed files with 120 additions and 87 deletions

View File

@ -200,4 +200,45 @@ task createCapsule(type:FatCapsule, dependsOn: 'quasarScan') {
javaAgents = ["quasar-core-${quasar_version}-jdk8.jar"]
minJavaVersion = '1.8.0'
}
}
task createStandalone(dependsOn: 'createCapsule') << {
copy {
from createCapsule.outputs.getFiles()
from 'config/dev/nameservernode.conf'
into "${buildDir}/standalone/nameserver"
rename 'nameservernode.conf', 'node.conf'
}
copy {
from createCapsule.outputs.getFiles()
from 'config/dev/generalnodea.conf'
into "${buildDir}/standalone/nodea"
rename 'generalnodea.conf', 'node.conf'
}
copy {
from createCapsule.outputs.getFiles()
from 'config/dev/generalnodeb.conf'
into "${buildDir}/standalone/nodeb"
rename 'generalnodeb.conf', 'node.conf'
}
delete("${buildDir}/standalone/runstandalone")
def myFile = file("${buildDir}/standalone/runstandalone")
def jarName = createCapsule.outputs.getFiles().getSingleFile().getName()
myFile << "#!/usr/bin/env bash\n"
myFile << "set -euo pipefail\n"
myFile << "trap 'kill \$(jobs -p)' SIGINT SIGTERM EXIT\n"
myFile << "export CAPSULE_CACHE_DIR=cache\n"
myFile << "pushd nameserver\n"
myFile << "( java -jar "+ jarName+" )& \n"
myFile << "popd\n"
myFile << "pushd nodea\n"
myFile << "( java -jar "+ jarName+" )& \n"
myFile << "popd\n"
myFile << "pushd nodeb\n"
myFile << "( java -jar "+ jarName+" )& \n"
myFile << "popd\n"
myFile << "read -p 'Any key to exit'\n"
myFile << "kill \$(jobs -p)\n"
}

View File

@ -1,4 +1,4 @@
basedir : "./standalone/nodea",
basedir : "./nodea",
myLegalName : "Bank A",
nearestCity : "London",
keyStorePassword : "cordacadevpass",

View File

@ -1,4 +1,4 @@
basedir : "./standalone/nodeb",
basedir : "./nodeb",
myLegalName : "Bank B",
nearestCity : "London",
keyStorePassword : "cordacadevpass",

View File

@ -1,4 +1,4 @@
basedir : "./standalone/nameserver",
basedir : "./nameserver",
myLegalName : "Notary Service",
nearestCity : "London",
keyStorePassword : "cordacadevpass",

View File

@ -1,8 +1,24 @@
package com.r3corda.node.services.config
import com.google.common.net.HostAndPort
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType
import com.r3corda.node.internal.Node
import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.messaging.ArtemisMessagingService
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Clock
import java.time.Instant
import java.time.LocalDate
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.javaType
interface NodeConfiguration {
val myLegalName: String
@ -12,8 +28,21 @@ interface NodeConfiguration {
val trustStorePassword: String
}
// Allow the use of "String by config" syntax. TODO: Make it more flexible.
operator fun Config.getValue(receiver: NodeConfigurationFromConfig, metadata: KProperty<*>) = getString(metadata.name)
@Suppress("UNCHECKED_CAST")
operator fun <T> Config.getValue(receiver: Any, metadata: KProperty<*>): T {
return when (metadata.returnType.javaType) {
String::class.java -> getString(metadata.name) as T
Int::class.java -> getInt(metadata.name) as T
Long::class.java -> getLong(metadata.name) as T
Double::class.java -> getDouble(metadata.name) as T
Boolean::class.java -> getBoolean(metadata.name) as T
LocalDate::class.java -> LocalDate.parse(getString(metadata.name)) as T
Instant::class.java -> Instant.parse(getString(metadata.name)) as T
HostAndPort::class.java -> HostAndPort.fromString(getString(metadata.name)) as T
Path::class.java -> Paths.get(getString(metadata.name)) as T
else -> throw IllegalArgumentException("Unsupported type ${metadata.returnType}")
}
}
class NodeConfigurationFromConfig(val config: Config = ConfigFactory.load()) : NodeConfiguration {
override val myLegalName: String by config
@ -21,4 +50,48 @@ class NodeConfigurationFromConfig(val config: Config = ConfigFactory.load()) : N
override val nearestCity: String by config
override val keyStorePassword: String by config
override val trustStorePassword: String by config
}
class NameServiceConfig(conf: Config) {
val hostServiceLocally: Boolean by conf
val address: HostAndPort by conf
val identity: String by conf
}
class FullNodeConfiguration(conf: Config) : NodeConfiguration {
val basedir: Path by conf
override val myLegalName: String by conf
override val nearestCity: String by conf
override val exportJMXto: String = "http"
override val keyStorePassword: String by conf
override val trustStorePassword: String by conf
val artemisAddress: HostAndPort by conf
val webAddress: HostAndPort by conf
val hostNotaryServiceLocally: Boolean by conf
val extraAdvertisedServiceIds: String by conf
val mapService: NameServiceConfig = NameServiceConfig(conf.getConfig("mapService"))
val clock: Clock = NodeClock()
fun createNode(): Node {
val networkMapTarget = ArtemisMessagingService.makeRecipient(mapService.address)
val advertisedServices = mutableSetOf<ServiceType>()
if (mapService.hostServiceLocally) advertisedServices.add(NetworkMapService.Type)
if (hostNotaryServiceLocally) advertisedServices.add(SimpleNotaryService.Type)
if (!extraAdvertisedServiceIds.isNullOrEmpty()) {
for (serviceId in extraAdvertisedServiceIds.split(",")) {
advertisedServices.add(object : ServiceType(serviceId) {})
}
}
// TODO Node startup should not need a full NodeInfo for the remote NetworkMapService provider as bootstrap
val networkMapBootstrapIdentity = Party(mapService.identity, generateKeyPair().public)
val networkMapAddress: NodeInfo? = if (mapService.hostServiceLocally) null else NodeInfo(networkMapTarget, networkMapBootstrapIdentity, setOf(NetworkMapService.Type))
return Node(basedir.toAbsolutePath().normalize(),
artemisAddress,
webAddress,
this,
networkMapAddress,
advertisedServices,
clock
)
}
}

View File

@ -1,17 +1,6 @@
package com.r3corda.standalone
import com.google.common.net.HostAndPort
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType
import com.r3corda.node.internal.Node
import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.messaging.ArtemisMessagingService
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService
import com.typesafe.config.Config
import com.r3corda.node.services.config.FullNodeConfiguration
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions
import joptsimple.OptionParser
@ -21,80 +10,10 @@ import java.lang.management.ManagementFactory
import java.net.InetAddress
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Clock
import java.time.Instant
import java.time.LocalDate
import java.util.*
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.javaType
val log = LoggerFactory.getLogger("Main")
@Suppress("UNCHECKED_CAST")
operator fun <T> Config.getValue(receiver: Any, metadata: KProperty<*>): T {
return when (metadata.returnType.javaType) {
String::class.java -> getString(metadata.name) as T
Int::class.java -> getInt(metadata.name) as T
Long::class.java -> getLong(metadata.name) as T
Double::class.java -> getDouble(metadata.name) as T
Boolean::class.java -> getBoolean(metadata.name) as T
LocalDate::class.java -> LocalDate.parse(getString(metadata.name)) as T
Instant::class.java -> Instant.parse(getString(metadata.name)) as T
HostAndPort::class.java -> HostAndPort.fromString(getString(metadata.name)) as T
Path::class.java -> Paths.get(getString(metadata.name)) as T
else -> throw IllegalArgumentException("Unsupported type ${metadata.returnType}")
}
}
interface AdvertisedServiceConfig {
val hostServiceLocally: Boolean
val address: HostAndPort
val identity: String
}
class AdvertisedServiceConfigImpl(conf: Config) : AdvertisedServiceConfig {
override val hostServiceLocally: Boolean by conf
override val address: HostAndPort by conf
override val identity: String by conf
}
class FullNodeConfiguration(conf: Config) : NodeConfiguration {
val basedir: Path by conf
override val myLegalName: String by conf
override val nearestCity: String by conf
override val exportJMXto: String = "http"
override val keyStorePassword: String by conf
override val trustStorePassword: String by conf
val artemisAddress: HostAndPort by conf
val webAddress: HostAndPort by conf
val hostNotaryServiceLocally: Boolean by conf
val extraAdvertisedServiceIds: String by conf
val mapService: AdvertisedServiceConfigImpl = AdvertisedServiceConfigImpl(conf.getConfig("mapService"))
val clock: Clock = NodeClock()
fun createNode(): Node {
val networkMapTarget = ArtemisMessagingService.makeRecipient(mapService.address)
val advertisedServices = mutableSetOf<ServiceType>()
if (mapService.hostServiceLocally) advertisedServices.add(NetworkMapService.Type)
if (hostNotaryServiceLocally) advertisedServices.add(SimpleNotaryService.Type)
if (!extraAdvertisedServiceIds.isNullOrEmpty()) {
for (serviceId in extraAdvertisedServiceIds.split(",")) {
advertisedServices.add(object : ServiceType(serviceId) {})
}
}
val networkMapBootstrapIdentity = Party(mapService.identity, generateKeyPair().public)
val networkMapAddress: NodeInfo? = if (mapService.hostServiceLocally) null else NodeInfo(networkMapTarget, networkMapBootstrapIdentity, setOf(NetworkMapService.Type))
return Node(basedir.toAbsolutePath().normalize(),
artemisAddress,
webAddress,
this,
networkMapAddress,
advertisedServices,
clock
)
}
}
object ParamsSpec {
val parser = OptionParser()