CORDA-2491: Ability to specify Java package namespace from Cordform (#5075)

Add entry point with generic extra configuration options. Move configuration verification code to avoid circular dependencies.
This commit is contained in:
rui-r3 2019-05-09 17:25:21 +01:00 committed by Shams Asari
parent f0c75448b4
commit 9e3a0a64ac
5 changed files with 55 additions and 12 deletions

View File

@ -14,6 +14,9 @@ Version 4.2
of a contract without having to manually install that version, provided a newer version is installed. Similarly, non-contract attachments of a contract without having to manually install that version, provided a newer version is installed. Similarly, non-contract attachments
are whitelisted if another attachment is present on the node that is signed by the same public key. are whitelisted if another attachment is present on the node that is signed by the same public key.
* :doc:`design/data-model-upgrades/package-namespace-ownership` configurations can be now be set as described in
:ref:`node_package_namespace_ownership`, when using the Cordformation plugin version 4.0.43.
.. _changelog_v4.0: .. _changelog_v4.0:
Version 4.0 Version 4.0

View File

@ -143,6 +143,29 @@ To copy the same file to all nodes `ext.drivers` can be defined in the top level
} }
} }
.. _node_package_namespace_ownership:
Package namespace ownership
^^^^^^^^^^^^^^^^^^^^^^^^^^^
To specify :doc:`design/data-model-upgrades/package-namespace-ownership` configuration, the optional ``networkParameterOverrides`` and ``packageOwnership`` blocks can be used, similar to the configuration file used in :doc:`network-bootstrapper`:
.. sourcecode:: groovy
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
[...]
networkParameterOverrides {
packageOwnership {
"com.mypackagename" {
keystore = "_teststore"
keystorePassword = "MyStorePassword"
keystoreAlias = "MyKeyAlias"
}
}
}
[...]
}
Signing Cordapp JARs Signing Cordapp JARs
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
The default behaviour of Cordform is to deploy CorDapp JARs "as built": The default behaviour of Cordform is to deploy CorDapp JARs "as built":

View File

@ -8,6 +8,7 @@ description 'Corda node API'
dependencies { dependencies {
compile project(":core") compile project(":core")
compile project(":serialization") // TODO Remove this once the NetworkBootstrapper class is moved into the tools:bootstrapper module compile project(":serialization") // TODO Remove this once the NetworkBootstrapper class is moved into the tools:bootstrapper module
compile project(':common-configuration-parsing') // TODO Remove this dependency once NetworkBootsrapper is moved into tools:bootstrapper
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

View File

@ -3,6 +3,7 @@ package net.corda.nodeapi.internal.network
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigException import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.* import net.corda.core.internal.*
@ -198,6 +199,23 @@ internal constructor(private val initSerEnv: Boolean,
bootstrap(directory, cordappJars, CopyCordapps.No, fromCordform = true) bootstrap(directory, cordappJars, CopyCordapps.No, fromCordform = true)
} }
/**
* Entry point for Cordform with extra configurations
* @param directory - directory on which the network will be deployed
* @param cordappJars - List of CordApps to deploy
* @param extraConfigurations - HOCON representation of extra configuration parameters
*/
fun bootstrapCordform(directory: Path, cordappJars: List<Path>, extraConfigurations: String) {
val configuration = ConfigFactory.parseString(extraConfigurations).resolve().getObject("networkParameterOverrides").toConfig().parseAsNetworkParametersConfiguration()
val networkParametersOverrides = configuration.doOnErrors(::reportErrors).optional ?: throw IllegalStateException("Invalid configuration passed.")
bootstrap(directory, cordappJars, CopyCordapps.No, fromCordform = true, networkParametersOverrides = networkParametersOverrides)
}
private fun reportErrors(errors: Set<Configuration.Validation.Error>) {
System.err.println("Error(s) found parsing the networkParameterOverrides:")
errors.forEach { System.err.println("Error parsing ${it.pathAsString}: ${it.message}") }
}
/** Entry point for the tool */ /** Entry point for the tool */
override fun bootstrap(directory: Path, copyCordapps: CopyCordapps, networkParameterOverrides: NetworkParametersOverrides) { override fun bootstrap(directory: Path, copyCordapps: CopyCordapps, networkParameterOverrides: NetworkParametersOverrides) {
require(networkParameterOverrides.minimumPlatformVersion == null || networkParameterOverrides.minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" } require(networkParameterOverrides.minimumPlatformVersion == null || networkParameterOverrides.minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" }

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper package net.corda.nodeapi.internal.network
import com.typesafe.config.Config import com.typesafe.config.Config
import net.corda.common.configuration.parsing.internal.Configuration import net.corda.common.configuration.parsing.internal.Configuration
@ -9,15 +9,13 @@ import net.corda.common.validation.internal.Validated
import net.corda.core.internal.noPackageOverlap import net.corda.core.internal.noPackageOverlap
import net.corda.core.internal.requirePackageValid import net.corda.core.internal.requirePackageValid
import net.corda.nodeapi.internal.crypto.loadKeyStore import net.corda.nodeapi.internal.crypto.loadKeyStore
import net.corda.nodeapi.internal.network.NetworkParametersOverrides
import net.corda.nodeapi.internal.network.PackageOwner
import java.io.IOException import java.io.IOException
import java.nio.file.InvalidPathException import java.nio.file.InvalidPathException
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.security.KeyStoreException import java.security.KeyStoreException
internal typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error> typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error>
fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = false)): fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = false)):
Valid<NetworkParametersOverrides> = NetworkParameterOverridesSpec.parse(this, options) Valid<NetworkParametersOverrides> = NetworkParameterOverridesSpec.parse(this, options)
@ -26,15 +24,15 @@ internal fun <T> badValue(msg: String): Valid<T> = Validated.invalid(sequenceOf(
internal fun <T> valid(value: T): Valid<T> = Validated.valid(value) internal fun <T> valid(value: T): Valid<T> = Validated.valid(value)
internal object NetworkParameterOverridesSpec : Configuration.Specification<NetworkParametersOverrides>("DefaultNetworkParameters") { internal object NetworkParameterOverridesSpec : Configuration.Specification<NetworkParametersOverrides>("DefaultNetworkParameters") {
private val minimumPlatformVersion by int().mapValid(::parsePositiveInteger).optional() private val minimumPlatformVersion by int().mapValid(NetworkParameterOverridesSpec::parsePositiveInteger).optional()
private val maxMessageSize by int().mapValid(::parsePositiveInteger).optional() private val maxMessageSize by int().mapValid(NetworkParameterOverridesSpec::parsePositiveInteger).optional()
private val maxTransactionSize by int().mapValid(::parsePositiveInteger).optional() private val maxTransactionSize by int().mapValid(NetworkParameterOverridesSpec::parsePositiveInteger).optional()
private val packageOwnership by nested(PackageOwnershipSpec).list().optional() private val packageOwnership by nested(PackageOwnershipSpec).list().optional()
private val eventHorizon by duration().optional() private val eventHorizon by duration().optional()
internal object PackageOwnershipSpec : Configuration.Specification<PackageOwner>("PackageOwners") { internal object PackageOwnershipSpec : Configuration.Specification<PackageOwner>("PackageOwners") {
private val packageName by string().mapValid(::toPackageName) private val packageName by string().mapValid(PackageOwnershipSpec::toPackageName)
private val keystore by string().mapValid(::toPath) private val keystore by string().mapValid(PackageOwnershipSpec::toPath)
private val keystorePassword by string() private val keystorePassword by string()
private val keystoreAlias by string() private val keystoreAlias by string()
@ -54,12 +52,12 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
val publicKey = ks.getCertificate(configuration[keystoreAlias]).publicKey val publicKey = ks.getCertificate(configuration[keystoreAlias]).publicKey
valid(PackageOwner(javaPackageName, publicKey)) valid(PackageOwner(javaPackageName, publicKey))
} catch (kse: KeyStoreException) { } catch (kse: KeyStoreException) {
badValue("Keystore has not been initialized for alias ${configuration[keystoreAlias]}") badValue("Keystore has not been initialized for alias ${configuration[keystoreAlias]}.")
} }
} catch (kse: KeyStoreException) { } catch (kse: KeyStoreException) {
badValue("Password is incorrect or the key store is damaged for keyStoreFilePath: $suppliedKeystorePath and keyStorePassword: $keystorePassword") badValue("Password is incorrect or the key store is damaged for keyStoreFilePath: $suppliedKeystorePath.")
} catch (e: IOException) { } catch (e: IOException) {
badValue("Error reading the key store from the file for keyStoreFilePath: $suppliedKeystorePath and keyStorePassword: $keystorePassword ${e.message}") badValue("Error reading the key store from the file for keyStoreFilePath: $suppliedKeystorePath ${e.message}.")
} }
} }