mirror of
https://github.com/corda/corda.git
synced 2025-03-19 18:45:28 +00:00
Corda Behave framework updates to decouple from Network Services (#914)
* Added new 'eventHorizonDays' configuration item. * Added custom authenticator to provide ARTIFACTORY credentials upon resolving protected internal URL. * Re-pointed functional test scenarios to point to Enterprise master. * Enterprise corda network scenarios to use NetworkBootstrapper tool (instead of Doorman/NMS) since decision made by Product Management to split out Doorman/NMS from Enterprise. * Configuration parameter changed to 'runMigration' since DP3. * Fixed problem with logger upon startup. * General improvements and additions to setup and execution scripts (eg. SIMM valuation demo now consists of 3 separate jars) * Updates to decouple from Network Services. * Download all JARs from artifactory for a given published distribution. * Add TODOs for Doorman/NMS rework. * Addressing TL PR review comments. * Additional instructions for setting up the environment and running QA tests. * Fixed repository URL references.
This commit is contained in:
parent
4de4e8a3ef
commit
c2f22e18a5
@ -55,4 +55,35 @@ the following parameter to the Gradle command:
|
||||
$ ../../gradlew scenario -Ptags="@cash"
|
||||
# or
|
||||
$ ../../gradlew scenario -Ptags="@cash,@logging"
|
||||
```
|
||||
```
|
||||
|
||||
# Environment variables and system properties
|
||||
|
||||
The following environment variables must be set to enable access to the internal R3 Artifactory repository hosting Enterprise distributions:
|
||||
https://ci-artifactory.corda.r3cev.com/artifactory/r3-corda-releases
|
||||
|
||||
```bash
|
||||
CORDA_ARTIFACTORY_USERNAME
|
||||
CORDA_ARTIFACTORY_PASSWORD
|
||||
```
|
||||
|
||||
The following system properties may be passed to the Cucumber and ScenarioRunner run-time processes:
|
||||
|
||||
* `STAGING_ROOT` to specify the filesystem location of the Corda distributions to be used (as setup by the prepare.sh script)
|
||||
|
||||
```bash
|
||||
e.g. -DSTAGING_ROOT=$HOME/staging
|
||||
```
|
||||
|
||||
* `USE_NETWORK_SERVICES` specifies to use the Doorman/NMS service to perform setup of an Enterprise network.
|
||||
By default both OS and Enterprise scenarios will use the [Network Bootstrapper utility](https://docs.corda.net/head/setting-up-a-corda-network.html#bootstrapping-the-network) to create a Corda network.
|
||||
|
||||
```bash
|
||||
e.g. -DUSE_NETWORK_SERVICES
|
||||
```
|
||||
|
||||
* `DISABLE_CLEANUP` to prevent clean-up of runtime directories after successfully running tests.
|
||||
|
||||
```bash
|
||||
e.g. -DDISABLE_CLEANUP
|
||||
```
|
||||
|
@ -7,13 +7,21 @@ set -x
|
||||
# corda-master => git clone https://github.com/corda/corda
|
||||
# r3corda-master => git clone https://github.com/corda/enterprise
|
||||
VERSION=r3corda-master
|
||||
STAGING_DIR=~/staging
|
||||
|
||||
STAGING_DIR="${STAGING_ROOT:-$TMPDIR/staging}"
|
||||
echo "Staging directory: $STAGING_DIR"
|
||||
|
||||
CORDA_DIR=${STAGING_DIR}/corda/${VERSION}
|
||||
echo "Corda staging directory: $CORDA_DIR"
|
||||
|
||||
CORDAPP_DIR=${CORDA_DIR}/apps
|
||||
echo "CorDapp staging directory: $CORDAPP_DIR"
|
||||
|
||||
DRIVERS_DIR=${STAGING_DIR}/drivers
|
||||
echo "Drivers staging directory: $DRIVERS_DIR"
|
||||
|
||||
# Set up directories
|
||||
mkdir -p ${STAGING_DIR}
|
||||
mkdir -p ${STAGING_DIR} || { echo "Unable to create directory $STAGING_DIR"; exit; }
|
||||
mkdir -p ${CORDA_DIR}
|
||||
mkdir -p ${CORDAPP_DIR}
|
||||
mkdir -p ${DRIVERS_DIR}
|
||||
@ -27,8 +35,14 @@ cp -v $(ls node/capsule/build/libs/corda-*.jar | tail -n1) ${CORDA_DIR}/corda.ja
|
||||
cp -v $(ls finance/build/libs/corda-finance-*.jar | tail -n1) ${CORDAPP_DIR}
|
||||
|
||||
# Copy sample Cordapps
|
||||
|
||||
# SIMM valuation demo
|
||||
./gradlew samples:simm-valuation-demo:jar
|
||||
cp -v $(ls samples/simm-valuation-demo/build/libs/simm-valuation-demo-*.jar | tail -n1) ${CORDAPP_DIR}
|
||||
./gradlew samples:simm-valuation-demo:contracts-states:jar
|
||||
cp -v $(ls samples/simm-valuation-demo/contracts-states/build/libs/contracts-states-*.jar | tail -n1) ${CORDAPP_DIR}
|
||||
./gradlew samples:simm-valuation-demo:flows:jar
|
||||
cp -v $(ls samples/simm-valuation-demo/flows/build/libs/flows-*.jar | tail -n1) ${CORDAPP_DIR}
|
||||
|
||||
# Download database drivers
|
||||
curl "https://search.maven.org/remotecontent?filepath=com/h2database/h2/1.4.196/h2-1.4.196.jar" > ${DRIVERS_DIR}/h2-1.4.196.jar
|
||||
@ -39,11 +53,17 @@ curl -L "https://github.com/Microsoft/mssql-jdbc/releases/download/v6.2.2/mssql-
|
||||
./gradlew buildBootstrapperJar
|
||||
cp -v $(ls tools/bootstrapper/build/libs/*.jar | tail -n1) ${CORDA_DIR}/network-bootstrapper.jar
|
||||
|
||||
# build and distribute Doorman/NMS
|
||||
./gradlew network-management:capsule:buildDoormanJAR
|
||||
cp -v $(ls network-management/capsule/build/libs/doorman-*.jar | tail -n1) ${CORDA_DIR}/doorman.jar
|
||||
# TODO: resolve Doorman/NMS artifacts from new artifactory location.
|
||||
# Doorman/NMS has moved to a separate repo: https://github.com/corda/network-services,
|
||||
# now follows a different release cycle (and versioning scheme), and is published to a new artifactory location:
|
||||
# https://ci-artifactory.corda.r3cev.com/artifactory/r3-corda-releases/com/r3/corda/networkservices/doorman/
|
||||
|
||||
# build and distribute DB Migration tool
|
||||
./gradlew tools:dbmigration:shadowJar
|
||||
cp -v $(ls tools/dbmigration/build/libs/*migration-*.jar | tail -n1) ${CORDA_DIR}/dbmigration.jar
|
||||
|
||||
# Build rpcProxy (required by CTS Scenario Driver to call Corda 3.0 which continues to use Kryo for RPC)
|
||||
./gradlew testing:qa:behave:tools:rpc-proxy:rpcProxyJar
|
||||
cp -v $(ls testing/qa/behave/tools/rpc-proxy/build/libs/corda-rpcProxy*.jar | tail -n1) ${CORDA_DIR}/corda-rpcProxy.jar
|
||||
cp -v testing/qa/behave/tools/rpc-proxy/startRPCproxy.sh ${CORDA_DIR}
|
||||
|
||||
|
@ -28,7 +28,7 @@ class SqlServerConfigurationTemplate : DatabaseConfigurationTemplate() {
|
||||
| dataSource.password = "${it.password}"
|
||||
|}
|
||||
|database = {
|
||||
| initialiseSchema=true
|
||||
| runMigration=true
|
||||
| transactionIsolationLevel = READ_COMMITTED
|
||||
| schema="${it.schema}"
|
||||
|}
|
||||
|
@ -108,10 +108,11 @@ class Network private constructor(
|
||||
throw CordaException("Unable to configure nodes in Corda network. Please check logs in $directory")
|
||||
}
|
||||
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE)
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null)
|
||||
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
|
||||
network.bootstrapDoorman()
|
||||
else
|
||||
network.bootstrapLocalNetwork()
|
||||
network.bootstrapLocalNetwork(networkType)
|
||||
return network
|
||||
}
|
||||
}
|
||||
@ -147,6 +148,10 @@ class Network private constructor(
|
||||
*/
|
||||
private fun bootstrapDoorman() {
|
||||
|
||||
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
|
||||
signalFailure("Bootstrapping a Corda Enterprise network using the Doorman is no longer supported; exiting ...")
|
||||
return
|
||||
|
||||
// WARNING!! Need to use the correct bootstrapper
|
||||
// only if using OS nodes (need to choose the latest version)
|
||||
val r3node = nodes.values
|
||||
@ -158,21 +163,25 @@ class Network private constructor(
|
||||
val doormanTargetDirectory = targetDirectory / "doorman"
|
||||
source.toFile().copyRecursively(doormanTargetDirectory.toFile(), true)
|
||||
|
||||
// Use master version of Bootstrapper
|
||||
val doormanJar = Distribution.R3_MASTER.doormanJar
|
||||
log.info("DoormanJar URL: $doormanJar\n")
|
||||
|
||||
// 1. Create key stores for local signer
|
||||
|
||||
// java -jar doorman-<version>.jar --mode ROOT_KEYGEN
|
||||
log.info("Doorman target directory: $doormanTargetDirectory")
|
||||
runCommand(JarCommand(distribution.doormanJar,
|
||||
runCommand(JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "ROOT_KEYGEN", "--trust-store-password", "password"),
|
||||
doormanTargetDirectory, timeout))
|
||||
|
||||
// java -jar doorman-<version>.jar --mode CA_KEYGEN
|
||||
runCommand(JarCommand(distribution.doormanJar,
|
||||
runCommand(JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "CA_KEYGEN"),
|
||||
doormanTargetDirectory, timeout))
|
||||
|
||||
// 2. Start the doorman service for notary registration
|
||||
doormanNMS = JarCommand(distribution.doormanJar,
|
||||
doormanNMS = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf"),
|
||||
doormanTargetDirectory, timeout)
|
||||
|
||||
@ -216,13 +225,13 @@ class Network private constructor(
|
||||
|
||||
// 6. Load initial network parameters file for network map service
|
||||
val networkParamsConfig = if (notaryNodes.isEmpty()) "network-parameters-without-notary.conf" else "network-parameters.conf"
|
||||
val updateNetworkParams = JarCommand(distribution.doormanJar,
|
||||
val updateNetworkParams = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanTargetDirectory/node.conf", "--set-network-parameters", "$doormanTargetDirectory/$networkParamsConfig"),
|
||||
doormanTargetDirectory, timeout)
|
||||
runCommand(updateNetworkParams)
|
||||
|
||||
// 7. Start a fully configured Doorman / NMS
|
||||
doormanNMS = JarCommand(distribution.doormanJar,
|
||||
doormanNMS = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node.conf"),
|
||||
doormanTargetDirectory, timeout)
|
||||
|
||||
@ -283,12 +292,14 @@ class Network private constructor(
|
||||
return command
|
||||
}
|
||||
|
||||
private fun bootstrapLocalNetwork() {
|
||||
val bootstrapper = nodes.values
|
||||
.filter { it.config.distribution.type != Distribution.Type.CORDA_ENTERPRISE }
|
||||
.sortedByDescending { it.config.distribution.version }
|
||||
.first()
|
||||
.config.distribution.networkBootstrapper
|
||||
private fun bootstrapLocalNetwork(networkType: Distribution.Type) {
|
||||
// Use master version of Bootstrapper
|
||||
val bootstrapper =
|
||||
when (networkType) {
|
||||
Distribution.Type.CORDA_OS -> Distribution.MASTER.networkBootstrapper
|
||||
Distribution.Type.CORDA_ENTERPRISE -> Distribution.R3_MASTER.networkBootstrapper
|
||||
}
|
||||
log.info("Bootstrapper URL: $bootstrapper\n")
|
||||
|
||||
if (!bootstrapper.exists()) {
|
||||
signalFailure("Network bootstrapping tool does not exist; exiting ...")
|
||||
@ -320,7 +331,7 @@ class Network private constructor(
|
||||
runCommand(rpcProxyCommand)
|
||||
}
|
||||
else {
|
||||
log.warn("Missing RPC proxy startup script. Continuing ...")
|
||||
log.warn("Missing RPC proxy startup script ($startProxyScript). Continuing ...")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,13 @@ import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.exists
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import java.io.IOException
|
||||
import java.net.Authenticator
|
||||
import java.net.PasswordAuthentication
|
||||
import java.net.URL
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
|
||||
/**
|
||||
* Corda distribution.
|
||||
@ -41,9 +46,9 @@ class Distribution private constructor(
|
||||
file: Path? = null,
|
||||
|
||||
/**
|
||||
* The URL of the distribution fat JAR, if available.
|
||||
* Map of all distribution JAR artifacts from artifactory, if available.
|
||||
*/
|
||||
val url: URL? = null,
|
||||
val artifactUrlMap: Map<String,URL>? = null,
|
||||
|
||||
/**
|
||||
* The Docker image details, if available
|
||||
@ -86,10 +91,22 @@ class Distribution private constructor(
|
||||
*/
|
||||
fun ensureAvailable() {
|
||||
if (cordaJar.exists()) return
|
||||
val url = checkNotNull(url) { "File not found $cordaJar" }
|
||||
try {
|
||||
cordaJar.parent.createDirectories()
|
||||
url.openStream().use { it.copyTo(cordaJar) }
|
||||
path.createDirectories()
|
||||
cordappDirectory.createDirectories()
|
||||
Authenticator.setDefault(object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(System.getenv("CORDA_ARTIFACTORY_USERNAME"), System.getenv("CORDA_ARTIFACTORY_PASSWORD").toCharArray())
|
||||
}
|
||||
})
|
||||
artifactUrlMap!!.forEach { artifactName, artifactUrl ->
|
||||
artifactUrl.openStream().use {
|
||||
if (artifactName.startsWith("corda-finance")) {
|
||||
it.copyTo(cordappDirectory / "$artifactName.jar", StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
else it.copyTo(path / "$artifactName.jar", StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if ("HTTP response code: 401" in e.message!!) {
|
||||
log.warn("CORDA_ARTIFACTORY_USERNAME ${System.getenv("CORDA_ARTIFACTORY_USERNAME")}")
|
||||
@ -105,9 +122,11 @@ class Distribution private constructor(
|
||||
*/
|
||||
override fun toString() = "Corda(version = $version, path = $cordaJar)"
|
||||
|
||||
enum class Type {
|
||||
CORDA_OS,
|
||||
CORDA_ENTERPRISE
|
||||
enum class Type(val artifacts: Set<String>) {
|
||||
CORDA_OS(setOf("corda", "corda-webserver", "corda-finance")),
|
||||
// bridge-server not available in Enterprise Dev Previews
|
||||
// migration-tool not published in Enterprise Dev Previews
|
||||
CORDA_ENTERPRISE(setOf("corda", "corda-webserver", "corda-finance", "corda-bridgeserver", "migration-tool"))
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -122,22 +141,43 @@ class Distribution private constructor(
|
||||
val R3_MASTER = fromJarFile(Type.CORDA_ENTERPRISE, "r3corda-master")
|
||||
|
||||
/**
|
||||
* Get representation of a Corda distribution from Artifactory based on its version string.
|
||||
* Get all jar artifacts from Artifactory for a given distribution and version of Corda.
|
||||
* @param type The Corda distribution type.
|
||||
* @param version The version of the Corda distribution.
|
||||
*/
|
||||
fun fromArtifactory(type: Type, version: String): Distribution {
|
||||
val url =
|
||||
when (type) {
|
||||
Type.CORDA_OS -> URL("https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases/net/corda/corda/$version/corda-$version.jar")
|
||||
Type.CORDA_ENTERPRISE -> URL("https://ci-artifactory.corda.r3cev.com/artifactory/r3-corda-releases/com/r3/corda/corda/$version/corda-$version.jar")
|
||||
val artifactUrlMap = when (type) {
|
||||
Type.CORDA_OS -> resolveArtifacts(Type.CORDA_OS.artifacts, version, "https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases/net/corda")
|
||||
Type.CORDA_ENTERPRISE -> {
|
||||
Authenticator.setDefault(object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(System.getenv("CORDA_ARTIFACTORY_USERNAME"), System.getenv("CORDA_ARTIFACTORY_PASSWORD").toCharArray())
|
||||
}
|
||||
})
|
||||
resolveArtifacts(Type.CORDA_ENTERPRISE.artifacts, version, "https://ci-artifactory.corda.r3cev.com/artifactory/r3-corda-releases/com/r3/corda")
|
||||
}
|
||||
log.info("Artifactory URL: $url\n")
|
||||
val distribution = Distribution(type, version, url = url)
|
||||
}
|
||||
val distribution = Distribution(type, version, artifactUrlMap = artifactUrlMap)
|
||||
distributions.add(distribution)
|
||||
return distribution
|
||||
}
|
||||
|
||||
private fun resolveArtifacts(artifacts: Set<String>, version: String, artifactoryBaseUrl: String) : Map<String,URL> {
|
||||
val urlMap = mutableMapOf<String,URL>()
|
||||
artifacts.forEach { artifact ->
|
||||
val url = URL("$artifactoryBaseUrl/$artifact/$version/$artifact-$version.jar")
|
||||
log.info("Artifactory resource URL: $url")
|
||||
try {
|
||||
url.openStream()
|
||||
urlMap[artifact] = url
|
||||
}
|
||||
catch (ex: IOException) {
|
||||
log.warn("Unable to open artifactory resource URL: ${ex.message}")
|
||||
}
|
||||
}
|
||||
return urlMap
|
||||
}
|
||||
|
||||
/**
|
||||
* Get representation of a Corda distribution based on its version string and fat JAR path.
|
||||
* @param type The Corda distribution type.
|
||||
@ -166,13 +206,24 @@ class Distribution private constructor(
|
||||
* Get registered representation of a Corda distribution based on its version string.
|
||||
* @param version The version of the Corda distribution
|
||||
*/
|
||||
private val entVersionScheme = "^\\d\\.\\d\\.\\d.*".toRegex() // ENTERPRISE version scheme x.y.z,
|
||||
private val osVersionScheme = "^\\d\\.\\d.*".toRegex() // OS version scheme x.y
|
||||
|
||||
fun fromVersionString(version: String): Distribution = when (version) {
|
||||
"master" -> MASTER
|
||||
"r3-master" -> R3_MASTER
|
||||
"corda-3.0" -> fromArtifactory(Type.CORDA_OS, version)
|
||||
"corda-3.1" -> fromArtifactory(Type.CORDA_OS, version)
|
||||
"3.1-corda" -> fromArtifactory(Type.CORDA_OS, version)
|
||||
"R3.CORDA-3.0.0-DEV-PREVIEW-3" -> fromArtifactory(Type.CORDA_ENTERPRISE, version)
|
||||
else -> distributions.firstOrNull { it.version == version } ?: throw CordaRuntimeException("Unable to locate Corda distribution for version: $version")
|
||||
else -> {
|
||||
if (version.matches(entVersionScheme))
|
||||
fromArtifactory(Type.CORDA_ENTERPRISE, version)
|
||||
else if (version.matches(osVersionScheme))
|
||||
fromArtifactory(Type.CORDA_OS, version)
|
||||
else
|
||||
distributions.firstOrNull { it.version == version }
|
||||
?: throw CordaRuntimeException("Invalid Corda distribution for specified version: $version")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ import java.util.concurrent.CountDownLatch
|
||||
*/
|
||||
class Node(
|
||||
val config: Configuration,
|
||||
private val rootDirectory: Path = currentDirectory,
|
||||
val rootDirectory: Path = currentDirectory,
|
||||
private val settings: ServiceSettings = ServiceSettings(),
|
||||
val rpcProxy: Boolean = false,
|
||||
val networkType: Distribution.Type
|
||||
@ -95,13 +95,13 @@ class Node(
|
||||
log.info("Configuring {} ...", this)
|
||||
serviceDependencies.addAll(config.database.type.dependencies(config))
|
||||
config.distribution.ensureAvailable()
|
||||
if (networkType == Distribution.Type.CORDA_OS) {
|
||||
config.writeToFile(rootDirectory / "${config.name}_node.conf")
|
||||
}
|
||||
else {
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null) {
|
||||
val nodeDirectory = (rootDirectory / config.name).createDirectories()
|
||||
config.writeToFile(nodeDirectory / "node.conf")
|
||||
}
|
||||
else {
|
||||
config.writeToFile(rootDirectory / "${config.name}_node.conf")
|
||||
}
|
||||
installApps()
|
||||
}
|
||||
|
||||
@ -273,8 +273,7 @@ class Node(
|
||||
}
|
||||
|
||||
private fun installApps() {
|
||||
val version = config.distribution.version
|
||||
val appDirectory = stagingRoot / "corda" / version / "apps"
|
||||
val appDirectory = config.distribution.cordappDirectory
|
||||
if (appDirectory.exists()) {
|
||||
val targetAppDirectory = runtimeDirectory / "cordapps"
|
||||
FileUtils.copyDirectory(appDirectory.toFile(), targetAppDirectory.toFile())
|
||||
@ -387,9 +386,10 @@ class Node(
|
||||
fun build(): Node {
|
||||
val name = name ?: error("Node name not set")
|
||||
val directory = directory ?: error("Runtime directory not set")
|
||||
val compatibilityZoneURL =
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE)
|
||||
compatibilityZoneURL ?: "http://localhost:1300"
|
||||
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
|
||||
val compatibilityZoneURL = null
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null)
|
||||
"http://localhost:1300" // TODO: add additional USE_NETWORK_SERVICES_URL to specify location of existing operational environment to use.
|
||||
else null
|
||||
return Node(
|
||||
Configuration(
|
||||
|
@ -36,7 +36,7 @@ class Configuration(
|
||||
vararg configElements: ConfigurationTemplate
|
||||
) {
|
||||
|
||||
private val developerMode = (distribution.type == Distribution.Type.CORDA_OS)
|
||||
private val developerMode = System.getProperty("USE_NETWORK_SERVICES") == null
|
||||
|
||||
val cordaX500Name: CordaX500Name by lazy({
|
||||
CordaX500Name(name, location, country)
|
||||
|
@ -60,7 +60,7 @@ open class Command(
|
||||
|
||||
private val thread = Thread(Runnable {
|
||||
try {
|
||||
log.info("Command: $command")
|
||||
log.info("Executing command: $command from directory: $directory")
|
||||
val processBuilder = ProcessBuilder(command)
|
||||
.directory(directory.toFile())
|
||||
.redirectErrorStream(true)
|
||||
|
@ -1,3 +1,4 @@
|
||||
minimumPlatformVersion = 1
|
||||
maxMessageSize = 10485760
|
||||
maxTransactionSize = 10485760
|
||||
eventHorizonDays = 30
|
||||
|
@ -5,3 +5,4 @@ notaries : [{
|
||||
minimumPlatformVersion = 1
|
||||
maxMessageSize = 10485760
|
||||
maxTransactionSize = 10485760
|
||||
eventHorizonDays = 30
|
||||
|
@ -10,13 +10,13 @@
|
||||
|
||||
package net.corda.behave.scenarios.helpers
|
||||
|
||||
import net.corda.behave.logging.getLogger
|
||||
import net.corda.behave.scenarios.ScenarioState
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.utilities.contextLogger
|
||||
|
||||
abstract class Substeps(protected val state: ScenarioState) {
|
||||
|
||||
protected val log = contextLogger()
|
||||
protected val log = getLogger<Substeps>()
|
||||
|
||||
protected fun withNetwork(action: ScenarioState.() -> Unit) =
|
||||
state.withNetwork(action)
|
||||
|
@ -14,7 +14,7 @@ cd ${BUILD_DIR}
|
||||
../../gradlew behaveJar
|
||||
|
||||
BEHAVE_JAR=$(ls build/libs/corda-behave-*.jar | tail -n1)
|
||||
STAGING_ROOT=~/staging
|
||||
STAGING_ROOT="${STAGING_ROOT:-TMPDIR/staging}"
|
||||
|
||||
# startup
|
||||
java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} --glue net.corda.behave.scenarios -path ./src/scenario/resources/features/startup/logging.feature
|
||||
|
@ -0,0 +1,34 @@
|
||||
package net.corda.behave.node
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class DistributionTest {
|
||||
|
||||
/**
|
||||
* NOTE: ensure you have correctly setup the system environment variables:
|
||||
* CORDA_ARTIFACTORY_USERNAME
|
||||
* CORDA_ARTIFACTORY_PASSWORD
|
||||
*/
|
||||
|
||||
@Test
|
||||
fun `resolve OS distribution from Artifactory`() {
|
||||
val distribution = Distribution.fromArtifactory(Distribution.Type.CORDA_OS, "3.1-corda")
|
||||
assertNotNull(distribution.artifactUrlMap)
|
||||
assertThat(distribution.artifactUrlMap!!.size).isGreaterThanOrEqualTo(3)
|
||||
// -DSTAGING_ROOT=${STAGING_ROOT}
|
||||
distribution.ensureAvailable()
|
||||
println("Check contents of ${distribution.path}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolve Enterprise distribution from Artifactory`() {
|
||||
val distribution = Distribution.fromArtifactory(Distribution.Type.CORDA_ENTERPRISE, "3.0.0-RC01")
|
||||
assertNotNull(distribution.artifactUrlMap)
|
||||
assertThat(distribution.artifactUrlMap!!.size).isGreaterThanOrEqualTo(5)
|
||||
// -DSTAGING_ROOT=${STAGING_ROOT}
|
||||
distribution.ensureAvailable()
|
||||
println("Check contents of ${distribution.path}")
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
The Behave Cucumber Scenarios defined under these sub-directories exercise Corda Enterprise and OS Corda distributions to include:
|
||||
- Open Source master
|
||||
- Corda Enterprise master
|
||||
@ -30,4 +33,197 @@ Further goals of this project are to:
|
||||
- automatically generate and register Docker images with target Azure Test Environments (eg. Functional/QA, CTS)
|
||||
- effect execution of scenarios in specified Target Environments
|
||||
- use Before and After hooks to pre-configure Target Environments to allow batch running of multiple scenarios (eg. a given
|
||||
feature will specify the environment once for one or many scenarios)
|
||||
feature will specify the environment once for one or many scenarios)
|
||||
|
||||
QA setup and usage instructions
|
||||
===============================
|
||||
|
||||
Setup
|
||||
-----
|
||||
Set up the staging area which will hold all the distributions of Corda referenced in the test scenarios:
|
||||
|
||||
- specify the staging root directory:
|
||||
|
||||
```bash
|
||||
$export STAGING_ROOT=$HOME/staging
|
||||
```
|
||||
|
||||
- if any of your tests are referencing a master version of [Corda OS](https://github.com/corda/corda), checkout the latest version of the Open Source repo and run:
|
||||
|
||||
```bash
|
||||
$ cd experimental/behave
|
||||
$ ./prepare.sh
|
||||
```
|
||||
|
||||
You should now see the following artifacts in your staging area:
|
||||
|
||||
```bash
|
||||
$ ls -lR /Users/home/staging/corda/corda-master
|
||||
total 285440
|
||||
drwxr-xr-x 3 user staff 96 4 Jun 16:11 apps
|
||||
-rw-r--r-- 1 user staff 55439705 4 Jun 16:11 corda.jar
|
||||
-rw-r--r-- 1 user staff 90699598 4 Jun 16:11 network-bootstrapper.jar
|
||||
|
||||
/Users/home/staging/corda/corda-master/apps:
|
||||
total 4688
|
||||
-rw------- 1 user staff 2396954 4 Jun 16:11 corda-finance-4.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
- similarly, if any of your tests are referencing a master version of [Corda Enterprise](https://github.com/corda/enterprise), checkout the latest version of the Enterprise repo and run:
|
||||
|
||||
```bash
|
||||
$ cd experimental/behave
|
||||
$ ./prepare.sh
|
||||
```
|
||||
|
||||
You should now see the following artifacts in your staging area:
|
||||
|
||||
```bash
|
||||
$ ls -lR /Users/home/staging/corda/r3corda-master/
|
||||
total 503264
|
||||
drwxr-xr-x 6 user staff 192 4 Jun 16:39 apps
|
||||
-rw-r--r-- 1 user staff 6239281 4 Jun 16:39 corda-rpcProxy.jar
|
||||
-rw-r--r-- 1 user staff 66441262 4 Jun 16:38 corda.jar
|
||||
-rw-r--r-- 1 user staff 71987460 4 Jun 16:39 dbmigration.jar
|
||||
-rw-r--r-- 1 user staff 112985324 4 Jun 16:39 network-bootstrapper.jar
|
||||
-rwxr-xr-x 1 user staff 1224 4 Jun 16:39 startRPCproxy.sh
|
||||
|
||||
/Users/home/staging/corda/r3corda-master/apps:
|
||||
total 82248
|
||||
-rw------- 1 user staff 2418144 4 Jun 16:38 corda-finance-R3.CORDA-3.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- all versions of Corda published to the Artifactory release repositories are automatically downloaded and configured
|
||||
on the fly as part of a test scenario.
|
||||
- Docker must be running for SQL Server, Oracle and PostrgeSQL tests.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Checkout the latest version of the Enterprise repo and run:
|
||||
|
||||
```bash
|
||||
$cd experimental/behave
|
||||
../../gradlew behaveJar
|
||||
````
|
||||
|
||||
Change to the QA testing directory containing the scenario scripts and run:
|
||||
```bash
|
||||
$cd ../../test/qa
|
||||
$export BEHAVE_JAR=$(ls ../../../experimental/behave/build/libs/corda-behave-*.jar | tail -n1)
|
||||
```
|
||||
|
||||
To verify the tool is ready to be used run:
|
||||
|
||||
```bash
|
||||
$ java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR}
|
||||
```
|
||||
|
||||
You should now see the following output providing details on how to run the tool:
|
||||
|
||||
```bash
|
||||
Missing required option(s) [path]
|
||||
Usage: ScenarioRunner [options] --path <location of feature scenario definitions>
|
||||
|
||||
Examples:
|
||||
ScenarioRunner -path <features-dir>
|
||||
ScenarioRunner -path <features-dir>/<name>.feature
|
||||
ScenarioRunner -path <features-dir>/<name>.feature:3:9
|
||||
|
||||
ScenarioRunner -path <features-dir> --plugin html --tags @qa
|
||||
ScenarioRunner -path <features-dir> --plugin html --tags @compatibility
|
||||
|
||||
Please refer to the Cucumber documentation https://cucumber.io/docs/reference/jvm for more info.
|
||||
|
||||
Option (* = required) Description
|
||||
--------------------- -----------
|
||||
-d
|
||||
--glue [location of additional step (default: net.corda.behave.scenarios)
|
||||
definitions, hooks and plugins]
|
||||
* --path <Path location of .feature
|
||||
specifications>
|
||||
--plugin [register additional plugins (default: pretty)
|
||||
(see https://cucumber.
|
||||
io/docs/reference/jvm)]
|
||||
--tags [only run scenarios marked as
|
||||
@<tag-name>]
|
||||
```
|
||||
Note: passing in a *-d* option will perform a dry run only (validates the syntax of the scenario but does not execute the code)
|
||||
|
||||
Scenario scripts
|
||||
----------------
|
||||
There are currently two sets of scripts:
|
||||
1. Functional
|
||||
|
||||
```bash
|
||||
# the Cucumber behave test scenario definitions themselves
|
||||
$ls -l functional/resources/features/functional.feature
|
||||
# Unix script to easily run these
|
||||
$ls -l functional/resources/scripts/run-functional.sh
|
||||
```
|
||||
|
||||
2. Interoperability & Compatibility
|
||||
|
||||
```bash
|
||||
# the Cucumber behave test scenario definitions themselves
|
||||
$ls -l compatibility/resources/features/interoperability.feature
|
||||
# Unix script to easily run these
|
||||
$ls -l compatibility/resources/scripts/run-interoperability.sh
|
||||
```
|
||||
|
||||
Note: the complete suite of Compatibility test scenarios have note yet been fully implemented.
|
||||
|
||||
You can now run the above test scripts in a number of different ways:
|
||||
|
||||
* as a complete suite called a *feature set*:
|
||||
|
||||
```bash
|
||||
# run all scenarios in the functional.feature file
|
||||
$java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} -path functional/resources/features/functional.feature
|
||||
```
|
||||
|
||||
```bash
|
||||
# run all scenarios in the interoperability.feature file
|
||||
$java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} -path compatibility/resources/features/interoperability.feature
|
||||
```
|
||||
|
||||
* as a set of tagged scenarios within a feature file:
|
||||
|
||||
```bash
|
||||
# run all scenarios tagged with qa in the interoperability.feature file
|
||||
$java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} -path compatibility/resources/features/interoperability.feature:@qa
|
||||
```
|
||||
|
||||
* as an individual scenario for all example configurations:
|
||||
|
||||
```bash
|
||||
# run the scenario defined on line 5 of the interoperability.feature file
|
||||
$java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} -path compatibility/resources/features/interoperability.feature:5
|
||||
|
||||
# by default the above will run as many times as there are parameterised variable definitions
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version | Corda-Node-Version | Currency |
|
||||
| r3-master | corda-master | GBP |
|
||||
| corda-3.0 | corda-3.1 | GBP |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | corda-3.0 | GBP |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | corda-3.1 | GBP |
|
||||
```
|
||||
|
||||
* as an individual scenario for a single example configuration you will need to comment out the other example line items:
|
||||
|
||||
```bash
|
||||
# run the scenario defined on line 5 of the interoperability.feature file
|
||||
$java -DSTAGING_ROOT=${STAGING_ROOT} -jar ${BEHAVE_JAR} -path compatibility/resources/features/interoperability.feature:5
|
||||
|
||||
# by default the above will the scenario using *corda-3.0* and *corda-3.1* node versions only:
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version | Corda-Node-Version | Currency |
|
||||
# | r3-master | corda-master | GBP |
|
||||
| corda-3.0 | corda-3.1 | GBP |
|
||||
# | R3.CORDA-3.0.0-DEV-PREVIEW-3 | corda-3.0 | GBP |
|
||||
# | R3.CORDA-3.0.0-DEV-PREVIEW-3 | corda-3.1 | GBP |
|
||||
```
|
||||
|
@ -12,5 +12,8 @@ BEHAVE_DIR=${R3CORDA_HOME}/experimental/behave
|
||||
cd ${BEHAVE_DIR}
|
||||
../../gradlew behaveJar
|
||||
|
||||
# QA interoperability
|
||||
java -jar ${BEHAVE_DIR}/build/libs/corda-behave.jar -d --glue net.corda.behave.scenarios -path ${R3CORDA_HOME}/testing/qa/behave/compatibility/resources/features/interoperability.feature
|
||||
BEHAVE_JAR=$(ls build/libs/corda-behave-*.jar | tail -n1)
|
||||
STAGING_ROOT="${STAGING_ROOT:-TMPDIR/staging}"
|
||||
|
||||
# QA interoperability (specify -d for dry-run)
|
||||
java -DSTAGING_ROOT=${STAGING_ROOT} -DDISABLE_CLEANUP=true -jar ${BEHAVE_JAR} --glue net.corda.behave.scenarios -path ${R3CORDA_HOME}/testing/qa/behave/compatibility/resources/features/interoperability.feature
|
||||
|
@ -7,12 +7,12 @@ Feature: QA Operational
|
||||
And node PartyA has the finance app installed
|
||||
When the network is ready
|
||||
Then node PartyA is on platform version 4
|
||||
And node PartyA is on release version R3.CORDA-3.0.0-DEV-PREVIEW-3
|
||||
And node PartyA is on release version <Version-label>
|
||||
And user can retrieve node identity information for node PartyA
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 |
|
||||
| R3-Corda-Node-Version | Version-label |
|
||||
| r3-master | 3.0.0-SNAPSHOT |
|
||||
|
||||
Scenario Outline: QA: Stand up a basic Corda Enterprise Network with one node and a notary; node can issue cash to itself
|
||||
Given a node PartyA of version <R3-Corda-Node-Version> with proxy
|
||||
@ -22,8 +22,8 @@ Feature: QA Operational
|
||||
Then node PartyA can issue 1000 <Currency>
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version | Currency |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | GBP |
|
||||
| R3-Corda-Node-Version | Currency |
|
||||
| r3-master | GBP |
|
||||
|
||||
Scenario Outline: User can connect to a Corda Enterprise node using a SQL Server database
|
||||
Given a node PartyA of version <Node-Version>
|
||||
@ -32,8 +32,8 @@ Feature: QA Operational
|
||||
Then user can connect to the database of node PartyA
|
||||
|
||||
Examples:
|
||||
| Node-Version | Database-Type |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | SQL Server |
|
||||
| Node-Version | Database-Type |
|
||||
| r3-master | SQL Server |
|
||||
|
||||
Scenario Outline: QA: Node using H2 can transact with node using SQL Server, in a Corda Enterprise configured network.
|
||||
Given a node PartyA of version <R3-Corda-Node-Version> with proxy
|
||||
@ -47,8 +47,8 @@ Feature: QA Operational
|
||||
And node PartyA can transfer 100 <Currency> to node B
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version | Currency | Database-Type |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | GBP | SQL Server |
|
||||
| R3-Corda-Node-Version | Currency | Database-Type |
|
||||
| r3-master | GBP | SQL Server |
|
||||
|
||||
Scenario Outline: User can connect to a Corda Enterprise node using a PostgreSQL database
|
||||
Given a node PartyA of version <Node-Version>
|
||||
@ -57,8 +57,8 @@ Feature: QA Operational
|
||||
Then user can connect to the database of node PartyA
|
||||
|
||||
Examples:
|
||||
| Node-Version | Database-Type |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | postgres |
|
||||
| Node-Version | Database-Type |
|
||||
| r3-master | postgres |
|
||||
|
||||
Scenario Outline: QA: Node using H2 can transact with node using Postgres, in a Corda Enterprise configured network.
|
||||
Given a node PartyA of version <R3-Corda-Node-Version> with proxy
|
||||
@ -72,5 +72,5 @@ Feature: QA Operational
|
||||
And node PartyA can transfer 100 <Currency> to node B
|
||||
|
||||
Examples:
|
||||
| R3-Corda-Node-Version | Currency | Database-Type |
|
||||
| R3.CORDA-3.0.0-DEV-PREVIEW-3 | GBP | postgres |
|
||||
| R3-Corda-Node-Version | Currency | Database-Type |
|
||||
| r3-master | GBP | postgres |
|
||||
|
@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Run this script from your ${R3CORDA_HOME}/experimental/behave directory, where R3CORDA_HOME refers to Corda Enterprise source code (eg. GitHub master, branch or TAG)
|
||||
# Run this script from your $R3CORDA_HOME directory, where R3CORDA_HOME refers to R3 Corda source code (eg. GitHub master, branch or TAG)
|
||||
# For example:
|
||||
# R3CORDA_HOME => git clone https://github.com/corda/enterprise
|
||||
#
|
||||
# $ testing/qa/behave/compatibility/resources/scripts/run-functional.sh
|
||||
# $ testing/qa/behave/functional/resources/scripts/run-functional.sh
|
||||
|
||||
|
||||
R3CORDA_HOME=$PWD
|
||||
@ -13,5 +13,8 @@ BEHAVE_DIR=${R3CORDA_HOME}/experimental/behave
|
||||
cd ${BEHAVE_DIR}
|
||||
../../gradlew behaveJar
|
||||
|
||||
# QA functional
|
||||
java -jar ${BEHAVE_DIR}/build/libs/corda-behave.jar -d --glue net.corda.behave.scenarios -path ${R3CORDA_HOME}/testing/qa/behave/functional/resources/features/functional.feature
|
||||
BEHAVE_JAR=$(ls build/libs/corda-behave-*.jar | tail -n1)
|
||||
STAGING_ROOT="${STAGING_ROOT:-TMPDIR/staging}"
|
||||
|
||||
# QA functional (specify -d for dry-run)
|
||||
java -DSTAGING_ROOT=${STAGING_ROOT} -DDISABLE_CLEANUP=true -jar ${BEHAVE_JAR} --glue net.corda.behave.scenarios -path ${R3CORDA_HOME}/testing/qa/behave/functional/resources/features/functional.feature
|
@ -12,7 +12,11 @@
|
||||
|
||||
VERSION=master
|
||||
BUILD_DIR=`pwd`
|
||||
STAGING_DIR=~/staging/corda/corda-${VERSION}
|
||||
STAGING_DIR="${STAGING_ROOT:-$TMPDIR/staging}"
|
||||
echo "Staging directory: $STAGING_DIR"
|
||||
|
||||
CORDA_DIR=${STAGING_DIR}/corda/corda-${VERSION}
|
||||
echo "Corda staging directory: $CORDA_DIR"
|
||||
|
||||
# Set up directories
|
||||
mkdir -p ${STAGING_DIR}/apps
|
||||
@ -21,19 +25,19 @@ cd ${BUILD_DIR}
|
||||
|
||||
echo "*************************************************************"
|
||||
echo "Building and installing $VERSION from $BUILD_DIR"
|
||||
echo " to $STAGING_DIR"
|
||||
echo " to $CORDA_DIR"
|
||||
echo "*************************************************************"
|
||||
|
||||
# Copy Corda capsule into deps
|
||||
./gradlew clean install
|
||||
cp -v $(ls node/capsule/build/libs/corda-*.jar | tail -n1) ${STAGING_DIR}/corda.jar
|
||||
cp -v $(ls finance/build/libs/corda-finance-*.jar | tail -n1) ${STAGING_DIR}/apps
|
||||
cp -v $(ls node/capsule/build/libs/corda-*.jar | tail -n1) ${CORDA_DIR}/corda.jar
|
||||
cp -v $(ls finance/build/libs/corda-finance-*.jar | tail -n1) ${CORDA_DIR}/apps
|
||||
|
||||
# Build Network Bootstrapper
|
||||
./gradlew buildBootstrapperJar
|
||||
cp -v $(ls tools/bootstrapper/build/libs/*.jar | tail -n1) ${STAGING_DIR}/network-bootstrapper.jar
|
||||
cp -v $(ls tools/bootstrapper/build/libs/*.jar | tail -n1) ${CORDA_DIR}/network-bootstrapper.jar
|
||||
|
||||
# Build rpcProxy (required by CTS Scenario Driver to call Corda 3.0 which continues to use Kryo for RPC)
|
||||
./gradlew testing:qa:behave:tools:rpc-proxy:rpcProxyJar
|
||||
cp -v $(ls testing/qa/behave/tools/rpc-proxy/build/libs/corda-rpcProxy*.jar | tail -n1) ${STAGING_DIR}/corda-rpcProxy.jar
|
||||
cp -v testing/qa/behave/tools/rpc-proxy/startRPCproxy.sh ${STAGING_DIR}
|
||||
cp -v $(ls testing/qa/behave/tools/rpc-proxy/build/libs/corda-rpcProxy*.jar | tail -n1) ${CORDA_DIR}/corda-rpcProxy.jar
|
||||
cp -v testing/qa/behave/tools/rpc-proxy/startRPCproxy.sh ${CORDA_DIR}
|
Loading…
x
Reference in New Issue
Block a user