mirror of
https://github.com/corda/corda.git
synced 2025-01-29 15:43:55 +00:00
CORDA-3307: Fix for underscore variables (#5682)
* Revert "Revert "CORDA-3307 - add support for environment variables in linux (#5523)" (#5643)" This reverts commit 03ab258fc2d0f40badd73f78c81e5ec6badf2940. * Env variables with underscore are now validated using schema validation and checking for unknown key errors. * Resolving comments from PR review. * Fix for deprecated import. * Reworked logic according to PR review. * Resolved bad string parsing problems where the json structure could be broken if some symbols were included in the key or value.
This commit is contained in:
parent
c349ff719d
commit
926429647d
@ -88,6 +88,9 @@ Unreleased
|
|||||||
Note that it's a responsibility of a client application to handle RPC reconnection in case this happens.
|
Note that it's a responsibility of a client application to handle RPC reconnection in case this happens.
|
||||||
See :ref:`setting_jvm_args` and :ref:`memory_usage_and_tuning` for further details.
|
See :ref:`setting_jvm_args` and :ref:`memory_usage_and_tuning` for further details.
|
||||||
|
|
||||||
|
* Environment variables and system properties can now be provided with underscore separators instead of dots. Neither are case sensitive.
|
||||||
|
See :ref:`overriding config values <corda_configuration_file_overriding_config>` for more information.
|
||||||
|
|
||||||
.. _changelog_v4.1:
|
.. _changelog_v4.1:
|
||||||
|
|
||||||
Version 4.1
|
Version 4.1
|
||||||
|
@ -39,6 +39,8 @@ To alter this behaviour, the ``on-unknown-config-keys`` command-line argument ca
|
|||||||
Overriding values from node.conf
|
Overriding values from node.conf
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
.. _corda_configuration_file_overriding_config:
|
||||||
|
|
||||||
Environment variables
|
Environment variables
|
||||||
For example: ``${NODE_TRUST_STORE_PASSWORD}`` would be replaced by the contents of environment variable ``NODE_TRUST_STORE_PASSWORD`` (see: :ref:`hiding-sensitive-data` section).
|
For example: ``${NODE_TRUST_STORE_PASSWORD}`` would be replaced by the contents of environment variable ``NODE_TRUST_STORE_PASSWORD`` (see: :ref:`hiding-sensitive-data` section).
|
||||||
|
|
||||||
@ -54,6 +56,11 @@ JVM options
|
|||||||
.. note:: If the same field is overriden by both an environment variable and system property, the system property
|
.. note:: If the same field is overriden by both an environment variable and system property, the system property
|
||||||
takes precedence.
|
takes precedence.
|
||||||
|
|
||||||
|
.. note:: Underscores can be used in instead of dots. For example overriding the ``p2pAddress`` with an environment variable can be done
|
||||||
|
by specifying ``CORDA_P2PADDRESS=host:port``. Variables and properties are not case sensitive. Corda will warn you if a variable
|
||||||
|
prefixed with ``CORDA`` cannot be mapped to a valid property. Shadowing occurs when two properties
|
||||||
|
of the same type with the same key are defined. For example having ``CORDA_P2PADDRESS=host:port`` and ``corda_p2paddress=host1:port1``
|
||||||
|
will raise an exception on startup. This is to prevent hard to spot mistakes.
|
||||||
Configuration file fields
|
Configuration file fields
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
package net.corda.node
|
||||||
|
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.node.logging.logFile
|
||||||
|
import net.corda.testing.driver.DriverParameters
|
||||||
|
import net.corda.testing.driver.NodeParameters
|
||||||
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.driver.internal.incrementalPortAllocation
|
||||||
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
|
||||||
|
|
||||||
|
class NodeConfigParsingTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config is overriden by underscore variable`() {
|
||||||
|
val portAllocator = incrementalPortAllocation()
|
||||||
|
val sshPort = portAllocator.nextPort()
|
||||||
|
|
||||||
|
driver(DriverParameters(
|
||||||
|
environmentVariables = mapOf("corda_sshd_port" to sshPort.toString()),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
portAllocation = portAllocator)) {
|
||||||
|
val hasSsh = startNode().get()
|
||||||
|
.logFile()
|
||||||
|
.readLines()
|
||||||
|
.filter { it.contains("SSH server listening on port") }
|
||||||
|
.any { it.contains(sshPort.toString()) }
|
||||||
|
assertTrue(hasSsh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config is overriden by case insensitive underscore variable`() {
|
||||||
|
val portAllocator = incrementalPortAllocation()
|
||||||
|
val sshPort = portAllocator.nextPort()
|
||||||
|
|
||||||
|
driver(DriverParameters(
|
||||||
|
environmentVariables = mapOf("CORDA_sshd_port" to sshPort.toString()),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
portAllocation = portAllocator)) {
|
||||||
|
val hasSsh = startNode().get()
|
||||||
|
.logFile()
|
||||||
|
.readLines()
|
||||||
|
.filter { it.contains("SSH server listening on port") }
|
||||||
|
.any { it.contains(sshPort.toString()) }
|
||||||
|
assertTrue(hasSsh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config is overriden by case insensitive dot variable`() {
|
||||||
|
val portAllocator = incrementalPortAllocation()
|
||||||
|
val sshPort = portAllocator.nextPort()
|
||||||
|
|
||||||
|
driver(DriverParameters(
|
||||||
|
environmentVariables = mapOf("CORDA.sshd.port" to sshPort.toString(),
|
||||||
|
"corda.devMode" to true.toString()),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
portAllocation = portAllocator)) {
|
||||||
|
val hasSsh = startNode(NodeParameters()).get()
|
||||||
|
.logFile()
|
||||||
|
.readLines()
|
||||||
|
.filter { it.contains("SSH server listening on port") }
|
||||||
|
.any { it.contains(sshPort.toString()) }
|
||||||
|
assertTrue(hasSsh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `shadowing is forbidden`() {
|
||||||
|
val portAllocator = incrementalPortAllocation()
|
||||||
|
val sshPort = portAllocator.nextPort()
|
||||||
|
|
||||||
|
driver(DriverParameters(
|
||||||
|
environmentVariables = mapOf(
|
||||||
|
"CORDA_sshd_port" to sshPort.toString(),
|
||||||
|
"corda.sshd.port" to sshPort.toString()),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
portAllocation = portAllocator,
|
||||||
|
notarySpecs = emptyList())) {
|
||||||
|
|
||||||
|
assertThatThrownBy {
|
||||||
|
startNode().getOrThrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bad keys are ignored and warned for`() {
|
||||||
|
val portAllocator = incrementalPortAllocation()
|
||||||
|
driver(DriverParameters(
|
||||||
|
environmentVariables = mapOf(
|
||||||
|
"corda_bad_key" to "2077"),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
portAllocation = portAllocator,
|
||||||
|
notarySpecs = emptyList())) {
|
||||||
|
|
||||||
|
val hasWarning = startNode()
|
||||||
|
.getOrThrow()
|
||||||
|
.logFile()
|
||||||
|
.readLines()
|
||||||
|
.any {
|
||||||
|
it.contains("(property or environment variable) cannot be mapped to an existing Corda")
|
||||||
|
}
|
||||||
|
assertTrue(hasWarning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,4 +24,4 @@ class NodeStartupPerformanceTests {
|
|||||||
println(times.map { it / 1_000_000.0 })
|
println(times.map { it / 1_000_000.0 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,10 +4,13 @@ import com.typesafe.config.Config
|
|||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.typesafe.config.ConfigParseOptions
|
import com.typesafe.config.ConfigParseOptions
|
||||||
import net.corda.cliutils.CordaSystemUtils
|
import net.corda.cliutils.CordaSystemUtils
|
||||||
|
import net.corda.common.configuration.parsing.internal.Configuration
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
|
import net.corda.node.internal.Node
|
||||||
|
import net.corda.node.services.config.schema.v1.V1NodeConfigurationSpec
|
||||||
import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS
|
import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS
|
||||||
import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier
|
import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier
|
||||||
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
||||||
@ -27,6 +30,7 @@ operator fun Config.plus(overrides: Map<String, Any?>): Config = ConfigFactory.p
|
|||||||
object ConfigHelper {
|
object ConfigHelper {
|
||||||
|
|
||||||
private const val CORDA_PROPERTY_PREFIX = "corda."
|
private const val CORDA_PROPERTY_PREFIX = "corda."
|
||||||
|
private const val UPPERCASE_PROPERTY_PREFIX = "CORDA."
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(javaClass)
|
private val log = LoggerFactory.getLogger(javaClass)
|
||||||
fun loadConfig(baseDirectory: Path,
|
fun loadConfig(baseDirectory: Path,
|
||||||
@ -68,10 +72,48 @@ object ConfigHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Config.cordaEntriesOnly(): Config {
|
private fun Config.cordaEntriesOnly(): Config {
|
||||||
return ConfigFactory.parseMap(toProperties()
|
val cordaPropOccurrences = mutableSetOf<String>()
|
||||||
.filterKeys { (it as String).startsWith(CORDA_PROPERTY_PREFIX) }
|
val badKeyConversions = mutableSetOf<String>()
|
||||||
.mapKeys { (it.key as String).removePrefix(CORDA_PROPERTY_PREFIX) }
|
|
||||||
)
|
return ConfigFactory.parseMap(
|
||||||
|
toProperties()
|
||||||
|
.mapKeys {
|
||||||
|
var newKey = (it.key as String)
|
||||||
|
.replace('_', '.')
|
||||||
|
.replace(UPPERCASE_PROPERTY_PREFIX, CORDA_PROPERTY_PREFIX)
|
||||||
|
|
||||||
|
if (!newKey.startsWith(CORDA_PROPERTY_PREFIX)) {
|
||||||
|
return@mapKeys newKey
|
||||||
|
}
|
||||||
|
|
||||||
|
newKey = newKey.substring(CORDA_PROPERTY_PREFIX.length)
|
||||||
|
|
||||||
|
if (cordaPropOccurrences.contains(newKey))
|
||||||
|
{
|
||||||
|
throw ShadowingException(it.key.toString(), newKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
cordaPropOccurrences.add(newKey)
|
||||||
|
|
||||||
|
newKey.let { key ->
|
||||||
|
val cfg = ConfigFactory.parseMap(mapOf(key to it.value))
|
||||||
|
val result = V1NodeConfigurationSpec.validate(cfg, Configuration.Validation.Options(strict = true))
|
||||||
|
|
||||||
|
val isInvalidProperty = result.errors.any { err -> err is Configuration.Validation.Error.Unknown }
|
||||||
|
if (isInvalidProperty) {
|
||||||
|
Node.printWarning(
|
||||||
|
"${it.key} (property or environment variable) cannot be mapped to an existing Corda" +
|
||||||
|
" config property and thus won't be used as a config override!" +
|
||||||
|
" It won't be passed as a config override! If that was the intention " +
|
||||||
|
" double check the spelling and ensure there is such config key.")
|
||||||
|
badKeyConversions.add(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
CORDA_PROPERTY_PREFIX + key
|
||||||
|
}
|
||||||
|
}.filterKeys { it.startsWith(CORDA_PROPERTY_PREFIX) }
|
||||||
|
.mapKeys { it.key.substring(CORDA_PROPERTY_PREFIX.length) }
|
||||||
|
.filterKeys { !badKeyConversions.contains(it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package net.corda.node.services.config
|
||||||
|
|
||||||
|
import com.typesafe.config.ConfigException
|
||||||
|
|
||||||
|
class ShadowingException(definedProperty : String, convertedProperty : String)
|
||||||
|
: ConfigException(
|
||||||
|
"Environment variable $definedProperty is shadowing another property transformed to $convertedProperty")
|
@ -201,7 +201,8 @@ fun <A> driver(defaultParameters: DriverParameters = DriverParameters(), dsl: Dr
|
|||||||
inMemoryDB = defaultParameters.inMemoryDB,
|
inMemoryDB = defaultParameters.inMemoryDB,
|
||||||
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
||||||
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
||||||
djvmCordaSource = defaultParameters.djvmCordaSource
|
djvmCordaSource = defaultParameters.djvmCordaSource,
|
||||||
|
environmentVariables = defaultParameters.environmentVariables
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
dsl = dsl
|
dsl = dsl
|
||||||
@ -261,7 +262,8 @@ data class DriverParameters(
|
|||||||
val inMemoryDB: Boolean = true,
|
val inMemoryDB: Boolean = true,
|
||||||
val cordappsForAllNodes: Collection<TestCordapp>? = null,
|
val cordappsForAllNodes: Collection<TestCordapp>? = null,
|
||||||
val djvmBootstrapSource: Path? = null,
|
val djvmBootstrapSource: Path? = null,
|
||||||
val djvmCordaSource: List<Path> = emptyList()
|
val djvmCordaSource: List<Path> = emptyList(),
|
||||||
|
val environmentVariables : Map<String, String> = emptyMap()
|
||||||
) {
|
) {
|
||||||
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes)
|
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes)
|
||||||
|
|
||||||
@ -301,7 +303,8 @@ data class DriverParameters(
|
|||||||
|
|
||||||
// These fields have been added in v4.4
|
// These fields have been added in v4.4
|
||||||
djvmBootstrapSource = null,
|
djvmBootstrapSource = null,
|
||||||
djvmCordaSource = emptyList()
|
djvmCordaSource = emptyList(),
|
||||||
|
environmentVariables = emptyMap()
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -420,6 +423,7 @@ data class DriverParameters(
|
|||||||
fun withCordappsForAllNodes(cordappsForAllNodes: Collection<TestCordapp>?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes)
|
fun withCordappsForAllNodes(cordappsForAllNodes: Collection<TestCordapp>?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes)
|
||||||
fun withDjvmBootstrapSource(djvmBootstrapSource: Path?): DriverParameters = copy(djvmBootstrapSource = djvmBootstrapSource)
|
fun withDjvmBootstrapSource(djvmBootstrapSource: Path?): DriverParameters = copy(djvmBootstrapSource = djvmBootstrapSource)
|
||||||
fun withDjvmCordaSource(djvmCordaSource: List<Path>): DriverParameters = copy(djvmCordaSource = djvmCordaSource)
|
fun withDjvmCordaSource(djvmCordaSource: List<Path>): DriverParameters = copy(djvmCordaSource = djvmCordaSource)
|
||||||
|
fun withEnvironmentVariables(variables : Map<String, String>): DriverParameters = copy(environmentVariables = variables)
|
||||||
|
|
||||||
fun copy(
|
fun copy(
|
||||||
isDebug: Boolean,
|
isDebug: Boolean,
|
||||||
@ -515,9 +519,9 @@ data class DriverParameters(
|
|||||||
notaryCustomOverrides = notaryCustomOverrides,
|
notaryCustomOverrides = notaryCustomOverrides,
|
||||||
inMemoryDB = inMemoryDB,
|
inMemoryDB = inMemoryDB,
|
||||||
cordappsForAllNodes = cordappsForAllNodes,
|
cordappsForAllNodes = cordappsForAllNodes,
|
||||||
|
|
||||||
// These fields have been added in v4.4
|
// These fields have been added in v4.4
|
||||||
djvmBootstrapSource = djvmBootstrapSource,
|
djvmBootstrapSource = djvmBootstrapSource,
|
||||||
djvmCordaSource = djvmCordaSource
|
djvmCordaSource = djvmCordaSource,
|
||||||
|
environmentVariables = environmentVariables
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -122,7 +122,8 @@ class DriverDSLImpl(
|
|||||||
val inMemoryDB: Boolean,
|
val inMemoryDB: Boolean,
|
||||||
val cordappsForAllNodes: Collection<TestCordappInternal>?,
|
val cordappsForAllNodes: Collection<TestCordappInternal>?,
|
||||||
val djvmBootstrapSource: Path?,
|
val djvmBootstrapSource: Path?,
|
||||||
val djvmCordaSource: List<Path>
|
val djvmCordaSource: List<Path>,
|
||||||
|
val environmentVariables : Map<String, String>
|
||||||
) : InternalDriverDSL {
|
) : InternalDriverDSL {
|
||||||
|
|
||||||
private var _executorService: ScheduledExecutorService? = null
|
private var _executorService: ScheduledExecutorService? = null
|
||||||
@ -335,9 +336,11 @@ class DriverDSLImpl(
|
|||||||
} else {
|
} else {
|
||||||
startOutOfProcessMiniNode(
|
startOutOfProcessMiniNode(
|
||||||
config,
|
config,
|
||||||
"initial-registration",
|
arrayOf(
|
||||||
"--network-root-truststore=${rootTruststorePath.toAbsolutePath()}",
|
"initial-registration",
|
||||||
"--network-root-truststore-password=$rootTruststorePassword"
|
"--network-root-truststore=${rootTruststorePath.toAbsolutePath()}",
|
||||||
|
"--network-root-truststore-password=$rootTruststorePassword"
|
||||||
|
)
|
||||||
).map { config }
|
).map { config }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -504,7 +507,7 @@ class DriverDSLImpl(
|
|||||||
} else {
|
} else {
|
||||||
// TODO The config we use here is uses a hardocded p2p port which changes when the node is run proper
|
// TODO The config we use here is uses a hardocded p2p port which changes when the node is run proper
|
||||||
// This causes two node info files to be generated.
|
// This causes two node info files to be generated.
|
||||||
startOutOfProcessMiniNode(config, "generate-node-info").map {
|
startOutOfProcessMiniNode(config, arrayOf("generate-node-info")).map {
|
||||||
// Once done we have to read the signed node info file that's been generated
|
// Once done we have to read the signed node info file that's been generated
|
||||||
val nodeInfoFile = config.corda.baseDirectory.list { paths ->
|
val nodeInfoFile = config.corda.baseDirectory.list { paths ->
|
||||||
paths.filter { it.fileName.toString().startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get()
|
paths.filter { it.fileName.toString().startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get()
|
||||||
@ -590,20 +593,20 @@ class DriverDSLImpl(
|
|||||||
* Start the node with the given flag which is expected to start the node for some function, which once complete will
|
* Start the node with the given flag which is expected to start the node for some function, which once complete will
|
||||||
* terminate the node.
|
* terminate the node.
|
||||||
*/
|
*/
|
||||||
@Suppress("SpreadOperator")
|
private fun startOutOfProcessMiniNode(config: NodeConfig, extraCmdLineFlag: Array<String> = emptyArray()): CordaFuture<Unit> {
|
||||||
private fun startOutOfProcessMiniNode(config: NodeConfig, vararg extraCmdLineFlag: String): CordaFuture<Unit> {
|
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val process = startOutOfProcessNode(
|
val process = startOutOfProcessNode(
|
||||||
config,
|
config,
|
||||||
quasarJarPath,
|
quasarJarPath,
|
||||||
debugPort,
|
debugPort,
|
||||||
bytemanJarPath,
|
bytemanJarPath,
|
||||||
null,
|
null,
|
||||||
systemProperties,
|
systemProperties,
|
||||||
"512m",
|
"512m",
|
||||||
null,
|
null,
|
||||||
ZonedDateTime.now().format(DateTimeFormatter.ofPattern("HHmmss.SSS")),
|
ZonedDateTime.now().format(DateTimeFormatter.ofPattern("HHmmss.SSS")),
|
||||||
*extraCmdLineFlag
|
environmentVariables,
|
||||||
|
extraCmdLineFlag
|
||||||
)
|
)
|
||||||
|
|
||||||
return poll(executorService, "$extraCmdLineFlag (${config.corda.myLegalName})") {
|
return poll(executorService, "$extraCmdLineFlag (${config.corda.myLegalName})") {
|
||||||
@ -664,15 +667,16 @@ class DriverDSLImpl(
|
|||||||
} else {
|
} else {
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val process = startOutOfProcessNode(
|
val process = startOutOfProcessNode(
|
||||||
config,
|
config,
|
||||||
quasarJarPath,
|
quasarJarPath,
|
||||||
debugPort,
|
debugPort,
|
||||||
bytemanJarPath,
|
bytemanJarPath,
|
||||||
bytemanPort,
|
bytemanPort,
|
||||||
systemProperties,
|
systemProperties,
|
||||||
parameters.maximumHeapSize,
|
parameters.maximumHeapSize,
|
||||||
parameters.logLevelOverride,
|
parameters.logLevelOverride,
|
||||||
identifier
|
identifier,
|
||||||
|
environmentVariables
|
||||||
)
|
)
|
||||||
|
|
||||||
// Destroy the child process when the parent exits.This is needed even when `waitForAllNodesToFinish` is
|
// Destroy the child process when the parent exits.This is needed even when `waitForAllNodesToFinish` is
|
||||||
@ -838,16 +842,17 @@ class DriverDSLImpl(
|
|||||||
|
|
||||||
@Suppress("ComplexMethod", "MaxLineLength", "LongParameterList")
|
@Suppress("ComplexMethod", "MaxLineLength", "LongParameterList")
|
||||||
private fun startOutOfProcessNode(
|
private fun startOutOfProcessNode(
|
||||||
config: NodeConfig,
|
config: NodeConfig,
|
||||||
quasarJarPath: String,
|
quasarJarPath: String,
|
||||||
debugPort: Int?,
|
debugPort: Int?,
|
||||||
bytemanJarPath: String?,
|
bytemanJarPath: String?,
|
||||||
bytemanPort: Int?,
|
bytemanPort: Int?,
|
||||||
overriddenSystemProperties: Map<String, String>,
|
overriddenSystemProperties: Map<String, String>,
|
||||||
maximumHeapSize: String,
|
maximumHeapSize: String,
|
||||||
logLevelOverride: String?,
|
logLevelOverride: String?,
|
||||||
identifier: String,
|
identifier: String,
|
||||||
vararg extraCmdLineFlag: String
|
environmentVariables : Map<String,String>,
|
||||||
|
extraCmdLineFlag: Array<String> = emptyArray()
|
||||||
): Process {
|
): Process {
|
||||||
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " +
|
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " +
|
||||||
"debug port is " + (debugPort ?: "not enabled") + ", " +
|
"debug port is " + (debugPort ?: "not enabled") + ", " +
|
||||||
@ -892,7 +897,7 @@ class DriverDSLImpl(
|
|||||||
"--base-directory=${config.corda.baseDirectory}",
|
"--base-directory=${config.corda.baseDirectory}",
|
||||||
"--logging-level=$loggingLevel",
|
"--logging-level=$loggingLevel",
|
||||||
"--no-local-shell").also {
|
"--no-local-shell").also {
|
||||||
it += extraCmdLineFlag
|
it.addAll(extraCmdLineFlag)
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
val bytemanJvmArgs = {
|
val bytemanJvmArgs = {
|
||||||
@ -920,14 +925,15 @@ class DriverDSLImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ProcessUtilities.startJavaProcess(
|
return ProcessUtilities.startJavaProcess(
|
||||||
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
|
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
|
||||||
arguments = arguments,
|
arguments = arguments,
|
||||||
jdwpPort = debugPort,
|
jdwpPort = debugPort,
|
||||||
extraJvmArguments = extraJvmArguments + bytemanJvmArgs + "-Dnet.corda.node.printErrorsToStdErr=true",
|
extraJvmArguments = extraJvmArguments + bytemanJvmArgs + "-Dnet.corda.node.printErrorsToStdErr=true",
|
||||||
workingDirectory = config.corda.baseDirectory,
|
workingDirectory = config.corda.baseDirectory,
|
||||||
maximumHeapSize = maximumHeapSize,
|
maximumHeapSize = maximumHeapSize,
|
||||||
classPath = cp,
|
classPath = cp,
|
||||||
identifier = identifier
|
identifier = identifier,
|
||||||
|
environmentVariables = environmentVariables
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,24 +1144,25 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
|
|||||||
val serializationEnv = setDriverSerialization()
|
val serializationEnv = setDriverSerialization()
|
||||||
val driverDsl = driverDslWrapper(
|
val driverDsl = driverDslWrapper(
|
||||||
DriverDSLImpl(
|
DriverDSLImpl(
|
||||||
portAllocation = defaultParameters.portAllocation,
|
portAllocation = defaultParameters.portAllocation,
|
||||||
debugPortAllocation = defaultParameters.debugPortAllocation,
|
debugPortAllocation = defaultParameters.debugPortAllocation,
|
||||||
systemProperties = defaultParameters.systemProperties,
|
systemProperties = defaultParameters.systemProperties,
|
||||||
driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(),
|
driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(),
|
||||||
useTestClock = defaultParameters.useTestClock,
|
useTestClock = defaultParameters.useTestClock,
|
||||||
isDebug = defaultParameters.isDebug,
|
isDebug = defaultParameters.isDebug,
|
||||||
startNodesInProcess = defaultParameters.startNodesInProcess,
|
startNodesInProcess = defaultParameters.startNodesInProcess,
|
||||||
waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish,
|
waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish,
|
||||||
extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan,
|
extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan,
|
||||||
jmxPolicy = defaultParameters.jmxPolicy,
|
jmxPolicy = defaultParameters.jmxPolicy,
|
||||||
notarySpecs = defaultParameters.notarySpecs,
|
notarySpecs = defaultParameters.notarySpecs,
|
||||||
compatibilityZone = null,
|
compatibilityZone = null,
|
||||||
networkParameters = defaultParameters.networkParameters,
|
networkParameters = defaultParameters.networkParameters,
|
||||||
notaryCustomOverrides = defaultParameters.notaryCustomOverrides,
|
notaryCustomOverrides = defaultParameters.notaryCustomOverrides,
|
||||||
inMemoryDB = defaultParameters.inMemoryDB,
|
inMemoryDB = defaultParameters.inMemoryDB,
|
||||||
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
||||||
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
||||||
djvmCordaSource = defaultParameters.djvmCordaSource
|
djvmCordaSource = defaultParameters.djvmCordaSource,
|
||||||
|
environmentVariables = defaultParameters.environmentVariables
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
||||||
@ -1252,28 +1259,30 @@ fun <A> internalDriver(
|
|||||||
cordappsForAllNodes: Collection<TestCordappInternal>? = null,
|
cordappsForAllNodes: Collection<TestCordappInternal>? = null,
|
||||||
djvmBootstrapSource: Path? = null,
|
djvmBootstrapSource: Path? = null,
|
||||||
djvmCordaSource: List<Path> = emptyList(),
|
djvmCordaSource: List<Path> = emptyList(),
|
||||||
|
environmentVariables: Map<String, String> = emptyMap(),
|
||||||
dsl: DriverDSLImpl.() -> A
|
dsl: DriverDSLImpl.() -> A
|
||||||
): A {
|
): A {
|
||||||
return genericDriver(
|
return genericDriver(
|
||||||
driverDsl = DriverDSLImpl(
|
driverDsl = DriverDSLImpl(
|
||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
debugPortAllocation = debugPortAllocation,
|
debugPortAllocation = debugPortAllocation,
|
||||||
systemProperties = systemProperties,
|
systemProperties = systemProperties,
|
||||||
driverDirectory = driverDirectory.toAbsolutePath(),
|
driverDirectory = driverDirectory.toAbsolutePath(),
|
||||||
useTestClock = useTestClock,
|
useTestClock = useTestClock,
|
||||||
isDebug = isDebug,
|
isDebug = isDebug,
|
||||||
startNodesInProcess = startNodesInProcess,
|
startNodesInProcess = startNodesInProcess,
|
||||||
waitForAllNodesToFinish = waitForAllNodesToFinish,
|
waitForAllNodesToFinish = waitForAllNodesToFinish,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
networkParameters = networkParameters,
|
networkParameters = networkParameters,
|
||||||
notaryCustomOverrides = notaryCustomOverrides,
|
notaryCustomOverrides = notaryCustomOverrides,
|
||||||
inMemoryDB = inMemoryDB,
|
inMemoryDB = inMemoryDB,
|
||||||
cordappsForAllNodes = cordappsForAllNodes,
|
cordappsForAllNodes = cordappsForAllNodes,
|
||||||
djvmBootstrapSource = djvmBootstrapSource,
|
djvmBootstrapSource = djvmBootstrapSource,
|
||||||
djvmCordaSource = djvmCordaSource
|
djvmCordaSource = djvmCordaSource,
|
||||||
|
environmentVariables = environmentVariables
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
dsl = dsl
|
dsl = dsl
|
||||||
|
@ -5,15 +5,26 @@ import java.io.File
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
object ProcessUtilities {
|
object ProcessUtilities {
|
||||||
|
@Suppress("LongParameterList")
|
||||||
inline fun <reified C : Any> startJavaProcess(
|
inline fun <reified C : Any> startJavaProcess(
|
||||||
arguments: List<String>,
|
arguments: List<String>,
|
||||||
classPath: List<String> = defaultClassPath,
|
classPath: List<String> = defaultClassPath,
|
||||||
workingDirectory: Path? = null,
|
workingDirectory: Path? = null,
|
||||||
jdwpPort: Int? = null,
|
jdwpPort: Int? = null,
|
||||||
extraJvmArguments: List<String> = emptyList(),
|
extraJvmArguments: List<String> = emptyList(),
|
||||||
maximumHeapSize: String? = null
|
maximumHeapSize: String? = null,
|
||||||
|
environmentVariables: Map<String, String> = emptyMap()
|
||||||
): Process {
|
): Process {
|
||||||
return startJavaProcess(C::class.java.name, arguments, classPath, workingDirectory, jdwpPort, extraJvmArguments, maximumHeapSize)
|
return startJavaProcess(
|
||||||
|
C::class.java.name,
|
||||||
|
arguments,
|
||||||
|
classPath,
|
||||||
|
workingDirectory,
|
||||||
|
jdwpPort,
|
||||||
|
extraJvmArguments,
|
||||||
|
maximumHeapSize,
|
||||||
|
environmentVariables = environmentVariables
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@ -25,7 +36,8 @@ object ProcessUtilities {
|
|||||||
jdwpPort: Int? = null,
|
jdwpPort: Int? = null,
|
||||||
extraJvmArguments: List<String> = emptyList(),
|
extraJvmArguments: List<String> = emptyList(),
|
||||||
maximumHeapSize: String? = null,
|
maximumHeapSize: String? = null,
|
||||||
identifier: String = ""
|
identifier: String = "",
|
||||||
|
environmentVariables: Map<String,String> = emptyMap()
|
||||||
): Process {
|
): Process {
|
||||||
val command = mutableListOf<String>().apply {
|
val command = mutableListOf<String>().apply {
|
||||||
add(javaPath)
|
add(javaPath)
|
||||||
@ -38,6 +50,7 @@ object ProcessUtilities {
|
|||||||
}
|
}
|
||||||
return ProcessBuilder(command).apply {
|
return ProcessBuilder(command).apply {
|
||||||
inheritIO()
|
inheritIO()
|
||||||
|
environment().putAll(environmentVariables)
|
||||||
environment()["CLASSPATH"] = classPath.joinToString(File.pathSeparator)
|
environment()["CLASSPATH"] = classPath.joinToString(File.pathSeparator)
|
||||||
if (workingDirectory != null) {
|
if (workingDirectory != null) {
|
||||||
// An identifier may be handy if the same process started, killed and then re-started. Without the identifier
|
// An identifier may be handy if the same process started, killed and then re-started. Without the identifier
|
||||||
|
@ -124,6 +124,7 @@ fun <A> rpcDriver(
|
|||||||
cordappsForAllNodes: Collection<TestCordappInternal>? = null,
|
cordappsForAllNodes: Collection<TestCordappInternal>? = null,
|
||||||
djvmBootstrapSource: Path? = null,
|
djvmBootstrapSource: Path? = null,
|
||||||
djvmCordaSource: List<Path> = emptyList(),
|
djvmCordaSource: List<Path> = emptyList(),
|
||||||
|
environmentVariables: Map<String, String> = emptyMap(),
|
||||||
dsl: RPCDriverDSL.() -> A
|
dsl: RPCDriverDSL.() -> A
|
||||||
): A {
|
): A {
|
||||||
return genericDriver(
|
return genericDriver(
|
||||||
@ -146,7 +147,8 @@ fun <A> rpcDriver(
|
|||||||
inMemoryDB = inMemoryDB,
|
inMemoryDB = inMemoryDB,
|
||||||
cordappsForAllNodes = cordappsForAllNodes,
|
cordappsForAllNodes = cordappsForAllNodes,
|
||||||
djvmBootstrapSource = djvmBootstrapSource,
|
djvmBootstrapSource = djvmBootstrapSource,
|
||||||
djvmCordaSource = djvmCordaSource
|
djvmCordaSource = djvmCordaSource,
|
||||||
|
environmentVariables = environmentVariables
|
||||||
), externalTrace
|
), externalTrace
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user