[EG-2225] Prevent extra directories being created when relative base directories are specified (#6282)

Don't create an extra directory if a relative base path specified
This commit is contained in:
James Higgs 2020-06-02 15:26:40 +01:00 committed by GitHub
parent ac9f6fca16
commit 04ddb267fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 27 deletions

View File

@ -77,7 +77,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
val messagingServerExternal = config[messagingServerExternal] ?: Defaults.messagingServerExternal(config[messagingServerAddress]) val messagingServerExternal = config[messagingServerExternal] ?: Defaults.messagingServerExternal(config[messagingServerAddress])
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] ?: Defaults.cordappsDirectories(baseDirectoryPath) val cordappDirectories = config[cordappDirectories]?.map { baseDirectoryPath.resolve(it) } ?: Defaults.cordappsDirectories(baseDirectoryPath)
val result = try { val result = try {
valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl( valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl(
baseDirectory = baseDirectoryPath, baseDirectory = baseDirectoryPath,
@ -127,7 +127,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
attachmentContentCacheSizeMegaBytes = config[attachmentContentCacheSizeMegaBytes], attachmentContentCacheSizeMegaBytes = config[attachmentContentCacheSizeMegaBytes],
h2port = config[h2port], h2port = config[h2port],
jarDirs = config[jarDirs], jarDirs = config[jarDirs],
cordappDirectories = cordappDirectories.map { baseDirectoryPath.resolve(it) }, cordappDirectories = cordappDirectories,
cordappSignerKeyFingerprintBlacklist = config[cordappSignerKeyFingerprintBlacklist], cordappSignerKeyFingerprintBlacklist = config[cordappSignerKeyFingerprintBlacklist],
blacklistedAttachmentSigningKeys = config[blacklistedAttachmentSigningKeys], blacklistedAttachmentSigningKeys = config[blacklistedAttachmentSigningKeys],
networkParameterAcceptanceSettings = config[networkParameterAcceptanceSettings], networkParameterAcceptanceSettings = config[networkParameterAcceptanceSettings],

View File

@ -21,6 +21,7 @@ import org.junit.Assert.assertNotNull
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.TemporaryFolder import org.junit.rules.TemporaryFolder
import java.io.File
import java.net.URI import java.net.URI
import java.net.URL import java.net.URL
import java.nio.file.Paths import java.nio.file.Paths
@ -34,7 +35,7 @@ class NodeConfigurationImplTest {
@JvmField @JvmField
val tempFolder = TemporaryFolder() val tempFolder = TemporaryFolder()
@Test(timeout=300_000) @Test(timeout=3_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)
@ -43,7 +44,7 @@ class NodeConfigurationImplTest {
configDebugOptions(false, null) configDebugOptions(false, null)
} }
@Test(timeout=300_000) @Test(timeout=3_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() }
@ -51,7 +52,7 @@ class NodeConfigurationImplTest {
assertThat(configValidationResult.first()).contains("tlsCertCrlIssuer") assertThat(configValidationResult.first()).contains("tlsCertCrlIssuer")
} }
@Test(timeout=300_000) @Test(timeout=3_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() }
@ -59,7 +60,7 @@ class NodeConfigurationImplTest {
assertThat(configValidationResult.first()).contains("crlCheckSoftFail") assertThat(configValidationResult.first()).contains("crlCheckSoftFail")
} }
@Test(timeout=300_000) @Test(timeout=3_000)
fun `check devModeOptions flag helper`() { fun `check devModeOptions flag helper`() {
assertTrue { configDebugOptions(true, null).shouldCheckCheckpoints() } assertTrue { configDebugOptions(true, null).shouldCheckCheckpoints() }
assertTrue { configDebugOptions(true, DevModeOptions()).shouldCheckCheckpoints() } assertTrue { configDebugOptions(true, DevModeOptions()).shouldCheckCheckpoints() }
@ -67,7 +68,7 @@ class NodeConfigurationImplTest {
assertFalse { configDebugOptions(true, DevModeOptions(true)).shouldCheckCheckpoints() } assertFalse { configDebugOptions(true, DevModeOptions(true)).shouldCheckCheckpoints() }
} }
@Test(timeout=300_000) @Test(timeout=3_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() }
@ -79,7 +80,7 @@ class NodeConfigurationImplTest {
assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() } assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() }
} }
@Test(timeout=300_000) @Test(timeout=3_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")
@ -102,20 +103,20 @@ class NodeConfigurationImplTest {
System.setProperty("os.name", os) System.setProperty("os.name", os)
} }
@Test(timeout=300_000) @Test(timeout=3_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=300_000) @Test(timeout=3_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=300_000) @Test(timeout=3_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"))
@ -131,7 +132,7 @@ class NodeConfigurationImplTest {
) )
} }
@Test(timeout=300_000) @Test(timeout=3_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,
@ -142,7 +143,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=300_000) @Test(timeout=3_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,
@ -153,7 +154,7 @@ class NodeConfigurationImplTest {
assertThat(errors).isEmpty() assertThat(errors).isEmpty()
} }
@Test(timeout=300_000) @Test(timeout=3_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)) var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
val missingPropertyPath = "rpcSettings.address" val missingPropertyPath = "rpcSettings.address"
@ -165,7 +166,7 @@ class NodeConfigurationImplTest {
} }
} }
@Test(timeout=300_000) @Test(timeout=3_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"),
@ -176,7 +177,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=300_000) @Test(timeout=3_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,
@ -192,7 +193,7 @@ class NodeConfigurationImplTest {
} }
} }
@Test(timeout=300_000) @Test(timeout=3_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 rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
rawConfig = rawConfig.withoutPath("rpcSettings.address") rawConfig = rawConfig.withoutPath("rpcSettings.address")
@ -201,8 +202,8 @@ class NodeConfigurationImplTest {
assertThat(rawConfig.parseAsNodeConfiguration().isValid).isTrue() assertThat(rawConfig.parseAsNodeConfiguration().isValid).isTrue()
} }
@Test(timeout=300_000) @Test(timeout=3_000)
fun `relative path correctly parsed`() { fun `absolute base directory leads to correct cordapp directories`() {
val rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false)) 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
@ -213,13 +214,69 @@ class NodeConfigurationImplTest {
.resolve() .resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration() val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
assertThat(nodeConfiguration.isValid).isTrue() assertTrue(nodeConfiguration.isValid)
val baseDirPath = tempFolder.root.toPath() val baseDirPath = tempFolder.root.toPath()
assertEquals(listOf(baseDirPath / "./myCorDapps1", baseDirPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories) assertEquals(listOf(baseDirPath / "./myCorDapps1", baseDirPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories)
} }
@Test(timeout=300_000) @Test(timeout=3_000)
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
val finalConfig = configOf(
// Add substitution values here
"baseDirectory" to tempFolder.root.canonicalPath)
.withFallback(rawConfig)
.resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
assertTrue(nodeConfiguration.isValid)
val baseDirPath = tempFolder.root.toPath()
assertEquals(listOf(baseDirPath / "cordapps"), nodeConfiguration.value().cordappDirectories)
}
@Test(timeout=3_000)
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 fullPath = File(".").resolve(path).toString()
// Override base directory to have predictable experience on diff OSes
val finalConfig = configOf(
// Add substitution values here
"baseDirectory" to fullPath)
.withFallback(rawConfig)
.resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
assertTrue(nodeConfiguration.isValid)
assertEquals(listOf(fullPath / "./myCorDapps1", fullPath / "./myCorDapps2"), nodeConfiguration.value().cordappDirectories)
}
@Test(timeout=3_000)
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 fullPath = File(".").resolve(path).toString()
// Override base directory to have predictable experience on diff OSes
val finalConfig = configOf(
// Add substitution values here
"baseDirectory" to fullPath)
.withFallback(rawConfig)
.resolve()
val nodeConfiguration = finalConfig.parseAsNodeConfiguration()
assertTrue(nodeConfiguration.isValid)
assertEquals(listOf(fullPath / "cordapps"), nodeConfiguration.value().cordappDirectories)
}
@Test(timeout=3_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)) var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
rawConfig = rawConfig.withoutPath("rpcSettings.adminAddress") rawConfig = rawConfig.withoutPath("rpcSettings.adminAddress")
@ -229,7 +286,7 @@ class NodeConfigurationImplTest {
assertThat(config.errors.asSequence().map(Configuration.Validation.Error::message).filter { it.contains("rpcSettings.adminAddress") }.toList()).isNotEmpty assertThat(config.errors.asSequence().map(Configuration.Validation.Error::message).filter { it.contains("rpcSettings.adminAddress") }.toList()).isNotEmpty
} }
@Test(timeout=300_000) @Test(timeout=3_000)
fun `compatibilityZoneURL populates NetworkServices`() { fun `compatibilityZoneURL populates NetworkServices`() {
val compatibilityZoneURL = URI.create("https://r3.com").toURL() val compatibilityZoneURL = URI.create("https://r3.com").toURL()
val configuration = testConfiguration.copy( val configuration = testConfiguration.copy(
@ -241,14 +298,14 @@ class NodeConfigurationImplTest {
assertEquals(compatibilityZoneURL, configuration.networkServices!!.networkMapURL) assertEquals(compatibilityZoneURL, configuration.networkServices!!.networkMapURL)
} }
@Test(timeout=300_000) @Test(timeout=3_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=300_000) @Test(timeout=3_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"))
@ -256,7 +313,7 @@ class NodeConfigurationImplTest {
assertEquals(JmxReporterType.NEW_RELIC.toString(), nodeConfig.jmxReporterType.toString()) assertEquals(JmxReporterType.NEW_RELIC.toString(), nodeConfig.jmxReporterType.toString())
} }
@Test(timeout=300_000) @Test(timeout=3_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"))
@ -264,7 +321,7 @@ class NodeConfigurationImplTest {
assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString()) assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString())
} }
@Test(timeout=300_000) @Test(timeout=3_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()
@ -276,7 +333,7 @@ class NodeConfigurationImplTest {
} }
} }
@Test(timeout=300_000) @Test(timeout=3_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)))

View File

@ -0,0 +1,31 @@
myLegalName = "O=Alice Corp, L=Madrid, C=ES"
emailAddress = "admin@company.com"
keyStorePassword = "cordacadevpass"
trustStorePassword = "trustpass"
crlCheckSoftFail = true
baseDirectory = "/opt/corda"
dataSourceProperties = {
dataSourceClassName = org.h2.jdbcx.JdbcDataSource
dataSource.url = "jdbc:h2:file:blah"
dataSource.user = "sa"
dataSource.password = ""
}
database = {
transactionIsolationLevel = "REPEATABLE_READ"
exportHibernateJMXStatistics = "false"
}
p2pAddress = "localhost:2233"
h2port = 0
useTestClock = false
verifierType = InMemory
rpcSettings = {
address = "locahost:3418"
adminAddress = "localhost:3419"
useSsl = false
standAloneBroker = false
}
flowTimeout {
timeout = 30 seconds
maxRestartCount = 3
backoffBase = 2.0
}