EG-3456: Make network parameters path configurable (#6531)

* Update docker image

* EG-3456: Make network parameters path configurable

* EG-3456: Remove filename from network parameters path property

* EG-3456: Add tests for network parameters and node configuration

* Revert docker image update

* EG-3456: Resolve network parameters path against base directory

* EG-3456: Add tests for network parameters path, increase test timeout limits

* EG-3456: Replace baseDirectory argument with networkParametersPath in NetworkParametersReader

* EG-3456: Refactor tests to reuse node configuration object

* EG-3456: Pass networkParametersPath as argument instead of baseDirectory
This commit is contained in:
Yash Nabar 2020-09-07 09:49:37 +01:00 committed by GitHub
parent e069277830
commit d1735b8c42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 132 additions and 70 deletions

View File

@ -472,7 +472,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
var pendingAppChanges: Int = 0 var pendingAppChanges: Int = 0
var pendingCoreChanges: Int = 0 var pendingCoreChanges: Int = 0
database.startHikariPool(props, metricRegistry) { dataSource, haveCheckpoints -> database.startHikariPool(props, metricRegistry) { dataSource, haveCheckpoints ->
val schemaMigration = SchemaMigration(dataSource, cordappLoader, configuration.baseDirectory, configuration.myLegalName) val schemaMigration = SchemaMigration(dataSource, cordappLoader, configuration.networkParametersPath, configuration.myLegalName)
if(updateCoreSchemas) { if(updateCoreSchemas) {
schemaMigration.runMigration(haveCheckpoints, schemaService.internalSchemas, true) schemaMigration.runMigration(haveCheckpoints, schemaService.internalSchemas, true)
} else { } else {
@ -490,7 +490,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
Node.printBasicNodeInfo("Initialising CorDapps to get schemas created by hibernate") Node.printBasicNodeInfo("Initialising CorDapps to get schemas created by hibernate")
val trustRoot = configuration.initKeyStores(cryptoService) val trustRoot = configuration.initKeyStores(cryptoService)
networkMapClient?.start(trustRoot) networkMapClient?.start(trustRoot)
val (netParams, signedNetParams) = NetworkParametersReader(trustRoot, networkMapClient, configuration.baseDirectory).read() val (netParams, signedNetParams) = NetworkParametersReader(trustRoot, networkMapClient, configuration.networkParametersPath).read()
log.info("Loaded network parameters: $netParams") log.info("Loaded network parameters: $netParams")
check(netParams.minimumPlatformVersion <= versionInfo.platformVersion) { check(netParams.minimumPlatformVersion <= versionInfo.platformVersion) {
"Node's platform version is lower than network's required minimumPlatformVersion" "Node's platform version is lower than network's required minimumPlatformVersion"
@ -523,7 +523,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
if (hikariProperties.isEmpty) throw DatabaseConfigurationException("There must be a database configured.") if (hikariProperties.isEmpty) throw DatabaseConfigurationException("There must be a database configured.")
val dataSource = DataSourceFactory.createDataSource(hikariProperties, metricRegistry = metricRegistry) val dataSource = DataSourceFactory.createDataSource(hikariProperties, metricRegistry = metricRegistry)
SchemaMigration(dataSource, cordappLoader, configuration.baseDirectory, configuration.myLegalName) SchemaMigration(dataSource, cordappLoader, configuration.networkParametersPath, configuration.myLegalName)
.synchroniseSchemas(schemaService.appSchemas, false) .synchroniseSchemas(schemaService.appSchemas, false)
Node.printBasicNodeInfo("CorDapp schemas synchronised") Node.printBasicNodeInfo("CorDapp schemas synchronised")
} }
@ -554,7 +554,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
startShell() startShell()
networkMapClient?.start(trustRoot) networkMapClient?.start(trustRoot)
val networkParametersReader = NetworkParametersReader(trustRoot, networkMapClient, configuration.baseDirectory) val networkParametersReader = NetworkParametersReader(trustRoot, networkMapClient, configuration.networkParametersPath)
val (netParams, signedNetParams) = networkParametersReader.read() val (netParams, signedNetParams) = networkParametersReader.read()
log.info("Loaded network parameters: $netParams") log.info("Loaded network parameters: $netParams")
check(netParams.minimumPlatformVersion <= versionInfo.platformVersion) { check(netParams.minimumPlatformVersion <= versionInfo.platformVersion) {
@ -1027,7 +1027,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
protected open fun startHikariPool() = protected open fun startHikariPool() =
database.startHikariPool(configuration.dataSourceProperties, metricRegistry) { dataSource, haveCheckpoints -> database.startHikariPool(configuration.dataSourceProperties, metricRegistry) { dataSource, haveCheckpoints ->
SchemaMigration(dataSource, cordappLoader, configuration.baseDirectory, configuration.myLegalName) SchemaMigration(dataSource, cordappLoader, configuration.networkParametersPath, configuration.myLegalName)
.checkOrUpdate(schemaService.internalSchemas, runMigrationScripts, haveCheckpoints, true) .checkOrUpdate(schemaService.internalSchemas, runMigrationScripts, haveCheckpoints, true)
.checkOrUpdate(schemaService.appSchemas, runMigrationScripts, haveCheckpoints && !allowAppSchemaUpgradeWithCheckpoints, false) .checkOrUpdate(schemaService.appSchemas, runMigrationScripts, haveCheckpoints && !allowAppSchemaUpgradeWithCheckpoints, false)
} }

View File

@ -1,7 +1,11 @@
package net.corda.node.internal package net.corda.node.internal
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.internal.* import net.corda.core.internal.copyTo
import net.corda.core.internal.div
import net.corda.core.internal.exists
import net.corda.core.internal.moveTo
import net.corda.core.internal.readObject
import net.corda.core.node.NetworkParameters import net.corda.core.node.NetworkParameters
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
@ -16,7 +20,7 @@ import java.security.cert.X509Certificate
class NetworkParametersReader(private val trustRoot: X509Certificate, class NetworkParametersReader(private val trustRoot: X509Certificate,
private val networkMapClient: NetworkMapClient?, private val networkMapClient: NetworkMapClient?,
private val baseDirectory: Path) { private val networkParamsPath: Path) {
companion object { companion object {
private val logger = contextLogger() private val logger = contextLogger()
} }
@ -28,13 +32,13 @@ class NetworkParametersReader(private val trustRoot: X509Certificate,
"Both network parameters and network parameters update files don't match" + "Both network parameters and network parameters update files don't match" +
"parameters advertised by network map. Please update node to use correct network parameters file." "parameters advertised by network map. Please update node to use correct network parameters file."
) )
class OldParams(previousParametersHash: SecureHash, advertisedParametersHash: SecureHash) : Error( class OldParams(previousParametersHash: SecureHash, advertisedParametersHash: SecureHash, path: Path) : Error(
"""Node is using network parameters with hash $previousParametersHash but the network map is advertising $advertisedParametersHash. """Node is using network parameters with hash $previousParametersHash but the network map is advertising $advertisedParametersHash.
To resolve this mismatch, and move to the current parameters, delete the $NETWORK_PARAMS_FILE_NAME file from the node's directory and restart.""" To resolve this mismatch, and move to the current parameters, delete the network-parameters file at location $path and restart."""
) )
} }
private val networkParamsFile = baseDirectory / NETWORK_PARAMS_FILE_NAME private val networkParamsFile = networkParamsPath / NETWORK_PARAMS_FILE_NAME
fun read(): NetworkParametersAndSigned { fun read(): NetworkParametersAndSigned {
val advertisedParametersHash = try { val advertisedParametersHash = try {
@ -68,9 +72,9 @@ class NetworkParametersReader(private val trustRoot: X509Certificate,
} }
private fun readParametersUpdate(advertisedParametersHash: SecureHash, previousParametersHash: SecureHash): SignedNetworkParameters { private fun readParametersUpdate(advertisedParametersHash: SecureHash, previousParametersHash: SecureHash): SignedNetworkParameters {
val parametersUpdateFile = baseDirectory / NETWORK_PARAMS_UPDATE_FILE_NAME val parametersUpdateFile = networkParamsPath / NETWORK_PARAMS_UPDATE_FILE_NAME
if (!parametersUpdateFile.exists()) { if (!parametersUpdateFile.exists()) {
throw Error.OldParams(previousParametersHash, advertisedParametersHash) throw Error.OldParams(previousParametersHash, advertisedParametersHash, networkParamsPath)
} }
val signedUpdatedParameters = parametersUpdateFile.readObject<SignedNetworkParameters>() val signedUpdatedParameters = parametersUpdateFile.readObject<SignedNetworkParameters>()
if (signedUpdatedParameters.raw.hash != advertisedParametersHash) { if (signedUpdatedParameters.raw.hash != advertisedParametersHash) {
@ -87,7 +91,9 @@ class NetworkParametersReader(private val trustRoot: X509Certificate,
networkMapClient ?: throw Error.NetworkMapNotConfigured() networkMapClient ?: throw Error.NetworkMapNotConfigured()
val signedParams = networkMapClient.getNetworkParameters(parametersHash) val signedParams = networkMapClient.getNetworkParameters(parametersHash)
signedParams.verifiedNetworkParametersCert(trustRoot) signedParams.verifiedNetworkParametersCert(trustRoot)
signedParams.serialize().open().copyTo(baseDirectory / NETWORK_PARAMS_FILE_NAME) networkParamsFile.parent.toFile().mkdirs()
signedParams.serialize().open().copyTo(networkParamsFile)
logger.info("Saved network parameters into: $networkParamsFile")
return signedParams return signedParams
} }

View File

@ -87,6 +87,8 @@ interface NodeConfiguration : ConfigurationWithOptionsContainer {
val networkParameterAcceptanceSettings: NetworkParameterAcceptanceSettings? val networkParameterAcceptanceSettings: NetworkParameterAcceptanceSettings?
val networkParametersPath: Path
val blacklistedAttachmentSigningKeys: List<String> val blacklistedAttachmentSigningKeys: List<String>
val flowExternalOperationThreadPoolSize: Int val flowExternalOperationThreadPoolSize: Int

View File

@ -84,7 +84,8 @@ data class NodeConfigurationImpl(
override val configurationWithOptions: ConfigurationWithOptions, override val configurationWithOptions: ConfigurationWithOptions,
override val flowExternalOperationThreadPoolSize: Int = Defaults.flowExternalOperationThreadPoolSize, override val flowExternalOperationThreadPoolSize: Int = Defaults.flowExternalOperationThreadPoolSize,
override val quasarExcludePackages: List<String> = Defaults.quasarExcludePackages, override val quasarExcludePackages: List<String> = Defaults.quasarExcludePackages,
override val reloadCheckpointAfterSuspend: Boolean = Defaults.reloadCheckpointAfterSuspend override val reloadCheckpointAfterSuspend: Boolean = Defaults.reloadCheckpointAfterSuspend,
override val networkParametersPath: Path = baseDirectory
) : NodeConfiguration { ) : NodeConfiguration {
internal object Defaults { internal object Defaults {

View File

@ -68,6 +68,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
private val flowExternalOperationThreadPoolSize by int().optional().withDefaultValue(Defaults.flowExternalOperationThreadPoolSize) private val flowExternalOperationThreadPoolSize by int().optional().withDefaultValue(Defaults.flowExternalOperationThreadPoolSize)
private val quasarExcludePackages by string().list().optional().withDefaultValue(Defaults.quasarExcludePackages) private val quasarExcludePackages by string().list().optional().withDefaultValue(Defaults.quasarExcludePackages)
private val reloadCheckpointAfterSuspend by boolean().optional().withDefaultValue(Defaults.reloadCheckpointAfterSuspend) private val reloadCheckpointAfterSuspend by boolean().optional().withDefaultValue(Defaults.reloadCheckpointAfterSuspend)
private val networkParametersPath by string().mapValid(::toPath).optional()
@Suppress("unused") @Suppress("unused")
private val custom by nestedObject().optional() private val custom by nestedObject().optional()
@Suppress("unused") @Suppress("unused")
@ -80,6 +81,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
val database = config[database] ?: Defaults.database(config[devMode]) val database = config[database] ?: Defaults.database(config[devMode])
val baseDirectoryPath = config[baseDirectory] val baseDirectoryPath = config[baseDirectory]
val cordappDirectories = config[cordappDirectories]?.map { baseDirectoryPath.resolve(it) } ?: Defaults.cordappsDirectories(baseDirectoryPath) val cordappDirectories = config[cordappDirectories]?.map { baseDirectoryPath.resolve(it) } ?: Defaults.cordappsDirectories(baseDirectoryPath)
val networkParametersPath = if (config[networkParametersPath] != null) baseDirectoryPath.resolve(config[networkParametersPath]) else baseDirectoryPath
val result = try { val result = try {
valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl( valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl(
baseDirectory = baseDirectoryPath, baseDirectory = baseDirectoryPath,
@ -136,7 +138,8 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Options.defaults), configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Options.defaults),
flowExternalOperationThreadPoolSize = config[flowExternalOperationThreadPoolSize], flowExternalOperationThreadPoolSize = config[flowExternalOperationThreadPoolSize],
quasarExcludePackages = config[quasarExcludePackages], quasarExcludePackages = config[quasarExcludePackages],
reloadCheckpointAfterSuspend = config[reloadCheckpointAfterSuspend] reloadCheckpointAfterSuspend = config[reloadCheckpointAfterSuspend],
networkParametersPath = networkParametersPath
)) ))
} catch (e: Exception) { } catch (e: Exception) {
return when (e) { return when (e) {

View File

@ -35,7 +35,7 @@ class NodeConfigurationImplTest {
@JvmField @JvmField
val tempFolder = TemporaryFolder() val tempFolder = TemporaryFolder()
@Test(timeout=3_000) @Test(timeout=6_000)
fun `can't have dev mode options if not in dev mode`() { fun `can't have dev mode options if not in dev mode`() {
val debugOptions = DevModeOptions() val debugOptions = DevModeOptions()
configDebugOptions(true, debugOptions) configDebugOptions(true, debugOptions)
@ -44,7 +44,7 @@ class NodeConfigurationImplTest {
configDebugOptions(false, null) configDebugOptions(false, null)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `can't have tlsCertCrlDistPoint null when tlsCertCrlIssuer is given`() { fun `can't have tlsCertCrlDistPoint null when tlsCertCrlIssuer is given`() {
val configValidationResult = configTlsCertCrlOptions(null, "C=US, L=New York, OU=Corda, O=R3 HoldCo LLC, CN=Corda Root CA").validate() val configValidationResult = configTlsCertCrlOptions(null, "C=US, L=New York, OU=Corda, O=R3 HoldCo LLC, CN=Corda Root CA").validate()
assertTrue { configValidationResult.isNotEmpty() } assertTrue { configValidationResult.isNotEmpty() }
@ -52,7 +52,7 @@ class NodeConfigurationImplTest {
assertThat(configValidationResult.first()).contains("tlsCertCrlIssuer") assertThat(configValidationResult.first()).contains("tlsCertCrlIssuer")
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `can't have tlsCertCrlDistPoint null when crlCheckSoftFail is false`() { fun `can't have tlsCertCrlDistPoint null when crlCheckSoftFail is false`() {
val configValidationResult = configTlsCertCrlOptions(null, null, false).validate() val configValidationResult = configTlsCertCrlOptions(null, null, false).validate()
assertTrue { configValidationResult.isNotEmpty() } assertTrue { configValidationResult.isNotEmpty() }
@ -60,7 +60,7 @@ class NodeConfigurationImplTest {
assertThat(configValidationResult.first()).contains("crlCheckSoftFail") assertThat(configValidationResult.first()).contains("crlCheckSoftFail")
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `check crashShell flags helper`() { fun `check crashShell flags helper`() {
assertFalse { testConfiguration.copy(sshd = null).shouldStartSSHDaemon() } assertFalse { testConfiguration.copy(sshd = null).shouldStartSSHDaemon() }
assertTrue { testConfiguration.copy(sshd = SSHDConfiguration(1234)).shouldStartSSHDaemon() } assertTrue { testConfiguration.copy(sshd = SSHDConfiguration(1234)).shouldStartSSHDaemon() }
@ -72,7 +72,7 @@ class NodeConfigurationImplTest {
assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() } assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `Dev mode is autodetected correctly`() { fun `Dev mode is autodetected correctly`() {
val os = System.getProperty("os.name") val os = System.getProperty("os.name")
@ -95,20 +95,20 @@ class NodeConfigurationImplTest {
System.setProperty("os.name", os) System.setProperty("os.name", os)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `Dev mode is read from the config over the autodetect logic`() { fun `Dev mode is read from the config over the autodetect logic`() {
assertTrue(getConfig("test-config-DevMode.conf").getBooleanCaseInsensitive("devMode")) assertTrue(getConfig("test-config-DevMode.conf").getBooleanCaseInsensitive("devMode"))
assertFalse(getConfig("test-config-noDevMode.conf").getBooleanCaseInsensitive("devMode")) assertFalse(getConfig("test-config-noDevMode.conf").getBooleanCaseInsensitive("devMode"))
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `Dev mode is true if overriden`() { fun `Dev mode is true if overriden`() {
assertTrue(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode")) assertTrue(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode"))
assertTrue(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode")) assertTrue(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode"))
assertTrue(getConfig("test-config-empty.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode")) assertTrue(getConfig("test-config-empty.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBooleanCaseInsensitive("devMode"))
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `Dev mode is false if overriden`() { fun `Dev mode is false if overriden`() {
assertFalse(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBooleanCaseInsensitive("devMode")) assertFalse(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBooleanCaseInsensitive("devMode"))
assertFalse(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBooleanCaseInsensitive("devMode")) assertFalse(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBooleanCaseInsensitive("devMode"))
@ -124,7 +124,7 @@ class NodeConfigurationImplTest {
) )
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `validation has error when compatibilityZoneURL is present and devMode is true`() { fun `validation has error when compatibilityZoneURL is present and devMode is true`() {
val configuration = testConfiguration.copy( val configuration = testConfiguration.copy(
devMode = true, devMode = true,
@ -135,7 +135,7 @@ class NodeConfigurationImplTest {
assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("compatibilityZoneURL") && error.contains("devMode") } assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("compatibilityZoneURL") && error.contains("devMode") }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `validation succeeds when compatibilityZoneURL is present and devMode is true and allowCompatibilityZoneURL is set`() { fun `validation succeeds when compatibilityZoneURL is present and devMode is true and allowCompatibilityZoneURL is set`() {
val configuration = testConfiguration.copy( val configuration = testConfiguration.copy(
devMode = true, devMode = true,
@ -146,19 +146,18 @@ class NodeConfigurationImplTest {
assertThat(errors).isEmpty() assertThat(errors).isEmpty()
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `errors for nested config keys contain path`() { fun `errors for nested config keys contain path`() {
var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
val missingPropertyPath = "rpcSettings.address" val missingPropertyPath = "rpcSettings.address"
rawConfig = rawConfig.withoutPath(missingPropertyPath) val config = rawConfig.withoutPath(missingPropertyPath)
assertThat(rawConfig.parseAsNodeConfiguration().errors.single()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(config.parseAsNodeConfiguration().errors.single()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
assertThat(error.message).contains(missingPropertyPath) assertThat(error.message).contains(missingPropertyPath)
assertThat(error.typeName).isEqualTo(NodeConfiguration::class.java.simpleName) assertThat(error.typeName).isEqualTo(NodeConfiguration::class.java.simpleName)
} }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `validation has error when compatibilityZone is present and devMode is true`() { fun `validation has error when compatibilityZone is present and devMode is true`() {
val configuration = testConfiguration.copy(devMode = true, networkServices = NetworkServicesConfig( val configuration = testConfiguration.copy(devMode = true, networkServices = NetworkServicesConfig(
URL("https://r3.com.doorman"), URL("https://r3.com.doorman"),
@ -169,7 +168,7 @@ class NodeConfigurationImplTest {
assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("networkServices") && error.contains("devMode") } assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("networkServices") && error.contains("devMode") }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `validation has error when both compatibilityZoneURL and networkServices are configured`() { fun `validation has error when both compatibilityZoneURL and networkServices are configured`() {
val configuration = testConfiguration.copy( val configuration = testConfiguration.copy(
devMode = false, devMode = false,
@ -185,19 +184,16 @@ class NodeConfigurationImplTest {
} }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `rpcAddress and rpcSettings_address are equivalent`() { fun `rpcAddress and rpcSettings_address are equivalent`() {
var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false)) var config = rawConfig.withoutPath("rpcSettings.address")
rawConfig = rawConfig.withoutPath("rpcSettings.address") config = config.withValue("rpcAddress", ConfigValueFactory.fromAnyRef("localhost:4444"))
rawConfig = rawConfig.withValue("rpcAddress", ConfigValueFactory.fromAnyRef("localhost:4444"))
assertThat(rawConfig.parseAsNodeConfiguration().isValid).isTrue() assertThat(config.parseAsNodeConfiguration().isValid).isTrue()
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `absolute base directory leads to correct cordapp directories`() { fun `absolute base directory leads to correct cordapp directories`() {
val rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
// Override base directory to have predictable experience on diff OSes // Override base directory to have predictable experience on diff OSes
val finalConfig = configOf( val finalConfig = configOf(
// Add substitution values here // Add substitution values here
@ -212,15 +208,13 @@ class NodeConfigurationImplTest {
assertEquals(listOf(baseDirPath / "./myCorDapps1", baseDirPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories) assertEquals(listOf(baseDirPath / "./myCorDapps1", baseDirPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `absolute base directory leads to correct default cordapp directory`() { fun `absolute base directory leads to correct default cordapp directory`() {
val rawConfig = ConfigFactory.parseResources("working-config-no-cordapps.conf", ConfigParseOptions.defaults().setAllowMissing(false))
// Override base directory to have predictable experience on diff OSes // Override base directory to have predictable experience on diff OSes
val finalConfig = configOf( val finalConfig = configOf(
// Add substitution values here // Add substitution values here
"baseDirectory" to tempFolder.root.canonicalPath) "baseDirectory" to tempFolder.root.canonicalPath)
.withFallback(rawConfig) .withFallback(rawConfigNoCordapps)
.resolve() .resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration() val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
@ -230,10 +224,8 @@ class NodeConfigurationImplTest {
assertEquals(listOf(baseDirPath / "cordapps"), nodeConfiguration.value().cordappDirectories) assertEquals(listOf(baseDirPath / "cordapps"), nodeConfiguration.value().cordappDirectories)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `relative base dir leads to correct cordapp directories`() { fun `relative base dir leads to correct cordapp directories`() {
val rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
val path = tempFolder.root.relativeTo(tempFolder.root.parentFile).toString() val path = tempFolder.root.relativeTo(tempFolder.root.parentFile).toString()
val fullPath = File(".").resolve(path).toString() val fullPath = File(".").resolve(path).toString()
// Override base directory to have predictable experience on diff OSes // Override base directory to have predictable experience on diff OSes
@ -249,17 +241,15 @@ class NodeConfigurationImplTest {
assertEquals(listOf(fullPath / "./myCorDapps1", fullPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories) assertEquals(listOf(fullPath / "./myCorDapps1", fullPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `relative base dir leads to correct default cordapp directory`() { fun `relative base dir leads to correct default cordapp directory`() {
val rawConfig = ConfigFactory.parseResources("working-config-no-cordapps.conf", ConfigParseOptions.defaults().setAllowMissing(false))
val path = tempFolder.root.relativeTo(tempFolder.root.parentFile).toString() val path = tempFolder.root.relativeTo(tempFolder.root.parentFile).toString()
val fullPath = File(".").resolve(path).toString() val fullPath = File(".").resolve(path).toString()
// Override base directory to have predictable experience on diff OSes // Override base directory to have predictable experience on diff OSes
val finalConfig = configOf( val finalConfig = configOf(
// Add substitution values here // Add substitution values here
"baseDirectory" to fullPath) "baseDirectory" to fullPath)
.withFallback(rawConfig) .withFallback(rawConfigNoCordapps)
.resolve() .resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration() val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
@ -268,17 +258,16 @@ class NodeConfigurationImplTest {
assertEquals(listOf(fullPath / "cordapps"), nodeConfiguration.value().cordappDirectories) assertEquals(listOf(fullPath / "cordapps"), nodeConfiguration.value().cordappDirectories)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `missing rpcSettings_adminAddress cause a graceful failure`() { fun `missing rpcSettings_adminAddress cause a graceful failure`() {
var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false)) val config = rawConfig.withoutPath("rpcSettings.adminAddress")
rawConfig = rawConfig.withoutPath("rpcSettings.adminAddress")
val config = rawConfig.parseAsNodeConfiguration() val nodeConfiguration = config.parseAsNodeConfiguration()
assertThat(config.errors.asSequence().map(Configuration.Validation.Error::message).filter { it.contains("rpcSettings.adminAddress") }.toList()).isNotEmpty assertThat(nodeConfiguration.errors.asSequence().map(Configuration.Validation.Error::message).filter { it.contains("rpcSettings.adminAddress") }.toList()).isNotEmpty
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `compatibilityZoneURL populates NetworkServices`() { fun `compatibilityZoneURL populates NetworkServices`() {
val compatibilityZoneURL = URI.create("https://r3.example.com").toURL() val compatibilityZoneURL = URI.create("https://r3.example.com").toURL()
val configuration = testConfiguration.copy( val configuration = testConfiguration.copy(
@ -290,14 +279,14 @@ class NodeConfigurationImplTest {
assertEquals(compatibilityZoneURL, configuration.networkServices!!.networkMapURL) assertEquals(compatibilityZoneURL, configuration.networkServices!!.networkMapURL)
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `jmxReporterType is null and defaults to Jokolia`() { fun `jmxReporterType is null and defaults to Jokolia`() {
val rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true))) val rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true)))
val nodeConfig = rawConfig.parseAsNodeConfiguration().value() val nodeConfig = rawConfig.parseAsNodeConfiguration().value()
assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString()) assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString())
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `jmxReporterType is not null and is set to New Relic`() { fun `jmxReporterType is not null and is set to New Relic`() {
var rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true))) var rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true)))
rawConfig = rawConfig.withValue("jmxReporterType", ConfigValueFactory.fromAnyRef("NEW_RELIC")) rawConfig = rawConfig.withValue("jmxReporterType", ConfigValueFactory.fromAnyRef("NEW_RELIC"))
@ -305,7 +294,7 @@ class NodeConfigurationImplTest {
assertEquals(JmxReporterType.NEW_RELIC.toString(), nodeConfig.jmxReporterType.toString()) assertEquals(JmxReporterType.NEW_RELIC.toString(), nodeConfig.jmxReporterType.toString())
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `jmxReporterType is not null and set to Jokolia`() { fun `jmxReporterType is not null and set to Jokolia`() {
var rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true))) var rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("devMode" to true)))
rawConfig = rawConfig.withValue("jmxReporterType", ConfigValueFactory.fromAnyRef("JOLOKIA")) rawConfig = rawConfig.withValue("jmxReporterType", ConfigValueFactory.fromAnyRef("JOLOKIA"))
@ -313,7 +302,7 @@ class NodeConfigurationImplTest {
assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString()) assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString())
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `network services`() { fun `network services`() {
val rawConfig = getConfig("test-config-with-networkservices.conf") val rawConfig = getConfig("test-config-with-networkservices.conf")
val nodeConfig = rawConfig.parseAsNodeConfiguration().value() val nodeConfig = rawConfig.parseAsNodeConfiguration().value()
@ -325,13 +314,54 @@ class NodeConfigurationImplTest {
} }
} }
@Test(timeout=3_000) @Test(timeout=6_000)
fun `check crlCheckArtemisServer flag`() { fun `check crlCheckArtemisServer flag`() {
assertFalse(getConfig("working-config.conf").parseAsNodeConfiguration().value().crlCheckArtemisServer) assertFalse(getConfig("working-config.conf").parseAsNodeConfiguration().value().crlCheckArtemisServer)
val rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("crlCheckArtemisServer" to true))) val rawConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("crlCheckArtemisServer" to true)))
assertTrue(rawConfig.parseAsNodeConfiguration().value().crlCheckArtemisServer) assertTrue(rawConfig.parseAsNodeConfiguration().value().crlCheckArtemisServer)
} }
@Test(timeout=6_000)
fun `absolute network parameters path is set as specified by node config`() {
val nodeConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("networkParametersPath" to tempFolder.root.canonicalPath))).parseAsNodeConfiguration().value()
assertEquals(nodeConfig.networkParametersPath, tempFolder.root.toPath())
}
@Test(timeout=6_000)
fun `relative network parameters path is set as specified by node config`() {
val path = tempFolder.root.relativeTo(tempFolder.root.parentFile).toString()
val fullPath = File(".").resolve(path).toString()
val nodeConfig = getConfig("working-config.conf", ConfigFactory.parseMap(mapOf("networkParametersPath" to fullPath))).parseAsNodeConfiguration().value()
assertEquals(nodeConfig.networkParametersPath, nodeConfig.baseDirectory.resolve(fullPath))
}
@Test(timeout=6_000)
fun `network parameters path is set as specified by node config with overridden base directory`() {
val finalConfig = configOf(
"baseDirectory" to "/path-to-base-directory",
"networkParametersPath" to "/network")
.withFallback(rawConfig)
.resolve()
val nodeConfig = finalConfig.parseAsNodeConfiguration().value()
assertEquals(nodeConfig.networkParametersPath, Paths.get("/network"))
}
@Test(timeout=6_000)
fun `network parameters path defaults to base directory`() {
val nodeConfig = getConfig("working-config.conf").parseAsNodeConfiguration().value()
assertEquals(nodeConfig.networkParametersPath, nodeConfig.baseDirectory)
}
@Test(timeout=6_000)
fun `network parameters path defaults to overridden base directory`() {
val finalConfig = configOf(
"baseDirectory" to "/path-to-base-directory")
.withFallback(rawConfig)
.resolve()
val nodeConfig = finalConfig.parseAsNodeConfiguration().value()
assertEquals(nodeConfig.networkParametersPath, Paths.get("/path-to-base-directory"))
}
private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfigurationImpl { private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfigurationImpl {
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions) return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
} }
@ -342,6 +372,9 @@ class NodeConfigurationImplTest {
private val testConfiguration = testNodeConfiguration() private val testConfiguration = testNodeConfiguration()
private val rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
private val rawConfigNoCordapps = ConfigFactory.parseResources("working-config-no-cordapps.conf", ConfigParseOptions.defaults().setAllowMissing(false))
private fun testNodeConfiguration(): NodeConfigurationImpl { private fun testNodeConfiguration(): NodeConfigurationImpl {
val baseDirectory = Paths.get(".") val baseDirectory = Paths.get(".")
val keyStorePassword = "cordacadevpass" val keyStorePassword = "cordacadevpass"

View File

@ -59,15 +59,31 @@ class NetworkParametersReaderTest {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `read correct set of parameters from file`() { fun `read correct set of parameters from file`() {
val baseDirectory = fs.getPath("/node").createDirectories() val networkParamsPath = fs.getPath("/node").createDirectories()
val oldParameters = testNetworkParameters(epoch = 1) val oldParameters = testNetworkParameters(epoch = 1)
NetworkParametersCopier(oldParameters).install(baseDirectory) NetworkParametersCopier(oldParameters).install(networkParamsPath)
NetworkParametersCopier(server.networkParameters, update = true).install(baseDirectory) // Parameters update file. NetworkParametersCopier(server.networkParameters, update = true).install(networkParamsPath) // Parameters update file.
val parameters = NetworkParametersReader(DEV_ROOT_CA.certificate, networkMapClient, baseDirectory).read().networkParameters val parameters = NetworkParametersReader(DEV_ROOT_CA.certificate, networkMapClient, networkParamsPath).read().networkParameters
assertFalse((baseDirectory / NETWORK_PARAMS_UPDATE_FILE_NAME).exists()) assertFalse((networkParamsPath / NETWORK_PARAMS_UPDATE_FILE_NAME).exists())
assertEquals(server.networkParameters, parameters) assertEquals(server.networkParameters, parameters)
// Parameters from update should be moved to `network-parameters` file. // Parameters from update should be moved to `network-parameters` file.
val parametersFromFile = (baseDirectory / NETWORK_PARAMS_FILE_NAME) val parametersFromFile = (networkParamsPath / NETWORK_PARAMS_FILE_NAME)
.readObject<SignedNetworkParameters>()
.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
assertEquals(server.networkParameters, parametersFromFile)
}
@Test(timeout=300_000)
fun `read correct set of parameters from specified network parameters path`() {
val networkParamsPath = fs.getPath("/node/network").createDirectories()
val oldParameters = testNetworkParameters(epoch = 1)
NetworkParametersCopier(oldParameters).install(networkParamsPath)
NetworkParametersCopier(server.networkParameters, update = true).install(networkParamsPath) // Parameters update file.
val parameters = NetworkParametersReader(DEV_ROOT_CA.certificate, networkMapClient, networkParamsPath).read().networkParameters
assertFalse((networkParamsPath / NETWORK_PARAMS_UPDATE_FILE_NAME).exists())
assertEquals(server.networkParameters, parameters)
// Parameters from update should be moved to `network-parameters` file.
val parametersFromFile = (networkParamsPath / NETWORK_PARAMS_FILE_NAME)
.readObject<SignedNetworkParameters>() .readObject<SignedNetworkParameters>()
.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate) .verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
assertEquals(server.networkParameters, parametersFromFile) assertEquals(server.networkParameters, parametersFromFile)
@ -76,10 +92,10 @@ class NetworkParametersReaderTest {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `read network parameters from file when network map server is down`() { fun `read network parameters from file when network map server is down`() {
server.close() server.close()
val baseDirectory = fs.getPath("/node").createDirectories() val networkParamsPath = fs.getPath("/node").createDirectories()
val fileParameters = testNetworkParameters(epoch = 1) val fileParameters = testNetworkParameters(epoch = 1)
NetworkParametersCopier(fileParameters).install(baseDirectory) NetworkParametersCopier(fileParameters).install(networkParamsPath)
val parameters = NetworkParametersReader(DEV_ROOT_CA.certificate, networkMapClient, baseDirectory).read().networkParameters val parameters = NetworkParametersReader(DEV_ROOT_CA.certificate, networkMapClient, networkParamsPath).read().networkParameters
assertThat(parameters).isEqualTo(fileParameters) assertThat(parameters).isEqualTo(fileParameters)
} }

View File

@ -479,6 +479,7 @@ open class InternalMockNetwork(cordappPackages: List<String> = emptyList(),
certificatesDirectory.createDirectories() certificatesDirectory.createDirectories()
val config = mockNodeConfiguration(certificatesDirectory).also { val config = mockNodeConfiguration(certificatesDirectory).also {
doReturn(baseDirectory).whenever(it).baseDirectory doReturn(baseDirectory).whenever(it).baseDirectory
doReturn(baseDirectory).whenever(it).networkParametersPath
doReturn(parameters.legalName ?: CordaX500Name("Mock Company $id", "London", "GB")).whenever(it).myLegalName doReturn(parameters.legalName ?: CordaX500Name("Mock Company $id", "London", "GB")).whenever(it).myLegalName
doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties
doReturn(emptyList<SecureHash>()).whenever(it).extraNetworkMapKeys doReturn(emptyList<SecureHash>()).whenever(it).extraNetworkMapKeys