CORE-10259: Update template to use CSDE plugin (#35)
* updated csde to use plugin * update csde block * update network file * allign to Kotlin csde * CORE-10259: Update template to use CSDE plugin --------- Co-authored-by: mattbradburyr3 <matthew.bradbury@r3.com>
This commit is contained in:
parent
a043d8dcd1
commit
2346e34494
3
.gitignore
vendored
3
.gitignore
vendored
@ -86,3 +86,6 @@ workspace/**
|
||||
#*.pfx
|
||||
#CPIFileStatus*.json
|
||||
#GroupPolicy.json
|
||||
|
||||
# Ignore temporary data files
|
||||
*.dat
|
35
build.gradle
35
build.gradle
@ -6,7 +6,7 @@ plugins {
|
||||
id 'org.jetbrains.kotlin.plugin.jpa'
|
||||
id 'java'
|
||||
id 'maven-publish'
|
||||
id 'csde'
|
||||
id 'net.corda.plugins.csde'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@ -15,6 +15,23 @@ allprojects {
|
||||
|
||||
def javaVersion = VERSION_11
|
||||
|
||||
// Configure the CSDE
|
||||
csde {
|
||||
cordaClusterURL = "https://localhost:8888"
|
||||
networkConfigFile = "config/static-network-config.json"
|
||||
corDappCpiName = "MyCorDapp"
|
||||
notaryCpiName = "NotaryServer"
|
||||
cordaRpcUser = "admin"
|
||||
cordaRpcPasswd ="admin"
|
||||
csdeWorkspaceDir = "workspace"
|
||||
notaryVersion = cordaNotaryPluginsVersion
|
||||
combinedWorkerVersion = "5.0.0.0-Gecko1.0"
|
||||
postgresJdbcVersion = "42.4.3"
|
||||
cordaDbContainerName = "CSDEpostgresql"
|
||||
cordaBinDir = "${System.getProperty("user.home")}/.corda/corda5"
|
||||
cordaCliBinDir = "${System.getProperty("user.home")}/.corda/cli"
|
||||
}
|
||||
|
||||
// Declare the set of Java compiler options we need to build a CorDapp.
|
||||
tasks.withType(JavaCompile) {
|
||||
// -parameters - Needed for reflection and serialization to work correctly.
|
||||
@ -25,9 +42,23 @@ allprojects {
|
||||
|
||||
repositories {
|
||||
// All dependencies are held in Maven Central
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
|
||||
// R3 Internal repositories for dev
|
||||
// Repository provides Corda 5 binaries that implement Corda-API.
|
||||
// These will be made publicly available.
|
||||
// Final location to be decided.
|
||||
// Repository subject to change
|
||||
maven {
|
||||
url = "$artifactoryContextUrl/"
|
||||
url = "$artifactoryContextUrl/corda-os-maven"
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
username = findProperty('cordaArtifactoryUsername') ?: System.getenv('CORDA_ARTIFACTORY_USERNAME')
|
||||
password = findProperty('cordaArtifactoryPassword') ?: System.getenv('CORDA_ARTIFACTORY_PASSWORD')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
|
||||
plugins {
|
||||
id 'groovy-gradle-plugin'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
def constants = new Properties()
|
||||
file("$rootDir/../gradle.properties").withInputStream { InputStream input -> constants.load(input) }
|
||||
def artifactoryContextUrl = constants.getProperty('artifactoryContextUrl')
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
url = "$artifactoryContextUrl/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||
|
||||
implementation "com.konghq:unirest-java:$unirestVersion"
|
||||
implementation "com.konghq:unirest-objectmapper-jackson:$unirestVersion"
|
||||
implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
|
||||
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion"
|
||||
|
||||
implementation "net.corda:corda-base:$cordaApiVersion"
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
jacksonVersion = 2.13.4
|
||||
unirestVersion=3.13.10
|
||||
|
||||
cordaApiVersion=5.0.0.665-Gecko1.0
|
@ -1 +0,0 @@
|
||||
// File intentionally left blank
|
@ -1,259 +0,0 @@
|
||||
// Note, IntelliJ does not recognise the imported Java Classes, hence they are
|
||||
// highlighted in Red. However, they are recognised in the gradle compilation.
|
||||
|
||||
|
||||
// todo: look at the declaration of the script variables, can they be combined with the declaration of the Project Context
|
||||
// todo: investigate adding corda-cli to the class path then executing it directly - might not work as gradle has to set up the jar file, so its not their when you start.
|
||||
// Todo: write a test flow runner helper function??
|
||||
// todo: rename deployCPIsHelper
|
||||
// todo: add proper logging, rather than reading Stdout
|
||||
// todo: add test corda running/live task
|
||||
// todo: add a test to check docker is running and display error if not + halt start corda
|
||||
// todo: add a clean corda task.
|
||||
// todo: fix logging level and make it configurable.
|
||||
|
||||
|
||||
import com.r3.csde.CordaLifeCycleHelper
|
||||
import com.r3.csde.ProjectContext
|
||||
import com.r3.csde.DeployCPIsHelper
|
||||
import com.r3.csde.BuildCPIsHelper
|
||||
import com.r3.csde.ProjectUtils
|
||||
import com.r3.csde.CordaStatusQueries
|
||||
import com.r3.csde.VNodesHelper
|
||||
import com.r3.csde.NetworkConfig
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'groovy'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
|
||||
configurations {
|
||||
combinedWorker{
|
||||
canBeConsumed = false
|
||||
canBeResolved= true
|
||||
}
|
||||
|
||||
myPostgresJDBC {
|
||||
canBeConsumed = false
|
||||
canBeResolved = true
|
||||
}
|
||||
|
||||
notaryServerCPB {
|
||||
canBeConsumed = false
|
||||
canBeResolved = true
|
||||
}
|
||||
}
|
||||
|
||||
// Dependencies for supporting tools
|
||||
dependencies {
|
||||
combinedWorker "net.corda:corda-combined-worker:$combinedWorkerVersion"
|
||||
myPostgresJDBC "org.postgresql:postgresql:$postgresqlVersion"
|
||||
notaryServerCPB("com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-server:$cordaNotaryPluginsVersion") {
|
||||
artifact {
|
||||
classifier = 'package'
|
||||
extension = 'cpb'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// task groupings
|
||||
def cordaGroup = 'csde-corda' // corda lifecycle tasks
|
||||
def cordappGroup = 'csde-cordapp' // tasks to build and deploy corDapps
|
||||
def queriesGroup = 'csde-queries' // tasks which query corda status
|
||||
def supportingGroup = 'supporting' // tasks which should be hidden from the csde user
|
||||
|
||||
|
||||
def cordaBinDir = System.getenv("CSDE_CORDA_BIN") ?: System.getProperty('user.home') + "/.corda/corda5"
|
||||
def cordaCliBinDir = System.getenv("CSDE_CORDA_CLI") ?:System.getProperty('user.home') + "/.corda/cli"
|
||||
def cordaJDBCDir = cordaBinDir + "/jdbcDrivers"
|
||||
def cordaNotaryServerDir = cordaBinDir + "/notaryserver"
|
||||
def signingCertAlias="gradle-plugin-default-key"
|
||||
// Get error if this is not a autotyped object
|
||||
// def signingCertFName = "$rootDir/config/gradle-plugin-default-key.pem"
|
||||
def signingCertFName = rootDir.toString() + "/config/gradle-plugin-default-key.pem"
|
||||
def keystoreAlias = "my-signing-key"
|
||||
def keystoreFName = devEnvWorkspace + "/signingkeys.pfx"
|
||||
def keystoreCertFName = devEnvWorkspace + "/signingkey1.pem"
|
||||
def combiWorkerPidCacheFile = devEnvWorkspace + "/CordaPID.dat"
|
||||
// todo: can we rely on the build directory always being /workflow/build? aslo, is the
|
||||
// workflow directory the correct place to build the cpb to. shoudl it be the main build directory.
|
||||
def workflowBuildDir = rootDir.toString() + "/workflows/build"
|
||||
|
||||
|
||||
// todo: Need to read things from cordapp plugin - the cordapp names will be changed by the user
|
||||
def appCpiName = 'cpi name' // !!! this must match with the cpi name in /config/static-network-config.json
|
||||
def notaryCpiName = 'CSDE Notary Server CPI'
|
||||
|
||||
|
||||
// todo: there should be a better way to set up these project context variables.
|
||||
def projectContext = new ProjectContext(project,
|
||||
cordaClusterURL.toString(),
|
||||
cordaRpcUser,
|
||||
cordaRpcPasswd,
|
||||
devEnvWorkspace,
|
||||
// todo: why is this not obtained in the groovy def's abouve - its inconsistent.
|
||||
new String("${System.getProperty("java.home")}/bin"),
|
||||
dbContainerName,
|
||||
cordaJDBCDir,
|
||||
combiWorkerPidCacheFile,
|
||||
signingCertAlias,
|
||||
signingCertFName,
|
||||
keystoreAlias,
|
||||
keystoreFName,
|
||||
keystoreCertFName,
|
||||
appCpiName,
|
||||
notaryCpiName,
|
||||
devEnvWorkspace,
|
||||
cordaCliBinDir,
|
||||
cordaNotaryServerDir,
|
||||
workflowBuildDir,
|
||||
cordaNotaryPluginsVersion
|
||||
)
|
||||
|
||||
def networkConfig = new NetworkConfig("config/static-network-config.json")
|
||||
|
||||
def utils = new ProjectUtils()
|
||||
|
||||
// Initiate workspace folder
|
||||
|
||||
tasks.register('projInit') {
|
||||
group = supportingGroup
|
||||
doLast {
|
||||
mkdir devEnvWorkspace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CordaLifeCycle tasks
|
||||
|
||||
def cordaLifeCycle = new CordaLifeCycleHelper(projectContext)
|
||||
|
||||
tasks.register("startCorda") {
|
||||
group = cordaGroup
|
||||
dependsOn('getDevCordaLite', 'getPostgresJDBC')
|
||||
doLast {
|
||||
mkdir devEnvWorkspace
|
||||
cordaLifeCycle.startCorda()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("stopCorda") {
|
||||
group = cordaGroup
|
||||
doLast {
|
||||
cordaLifeCycle.stopCorda()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("stopAndCleanCorda") {
|
||||
group = cordaGroup
|
||||
dependsOn('clean')
|
||||
doLast {
|
||||
try {
|
||||
cordaLifeCycle.stopCorda()
|
||||
} catch (Exception ignore) {
|
||||
println("ignoring exception: ${ignore.toString()}")
|
||||
}
|
||||
delete devEnvWorkspace
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("getPostgresJDBC") {
|
||||
group = supportingGroup
|
||||
doLast {
|
||||
copy {
|
||||
from configurations.myPostgresJDBC
|
||||
into "$cordaJDBCDir"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("getDevCordaLite", Copy) {
|
||||
group = supportingGroup
|
||||
from configurations.combinedWorker
|
||||
into cordaBinDir
|
||||
}
|
||||
|
||||
|
||||
// Corda status queries
|
||||
|
||||
def cordaStatusQueries = new CordaStatusQueries(projectContext)
|
||||
|
||||
|
||||
tasks.register('listVNodes') {
|
||||
group = queriesGroup
|
||||
doLast {
|
||||
cordaStatusQueries.listVNodes()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('listCPIs') {
|
||||
group = queriesGroup
|
||||
doLast {
|
||||
cordaStatusQueries.listCPIs()
|
||||
}
|
||||
}
|
||||
|
||||
// Build CPI tasks
|
||||
|
||||
def buildCPIsHelper = new BuildCPIsHelper(projectContext, networkConfig)
|
||||
|
||||
tasks.register("1-createGroupPolicy") {
|
||||
group = cordappGroup
|
||||
dependsOn('projInit')
|
||||
doLast {
|
||||
buildCPIsHelper.createGroupPolicy()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("getNotaryServerCPB", Copy) {
|
||||
group = supportingGroup
|
||||
from configurations.notaryServerCPB
|
||||
into cordaNotaryServerDir
|
||||
}
|
||||
|
||||
tasks.register('2-createKeystore') {
|
||||
group = cordappGroup
|
||||
dependsOn('projInit')
|
||||
doLast {
|
||||
buildCPIsHelper.createKeyStore()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('3-buildCPIs') {
|
||||
group = cordappGroup
|
||||
def dependsOnTasks = subprojects.collect {it.tasks.findByName("build") }
|
||||
dependsOnTasks.add('1-createGroupPolicy')
|
||||
dependsOnTasks.add('2-createKeystore')
|
||||
dependsOnTasks.add('getNotaryServerCPB')
|
||||
dependsOn dependsOnTasks
|
||||
doLast{
|
||||
buildCPIsHelper.buildCPIs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// deploy CPI tasks
|
||||
|
||||
def deployCPIsHelper = new DeployCPIsHelper(projectContext)
|
||||
|
||||
tasks.register('4-deployCPIs') {
|
||||
group = cordappGroup
|
||||
dependsOn('3-buildCPIs')
|
||||
doLast {
|
||||
deployCPIsHelper.deployCPIs()
|
||||
}
|
||||
}
|
||||
|
||||
// Setup VNodes tasks
|
||||
|
||||
def vNodesHelper = new VNodesHelper(projectContext, networkConfig )
|
||||
|
||||
tasks.register('5-vNodeSetup') {
|
||||
group = cordappGroup
|
||||
dependsOn('4-deployCPIs')
|
||||
doLast {
|
||||
vNodesHelper.vNodesSetup()
|
||||
}
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
// todo: This class needs refactoring, see https://r3-cev.atlassian.net/browse/CORE-11624
|
||||
public class BuildCPIsHelper {
|
||||
|
||||
public ProjectContext pc;
|
||||
public ProjectUtils utils;
|
||||
|
||||
public NetworkConfig config;
|
||||
public BuildCPIsHelper(ProjectContext _pc, NetworkConfig _config) {
|
||||
pc = _pc;
|
||||
utils = new ProjectUtils(pc);
|
||||
config = _config;
|
||||
}
|
||||
|
||||
public void createGroupPolicy() throws IOException {
|
||||
|
||||
File groupPolicyFile = new File(String.format("%s/GroupPolicy.json", pc.devEnvWorkspace));
|
||||
File devnetFile = new File(pc.project.getRootDir() + "/" + config.getConfigFilePath());
|
||||
|
||||
|
||||
if (!groupPolicyFile.exists() || groupPolicyFile.lastModified() < devnetFile.lastModified()) {
|
||||
|
||||
pc.out.println("createGroupPolicy: Creating a GroupPolicy");
|
||||
|
||||
List<String> configX500Ids = config.getX500Names();
|
||||
LinkedList<String> commandList = new LinkedList<>();
|
||||
|
||||
commandList.add(String.format("%s/java", pc.javaBinDir));
|
||||
commandList.add(String.format("-Dpf4j.pluginsDir=%s/plugins/", pc.cordaCliBinDir));
|
||||
commandList.add("-jar");
|
||||
commandList.add(String.format("%s/corda-cli.jar", pc.cordaCliBinDir));
|
||||
commandList.add("mgm");
|
||||
commandList.add("groupPolicy");
|
||||
for (String id : configX500Ids) {
|
||||
commandList.add("--name");
|
||||
commandList.add(id);
|
||||
}
|
||||
commandList.add("--endpoint-protocol=1");
|
||||
commandList.add("--endpoint=http://localhost:1080");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(commandList);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||
|
||||
// todo add exception catching
|
||||
FileWriter fileWriter = new FileWriter(groupPolicyFile);
|
||||
String line;
|
||||
while (( line = reader.readLine()) != null){
|
||||
fileWriter.write(line + "\n");
|
||||
}
|
||||
fileWriter.close();
|
||||
|
||||
} else {
|
||||
pc.out.println("createPolicyTask: everything up to date; nothing to do.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void createKeyStore() throws IOException, InterruptedException {
|
||||
|
||||
File keystoreFile = new File(pc.keystoreFName);
|
||||
if(!keystoreFile.exists()) {
|
||||
pc.out.println("createKeystore: Create a keystore");
|
||||
|
||||
generateKeyPair();
|
||||
addDefaultSigningKey();
|
||||
exportCert();
|
||||
|
||||
} else {
|
||||
pc.out.println("createKeystore: keystore already created; nothing to do.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void generateKeyPair() throws IOException, InterruptedException {
|
||||
|
||||
LinkedList<String> cmdArray = new LinkedList<>();
|
||||
|
||||
cmdArray.add(pc.javaBinDir + "/keytool");
|
||||
cmdArray.add("-genkeypair");
|
||||
cmdArray.add("-alias");
|
||||
cmdArray.add(pc.keystoreAlias);
|
||||
cmdArray.add("-keystore");
|
||||
cmdArray.add(pc.keystoreFName);
|
||||
cmdArray.add("-storepass");
|
||||
cmdArray.add("keystore password");
|
||||
cmdArray.add("-dname");
|
||||
cmdArray.add("CN=CPI Example - My Signing Key, O=CorpOrgCorp, L=London, C=GB");
|
||||
cmdArray.add("-keyalg");
|
||||
cmdArray.add("RSA");
|
||||
cmdArray.add("-storetype");
|
||||
cmdArray.add("pkcs12");
|
||||
cmdArray.add("-validity");
|
||||
cmdArray.add("4000");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdArray);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
|
||||
}
|
||||
|
||||
private void addDefaultSigningKey() throws IOException, InterruptedException {
|
||||
|
||||
LinkedList<String> cmdArray = new LinkedList<>();
|
||||
|
||||
cmdArray.add(pc.javaBinDir + "/keytool");
|
||||
cmdArray.add("-importcert");
|
||||
cmdArray.add("-keystore");
|
||||
cmdArray.add(pc.keystoreFName);
|
||||
cmdArray.add("-storepass");
|
||||
cmdArray.add("keystore password");
|
||||
cmdArray.add("-noprompt");
|
||||
cmdArray.add("-alias");
|
||||
cmdArray.add(pc.signingCertAlias);
|
||||
cmdArray.add("-file");
|
||||
cmdArray.add(pc.signingCertFName);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdArray);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
}
|
||||
|
||||
private void exportCert() throws IOException, InterruptedException {
|
||||
|
||||
LinkedList<String> cmdArray = new LinkedList<>();
|
||||
|
||||
cmdArray.add(pc.javaBinDir + "/keytool");
|
||||
cmdArray.add("-exportcert");
|
||||
cmdArray.add("-rfc");
|
||||
cmdArray.add("-alias");
|
||||
cmdArray.add(pc.keystoreAlias);
|
||||
cmdArray.add("-keystore");
|
||||
cmdArray.add(pc.keystoreFName);
|
||||
cmdArray.add("-storepass");
|
||||
cmdArray.add("keystore password");
|
||||
cmdArray.add("-file");
|
||||
cmdArray.add(pc.keystoreCertFName);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdArray);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
|
||||
}
|
||||
|
||||
public void buildCPIs() throws IOException, InterruptedException, CsdeException {
|
||||
createCorDappCPI();
|
||||
createNotaryCPI();
|
||||
}
|
||||
|
||||
private void createCorDappCPI() throws IOException, InterruptedException, CsdeException {
|
||||
|
||||
String appCPIFilePath = pc.workflowBuildDir + "/" +
|
||||
pc.project.getRootProject().getName() + "-" +
|
||||
pc.project.getVersion() + ".cpi";
|
||||
|
||||
File appCPIFile = new File(appCPIFilePath);
|
||||
appCPIFile.delete();
|
||||
|
||||
File srcDir = new File(pc.workflowBuildDir + "/libs");
|
||||
File[] appCPBs = srcDir.listFiles(( x , name ) -> name.endsWith(".cpb"));
|
||||
if (appCPBs == null) throw new CsdeException("Expecting exactly one CPB but no CPB found.");
|
||||
if (appCPBs.length != 1) throw new CsdeException("Expecting exactly one CPB but more than one found.");
|
||||
|
||||
pc.out.println("appCpbs:");
|
||||
pc.out.println(appCPBs[0].getAbsolutePath());
|
||||
|
||||
LinkedList<String> commandList = new LinkedList<>();
|
||||
|
||||
commandList.add(String.format("%s/java", pc.javaBinDir));
|
||||
commandList.add(String.format("-Dpf4j.pluginsDir=%s/plugins/", pc.cordaCliBinDir));
|
||||
commandList.add("-jar");
|
||||
commandList.add(String.format("%s/corda-cli.jar", pc.cordaCliBinDir));
|
||||
commandList.add("package");
|
||||
commandList.add("create-cpi");
|
||||
commandList.add("--cpb");
|
||||
commandList.add(appCPBs[0].getAbsolutePath());
|
||||
commandList.add("--group-policy");
|
||||
commandList.add(pc.devEnvWorkspace + "/GroupPolicy.json");
|
||||
commandList.add("--cpi-name");
|
||||
commandList.add(pc.appCPIName);
|
||||
commandList.add("--cpi-version");
|
||||
commandList.add(pc.project.getVersion().toString());
|
||||
commandList.add("--file");
|
||||
commandList.add(appCPIFilePath);
|
||||
commandList.add("--keystore");
|
||||
commandList.add(pc.devEnvWorkspace + "/signingkeys.pfx");
|
||||
commandList.add("--storepass");
|
||||
commandList.add("keystore password");
|
||||
commandList.add("--key");
|
||||
commandList.add("my-signing-key"); // todo: should be passed as context property
|
||||
|
||||
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(commandList);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
|
||||
//Get CPI packaging errors
|
||||
if (proc.getErrorStream().available() > 0) {
|
||||
proc.getErrorStream().transferTo(pc.out);
|
||||
}
|
||||
}
|
||||
|
||||
private void createNotaryCPI() throws CsdeException, IOException, InterruptedException {
|
||||
|
||||
String notaryCPIFilePath = pc.workflowBuildDir + "/" +
|
||||
pc.notaryCPIName.replace(' ', '-').toLowerCase() + "-" +
|
||||
pc.project.getVersion() + ".cpi";
|
||||
|
||||
File notaryCPIFile = new File(notaryCPIFilePath);
|
||||
notaryCPIFile.delete();
|
||||
|
||||
File srcDir = new File(pc.cordaNotaryServiceDir);
|
||||
File[] notaryCPBs = srcDir.listFiles(( x , name ) -> name.endsWith(".cpb") && name.contains(pc.cordaNotaryPluginsVersion));
|
||||
if (notaryCPBs == null) throw new CsdeException("Expecting exactly one notary CPB but no CPB found.");
|
||||
if (notaryCPBs.length != 1) throw new CsdeException("Expecting exactly one notary CPB but more than one found.");
|
||||
|
||||
pc.out.println("notaryCpbs:");
|
||||
pc.out.println(notaryCPBs[0]);
|
||||
|
||||
LinkedList<String> commandList = new LinkedList<>();
|
||||
|
||||
commandList.add(String.format("%s/java", pc.javaBinDir));
|
||||
commandList.add(String.format("-Dpf4j.pluginsDir=%s/plugins/", pc.cordaCliBinDir));
|
||||
commandList.add("-jar");
|
||||
commandList.add(String.format("%s/corda-cli.jar", pc.cordaCliBinDir));
|
||||
commandList.add("package");
|
||||
commandList.add("create-cpi");
|
||||
commandList.add("--cpb");
|
||||
commandList.add(notaryCPBs[0].getAbsolutePath());
|
||||
commandList.add("--group-policy");
|
||||
commandList.add(pc.devEnvWorkspace + "/GroupPolicy.json");
|
||||
commandList.add("--cpi-name");
|
||||
commandList.add(pc.notaryCPIName);
|
||||
commandList.add("--cpi-version");
|
||||
commandList.add(pc.project.getVersion().toString());
|
||||
commandList.add("--file");
|
||||
commandList.add(notaryCPIFilePath);
|
||||
commandList.add("--keystore");
|
||||
commandList.add(pc.devEnvWorkspace + "/signingkeys.pfx");
|
||||
commandList.add("--storepass");
|
||||
commandList.add("keystore password");
|
||||
commandList.add("--key");
|
||||
commandList.add("my-signing-key");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(commandList);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
|
||||
}
|
||||
|
||||
// todo: this might be needed for improved logging
|
||||
private void printCmdArray(LinkedList<String> cmdArray) {
|
||||
for (int i = 0; i < cmdArray.size(); i++) {
|
||||
pc.out.print(cmdArray.get(i) + " ");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import kong.unirest.Unirest;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Manages Bringing corda up, testing for liveness and taking corda down
|
||||
*/
|
||||
// todo: This class needs refactoring, see https://r3-cev.atlassian.net/browse/CORE-11624
|
||||
public class CordaLifeCycleHelper {
|
||||
|
||||
ProjectContext pc;
|
||||
ProjectUtils utils;
|
||||
|
||||
public CordaLifeCycleHelper(ProjectContext _pc) {
|
||||
pc = _pc;
|
||||
utils = new ProjectUtils(pc);
|
||||
Unirest.config().verifySsl(false);
|
||||
}
|
||||
|
||||
public void startCorda() throws IOException, CsdeException {
|
||||
File cordaPIDFile = new File(pc.cordaPidCache);
|
||||
if (cordaPIDFile.exists()) {
|
||||
throw new CsdeException("Cannot start the Combined worker. Cached process ID file " + cordaPIDFile + " existing. Was the combined worker already started?");
|
||||
}
|
||||
PrintStream pidStore = new PrintStream(new FileOutputStream(cordaPIDFile));
|
||||
File combinedWorkerJar = pc.project.getConfigurations().getByName("combinedWorker").getSingleFile();
|
||||
|
||||
// Manual version of the command to start postgres (for reference):
|
||||
// docker run -d --rm -p5432:5432 --name CSDEpostgresql -e POSTGRES_DB=cordacluster -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password postgres:latest
|
||||
|
||||
new ProcessBuilder(
|
||||
"docker",
|
||||
"run", "-d", "--rm",
|
||||
"-p", "5432:5432",
|
||||
"--name", pc.dbContainerName,
|
||||
"-e", "POSTGRES_DB=cordacluster",
|
||||
"-e", "POSTGRES_USER=postgres",
|
||||
"-e", "POSTGRES_PASSWORD=password",
|
||||
"postgres:latest").start();
|
||||
|
||||
// todo: we should poll for readiness not wait 10 seconds, see https://r3-cev.atlassian.net/browse/CORE-11626
|
||||
utils.rpcWait(10000);
|
||||
|
||||
ProcessBuilder procBuild = new ProcessBuilder(pc.javaBinDir + "/java",
|
||||
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005",
|
||||
"-DsecurityMangerEnabled=false",
|
||||
"-Dlog4j.configurationFile=" + pc.project.getRootDir() + "/config/log4j2.xml",
|
||||
"-Dco.paralleluniverse.fibers.verifyInstrumentation=true",
|
||||
"-jar",
|
||||
combinedWorkerJar.toString(),
|
||||
"--instance-id=0",
|
||||
"-mbus.busType=DATABASE",
|
||||
"-spassphrase=password",
|
||||
"-ssalt=salt",
|
||||
"-ddatabase.user=user",
|
||||
"-ddatabase.pass=password",
|
||||
"-ddatabase.jdbc.url=jdbc:postgresql://localhost:5432/cordacluster",
|
||||
"-ddatabase.jdbc.directory="+pc.JDBCDir);
|
||||
|
||||
procBuild.redirectErrorStream(true);
|
||||
Process proc = procBuild.start();
|
||||
pidStore.print(proc.pid());
|
||||
pc.out.println("Corda Process-id="+proc.pid());
|
||||
proc.getInputStream().transferTo(pc.out);
|
||||
|
||||
// todo: we should poll for readiness before completing the startCorda task, see https://r3-cev.atlassian.net/browse/CORE-11625
|
||||
}
|
||||
|
||||
|
||||
public void stopCorda() throws IOException, CsdeException {
|
||||
File cordaPIDFile = new File(pc.cordaPidCache);
|
||||
if(cordaPIDFile.exists()) {
|
||||
Scanner sc = new Scanner(cordaPIDFile);
|
||||
long pid = sc.nextLong();
|
||||
pc.out.println("pid to kill=" + pid);
|
||||
|
||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
new ProcessBuilder("Powershell", "-Command", "Stop-Process", "-Id", Long.toString(pid), "-PassThru").start();
|
||||
} else {
|
||||
new ProcessBuilder("kill", "-9", Long.toString(pid)).start();
|
||||
}
|
||||
|
||||
Process proc = new ProcessBuilder("docker", "stop", pc.dbContainerName).start();
|
||||
|
||||
cordaPIDFile.delete();
|
||||
}
|
||||
else {
|
||||
throw new CsdeException("Cannot stop the Combined worker. Cached process ID file " + pc.cordaPidCache + " missing. Was the combined worker not started?");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import kong.unirest.HttpResponse;
|
||||
import kong.unirest.JsonNode;
|
||||
import kong.unirest.Unirest;
|
||||
import kong.unirest.json.JSONArray;
|
||||
import kong.unirest.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
// todo: This class needs refactoring, see https://r3-cev.atlassian.net/browse/CORE-11624
|
||||
public class CordaStatusQueries {
|
||||
|
||||
ProjectContext pc;
|
||||
|
||||
public CordaStatusQueries(ProjectContext _pc) {
|
||||
pc = _pc;
|
||||
}
|
||||
|
||||
public HttpResponse<JsonNode> getCpiInfo() {
|
||||
Unirest.config().verifySsl(false);
|
||||
return Unirest.get(pc.baseURL + "/api/v1/cpi/")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
}
|
||||
|
||||
public HttpResponse<JsonNode> getVNodeInfo() {
|
||||
Unirest.config().verifySsl(false);
|
||||
return Unirest.get(pc.baseURL + "/api/v1/virtualnode/")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
}
|
||||
|
||||
// cpiName, cpiVersion
|
||||
public void listCPIs() {
|
||||
HttpResponse<JsonNode> cpiResponse = getCpiInfo();
|
||||
|
||||
JSONArray cpisJson = (JSONArray) cpiResponse.getBody().getObject().get("cpis");
|
||||
|
||||
List<List<String>> lines = new LinkedList<>();
|
||||
for (Object o : cpisJson) {
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject idObj = ((JSONObject) o).getJSONObject("id");
|
||||
String cpiName = idObj.get("cpiName").toString();
|
||||
String cpiVersion = idObj.get("cpiVersion").toString();
|
||||
|
||||
lines.add(Arrays.asList(cpiName, cpiVersion));
|
||||
}
|
||||
}
|
||||
List<String> title = Arrays.asList("CPI Name", "CPI Version");
|
||||
List<Integer> titleSizes = Arrays.asList(40, 20);
|
||||
printTable(titleSizes, title, lines);
|
||||
}
|
||||
|
||||
public void listVNodesVerbose() {
|
||||
HttpResponse<JsonNode> vnodeResponse = getVNodeInfo();
|
||||
pc.out.println("VNodes:\n" + vnodeResponse.getBody().toPrettyString());
|
||||
}
|
||||
|
||||
// x500Name, shortHash, cpiName
|
||||
public void listVNodes() {
|
||||
HttpResponse<JsonNode> vnodeResponse = getVNodeInfo();
|
||||
|
||||
JSONArray virtualNodesJson = (JSONArray) vnodeResponse.getBody().getObject().get("virtualNodes");
|
||||
|
||||
List<List<String>> lines = new LinkedList<>();
|
||||
for (Object o : virtualNodesJson) {
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject idObj = ((JSONObject) o).getJSONObject("holdingIdentity");
|
||||
String x500Name = idObj.get("x500Name").toString();
|
||||
String shortHash = idObj.get("shortHash").toString();
|
||||
|
||||
JSONObject cpiObj = ((JSONObject) o).getJSONObject("cpiIdentifier");
|
||||
String cpiName = cpiObj.get("cpiName").toString();
|
||||
|
||||
lines.add(Arrays.asList(x500Name, shortHash, cpiName));
|
||||
}
|
||||
}
|
||||
List<String> title = Arrays.asList("X500 Name", "Holding identity short hash", "CPI Name");
|
||||
List<Integer> titleSizes = Arrays.asList(60, 30, 40);
|
||||
printTable(titleSizes, title, lines);
|
||||
}
|
||||
|
||||
public void printTable(List<Integer> titleSizes, List<String> title, List<List<String>> lines) {
|
||||
int width = titleSizes.stream().reduce(0, Integer::sum);
|
||||
String separator = "-".repeat(width + 1);
|
||||
pc.out.println(separator);
|
||||
pc.out.println(formatLine(titleSizes, title));
|
||||
pc.out.println(separator);
|
||||
for (List<String> line : lines) {
|
||||
pc.out.println(formatLine(titleSizes, line));
|
||||
}
|
||||
pc.out.println(separator);
|
||||
}
|
||||
|
||||
public String formatLine(List<Integer> titleSizes, List<String> line) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int delta = 0;
|
||||
for (int i = 0; i < titleSizes.size(); i++) {
|
||||
String s = line.get(i);
|
||||
sb.append("| ").append(s);
|
||||
delta += titleSizes.get(i) - (2 + s.length());
|
||||
|
||||
if (delta > 0) {
|
||||
sb.append(" ".repeat(delta));
|
||||
delta = 0;
|
||||
} else {
|
||||
sb.append(" ");
|
||||
delta -= 1;
|
||||
}
|
||||
}
|
||||
sb.append("|");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
public class CsdeException extends Exception {
|
||||
public CsdeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public CsdeException(String message){
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import kong.unirest.JsonNode;
|
||||
import kong.unirest.Unirest;
|
||||
import kong.unirest.json.JSONArray;
|
||||
import kong.unirest.json.JSONObject;
|
||||
import kong.unirest.HttpResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
|
||||
// todo: This class needs refactoring, see https://r3-cev.atlassian.net/browse/CORE-11624
|
||||
public class DeployCPIsHelper {
|
||||
|
||||
public DeployCPIsHelper() {
|
||||
}
|
||||
ProjectContext pc;
|
||||
CordaStatusQueries queries;
|
||||
ProjectUtils utils;
|
||||
|
||||
public DeployCPIsHelper(ProjectContext _pc) {
|
||||
pc = _pc;
|
||||
queries = new CordaStatusQueries(pc);
|
||||
utils = new ProjectUtils(pc);
|
||||
}
|
||||
|
||||
public void deployCPIs() throws FileNotFoundException, CsdeException{
|
||||
|
||||
uploadCertificate(pc.signingCertAlias, pc.signingCertFName);
|
||||
uploadCertificate(pc.keystoreAlias, pc.keystoreCertFName);
|
||||
|
||||
// todo: make consistent with other string building code - remove String.format
|
||||
String appCPILocation = String.format("%s/%s-%s.cpi",
|
||||
pc.workflowBuildDir,
|
||||
pc.project.getName(),
|
||||
pc.project.getVersion());
|
||||
deployCPI(appCPILocation, pc.appCPIName,pc.project.getVersion().toString());
|
||||
|
||||
String notaryCPILocation = String.format("%s/%s-%s.cpi",
|
||||
pc.workflowBuildDir,
|
||||
pc.notaryCPIName.replace(' ','-').toLowerCase(),
|
||||
pc.project.getVersion());
|
||||
deployCPI(notaryCPILocation,
|
||||
pc.notaryCPIName,
|
||||
pc.project.getVersion().toString(),
|
||||
"-NotaryServer" );
|
||||
|
||||
}
|
||||
|
||||
public void uploadCertificate(String certAlias, String certFName) {
|
||||
Unirest.config().verifySsl(false);
|
||||
HttpResponse<JsonNode> uploadResponse = Unirest.put(pc.baseURL + "/api/v1/certificates/cluster/code-signer")
|
||||
.field("alias", certAlias)
|
||||
.field("certificate", new File(certFName))
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
pc.out.println("Certificate/key upload, alias "+certAlias+" certificate/key file "+certFName);
|
||||
pc.out.println(uploadResponse.getBody().toPrettyString());
|
||||
}
|
||||
|
||||
public void forceuploadCPI(String cpiFName) throws FileNotFoundException, CsdeException {
|
||||
forceuploadCPI(cpiFName, "");
|
||||
}
|
||||
|
||||
public void forceuploadCPI(String cpiFName, String uploadStatusQualifier) throws FileNotFoundException, CsdeException {
|
||||
Unirest.config().verifySsl(false);
|
||||
HttpResponse<JsonNode> jsonResponse = Unirest.post(pc.baseURL + "/api/v1/maintenance/virtualnode/forcecpiupload/")
|
||||
.field("upload", new File(cpiFName))
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if(jsonResponse.getStatus() == HTTP_OK) {
|
||||
String id = (String) jsonResponse.getBody().getObject().get("id");
|
||||
pc.out.println("get id:\n" +id);
|
||||
HttpResponse<JsonNode> statusResponse = uploadStatus(id);
|
||||
|
||||
if (statusResponse.getStatus() == HTTP_OK) {
|
||||
PrintStream cpiUploadStatus = new PrintStream(new FileOutputStream(
|
||||
pc.CPIUploadStatusFName.replace(".json", uploadStatusQualifier + ".json" )));
|
||||
cpiUploadStatus.print(statusResponse.getBody());
|
||||
pc.out.println("Caching CPI file upload status:\n" + statusResponse.getBody());
|
||||
} else {
|
||||
utils.reportError(statusResponse);
|
||||
}
|
||||
}
|
||||
else {
|
||||
utils.reportError(jsonResponse);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean uploadStatusRetry(HttpResponse<JsonNode> response) {
|
||||
int status = response.getStatus();
|
||||
JsonNode body = response.getBody();
|
||||
// Do not retry on success // todo: need to think through the possible outcomes here - what if the bodyTitle is null, it won't retry
|
||||
if(status == HTTP_OK) {
|
||||
// Keep retrying until we get "OK" may move through "Validating upload", "Persisting CPI"
|
||||
return !(body.getObject().get("status").equals("OK"));
|
||||
}
|
||||
else if (status == HTTP_BAD_REQUEST){
|
||||
String bodyTitle = response.getBody().getObject().getString("title");
|
||||
return bodyTitle != null && bodyTitle.matches("No such requestId=[-0-9a-f]+");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public HttpResponse<JsonNode> uploadStatus(String requestId) {
|
||||
HttpResponse<JsonNode> statusResponse = null;
|
||||
do {
|
||||
utils.rpcWait(1000);
|
||||
statusResponse = Unirest
|
||||
.get(pc.baseURL + "/api/v1/cpi/status/" + requestId + "/")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
pc.out.println("Upload status="+statusResponse.getStatus()+", status query response:\n"+statusResponse.getBody().toPrettyString());
|
||||
}
|
||||
while(uploadStatusRetry(statusResponse));
|
||||
|
||||
return statusResponse;
|
||||
}
|
||||
|
||||
public void deployCPI(String cpiFName, String cpiName, String cpiVersion) throws FileNotFoundException, CsdeException {
|
||||
deployCPI(cpiFName, cpiName, cpiVersion, "");
|
||||
}
|
||||
|
||||
public void deployCPI(String cpiFName,
|
||||
String cpiName,
|
||||
String cpiVersion,
|
||||
String uploadStatusQualifier) throws FileNotFoundException, CsdeException {
|
||||
// todo: where is the primary instance declared?
|
||||
Unirest.config().verifySsl(false);
|
||||
|
||||
HttpResponse<JsonNode> cpiResponse = queries.getCpiInfo();
|
||||
JSONArray jArray = (JSONArray) cpiResponse.getBody().getObject().get("cpis");
|
||||
|
||||
int matches = 0;
|
||||
for(Object o: jArray.toList() ) {
|
||||
if(o instanceof JSONObject) {
|
||||
JSONObject idObj = ((JSONObject) o).getJSONObject("id");
|
||||
if((idObj.get("cpiName").toString().equals(cpiName)
|
||||
&& idObj.get("cpiVersion").toString().equals(cpiVersion))) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pc.out.println("Matching CPIS="+matches);
|
||||
|
||||
if(matches == 0) {
|
||||
HttpResponse<JsonNode> uploadResponse = Unirest.post(pc.baseURL + "/api/v1/cpi/")
|
||||
.field("upload", new File(cpiFName))
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
JsonNode body = uploadResponse.getBody();
|
||||
|
||||
int status = uploadResponse.getStatus();
|
||||
|
||||
pc.out.println("Upload Status:" + status);
|
||||
pc.out.println("Pretty print the body\n" + body.toPrettyString());
|
||||
|
||||
// We expect the id field to be a string.
|
||||
if (status == HTTP_OK) {
|
||||
String id = (String) body.getObject().get("id");
|
||||
pc.out.println("get id:\n" + id);
|
||||
|
||||
HttpResponse<JsonNode> statusResponse = uploadStatus(id);
|
||||
if (statusResponse.getStatus() == HTTP_OK) {
|
||||
PrintStream cpiUploadStatus = new PrintStream(new FileOutputStream(
|
||||
pc.CPIUploadStatusFName.replace(".json", uploadStatusQualifier + ".json" )));
|
||||
cpiUploadStatus.print(statusResponse.getBody());
|
||||
pc.out.println("Caching CPI file upload status:\n" + statusResponse.getBody());
|
||||
} else {
|
||||
utils.reportError(statusResponse);
|
||||
}
|
||||
} else {
|
||||
utils.reportError(uploadResponse);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pc.out.println("CPI already uploaded doing a 'force' upload.");
|
||||
forceuploadCPI(cpiFName, uploadStatusQualifier);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* This class reads the network config from the json file and makes it available as a list of VNodes.
|
||||
*/
|
||||
public class NetworkConfig {
|
||||
|
||||
private List<VNode> vNodes;
|
||||
private String configFilePath;
|
||||
|
||||
public NetworkConfig(String _configFilePath) throws CsdeException {
|
||||
configFilePath = _configFilePath;
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(configFilePath);
|
||||
vNodes = mapper.readValue(in, new TypeReference<List<VNode>>() {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new CsdeException("Failed to read static network configuration file, with exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
String getConfigFilePath() { return configFilePath; }
|
||||
|
||||
List<VNode> getVNodes() { return vNodes; }
|
||||
|
||||
List<String> getX500Names() {
|
||||
return vNodes.stream().map(vn -> vn.getX500Name()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProjectContext {
|
||||
Project project;
|
||||
String baseURL = "https://localhost:8888";
|
||||
String rpcUser = "admin";
|
||||
String rpcPasswd = "admin";
|
||||
String workspaceDir = "workspace";
|
||||
int retryWaitMs = 1000;
|
||||
PrintStream out = System.out;
|
||||
String CPIUploadStatusBaseName = "CPIFileStatus.json";
|
||||
String NotaryCPIUploadBaseName = "CPIFileStatus-NotaryServer.json";
|
||||
String CPIUploadStatusFName;
|
||||
String NotaryCPIUploadStatusFName;
|
||||
String javaBinDir;
|
||||
String cordaPidCache = "CordaPIDCache.dat";
|
||||
String dbContainerName;
|
||||
String JDBCDir;
|
||||
String combinedWorkerBinRe;
|
||||
Map<String, String> notaryRepresentatives = null;
|
||||
String signingCertAlias;
|
||||
String signingCertFName;
|
||||
String keystoreAlias;
|
||||
String keystoreFName;
|
||||
String keystoreCertFName;
|
||||
String appCPIName;
|
||||
String notaryCPIName;
|
||||
String devEnvWorkspace;
|
||||
String cordaCliBinDir;
|
||||
String cordaNotaryServiceDir;
|
||||
String workflowBuildDir;
|
||||
String cordaNotaryPluginsVersion;
|
||||
|
||||
public ProjectContext (Project inProject,
|
||||
String inBaseUrl,
|
||||
String inRpcUser,
|
||||
String inRpcPasswd,
|
||||
String inWorkspaceDir,
|
||||
String inJavaBinDir,
|
||||
String inDbContainerName,
|
||||
String inJDBCDir,
|
||||
String inCordaPidCache,
|
||||
String inSigningCertAlias,
|
||||
String inSigningCertFName,
|
||||
String inKeystoreAlias,
|
||||
String inKeystoreFName,
|
||||
String inKeystoreCertFName,
|
||||
String inAppCPIName,
|
||||
String inNotaryCPIName,
|
||||
String inDevEnvWorkspace,
|
||||
String inCordaCLiBinDir,
|
||||
String inCordaNotaryServiceDir,
|
||||
String inWorkflowBuildDir,
|
||||
String inCordaNotaryPluginsVersion
|
||||
) {
|
||||
project = inProject;
|
||||
baseURL = inBaseUrl;
|
||||
rpcUser = inRpcUser;
|
||||
rpcPasswd = inRpcPasswd;
|
||||
workspaceDir = inWorkspaceDir;
|
||||
javaBinDir = inJavaBinDir;
|
||||
cordaPidCache = inCordaPidCache;
|
||||
dbContainerName = inDbContainerName;
|
||||
JDBCDir = inJDBCDir;
|
||||
CPIUploadStatusFName = workspaceDir + "/" + CPIUploadStatusBaseName;
|
||||
NotaryCPIUploadStatusFName = workspaceDir + "/" + NotaryCPIUploadBaseName;
|
||||
signingCertAlias = inSigningCertAlias;
|
||||
signingCertFName = inSigningCertFName;
|
||||
keystoreAlias = inKeystoreAlias;
|
||||
keystoreFName = inKeystoreFName;
|
||||
keystoreCertFName = inKeystoreCertFName;
|
||||
appCPIName = inAppCPIName;
|
||||
notaryCPIName = inNotaryCPIName;
|
||||
devEnvWorkspace = inDevEnvWorkspace;
|
||||
cordaCliBinDir = inCordaCLiBinDir;
|
||||
cordaNotaryServiceDir = inCordaNotaryServiceDir;
|
||||
workflowBuildDir = inWorkflowBuildDir;
|
||||
cordaNotaryPluginsVersion = inCordaNotaryPluginsVersion;
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import kong.unirest.HttpResponse;
|
||||
import kong.unirest.JsonNode;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
// todo: This class needs refactoring, see https://r3-cev.atlassian.net/browse/CORE-11624
|
||||
public class ProjectUtils {
|
||||
|
||||
ProjectContext pc;
|
||||
|
||||
ProjectUtils(ProjectContext _pc) {
|
||||
pc = _pc;
|
||||
}
|
||||
|
||||
void rpcWait(int millis) {
|
||||
try {
|
||||
sleep(millis);
|
||||
}
|
||||
catch(InterruptedException e) {
|
||||
throw new UnsupportedOperationException("Interrupts not supported.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void reportError(HttpResponse<JsonNode> response) throws CsdeException {
|
||||
|
||||
pc.out.println("*** *** ***");
|
||||
pc.out.println("Unexpected response from Corda");
|
||||
pc.out.println("Status="+ response.getStatus());
|
||||
pc.out.println("*** Headers ***\n"+ response.getHeaders());
|
||||
pc.out.println("*** Body ***\n"+ response.getBody());
|
||||
pc.out.println("*** *** ***");
|
||||
throw new CsdeException("Error: unexpected response from Corda.");
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
|
||||
/**
|
||||
* This class is a representation of a Vnode used to express the vNodes required on the network.
|
||||
*/
|
||||
|
||||
public class VNode {
|
||||
private String x500Name;
|
||||
private String cpi;
|
||||
|
||||
private String serviceX500Name;
|
||||
|
||||
public VNode() { }
|
||||
|
||||
public String getX500Name(){ return x500Name; }
|
||||
public void setX500Name(String _x500Name) { x500Name = _x500Name; }
|
||||
|
||||
public String getCpi() { return cpi; }
|
||||
public void setCpi(String _cpi) { cpi = _cpi; }
|
||||
|
||||
public String getServiceX500Name() { return serviceX500Name; }
|
||||
public void setServiceX500Name(String _name) { serviceX500Name = _name; }
|
||||
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
package com.r3.csde;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r3.csde.dtos.*;
|
||||
import kong.unirest.HttpResponse;
|
||||
import kong.unirest.JsonNode;
|
||||
import kong.unirest.Unirest;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
|
||||
/**
|
||||
* The VNodesHelper class is used to create and register the Vnodes specified in the static-network-config.json file.
|
||||
*/
|
||||
|
||||
public class VNodesHelper {
|
||||
private ProjectContext pc;
|
||||
private ProjectUtils utils;
|
||||
private NetworkConfig config;
|
||||
private ObjectMapper mapper;
|
||||
|
||||
public VNodesHelper(ProjectContext _pc, NetworkConfig _config) {
|
||||
pc = _pc;
|
||||
utils = new ProjectUtils(pc);
|
||||
config = _config;
|
||||
Unirest.config().verifySsl(false);
|
||||
mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for setting up vnodes, called from the 5-vNodeSetup task in csde.gradle
|
||||
*/
|
||||
public void vNodesSetup() throws CsdeException {
|
||||
List<VNode> requiredNodes = config.getVNodes();
|
||||
createVNodes(requiredNodes);
|
||||
registerVNodes(requiredNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates vnodes specified in the config if they don't already exist.
|
||||
* @param requiredNodes represents the list of VNodes as specified in the network Config json file (static-network-config.json)
|
||||
*/
|
||||
private void createVNodes(List<VNode> requiredNodes) throws CsdeException {
|
||||
|
||||
// Get existing Nodes.
|
||||
List<VirtualNodeInfoDTO> existingVNodes = getExistingNodes();
|
||||
|
||||
// Check if each required vnode already exist, if not create it.
|
||||
for (VNode vn : requiredNodes) {
|
||||
// Match on x500 and cpi name
|
||||
List<VirtualNodeInfoDTO> matches = existingVNodes
|
||||
.stream()
|
||||
.filter(existing ->
|
||||
existing.getHoldingIdentity().getX500Name().equals( vn.getX500Name()) &&
|
||||
existing.getCpiIdentifier().getCpiName().equals(vn.getCpi()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (matches.size() == 0) {
|
||||
createVNode(vn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of the virtual nodes which have already been created.
|
||||
* @return a list of the virtual nodes which have already been created.
|
||||
*/
|
||||
private List<VirtualNodeInfoDTO> getExistingNodes () throws CsdeException {
|
||||
|
||||
HttpResponse<JsonNode> response = Unirest.get(pc.baseURL + "/api/v1/virtualnode")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if (response.getStatus() != HTTP_OK) {
|
||||
throw new CsdeException("Failed to get Existing vNodes, response status: "+ response.getStatus());
|
||||
}
|
||||
|
||||
try {
|
||||
return mapper.readValue(response.getBody().toString(), VirtualNodesDTO.class).getVirtualNodes();
|
||||
} catch (Exception e){
|
||||
throw new CsdeException("Failed to get Existing vNodes with exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a vnode on the Corda cluster from the VNode info.
|
||||
* @param vNode represents a virtual node using VNode Class.
|
||||
*/
|
||||
private void createVNode(VNode vNode) throws CsdeException {
|
||||
|
||||
pc.out.println("Creating virtual node for "+ vNode.getX500Name());
|
||||
|
||||
// Reads the current CPIFileChecksum value and checks it has been uploaded.
|
||||
String cpiCheckSum = getCpiCheckSum(vNode);
|
||||
if (!checkCpiUploaded(cpiCheckSum)) throw new CsdeException("Cpi " + cpiCheckSum + " not uploaded.");
|
||||
|
||||
// Creates the vnode on Cluster
|
||||
HttpResponse<JsonNode> response = Unirest.post(pc.baseURL + "/api/v1/virtualnode")
|
||||
.body("{ \"request\" : { \"cpiFileChecksum\": \"" + cpiCheckSum + "\", \"x500Name\": \"" + vNode.getX500Name() + "\" } }")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if (response.getStatus() != HTTP_OK) {
|
||||
throw new CsdeException("Creation of virtual node failed with response status: " + response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the latest CPI checksums from file.
|
||||
* @param vNode represents a virtual node using VNode Class.
|
||||
*/
|
||||
private String getCpiCheckSum(VNode vNode) throws CsdeException {
|
||||
|
||||
try {
|
||||
String file = (vNode.getServiceX500Name() == null) ? pc.CPIUploadStatusFName : pc.NotaryCPIUploadStatusFName;
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
CPIFileStatusDTO statusDTO = mapper.readValue(in, CPIFileStatusDTO.class);
|
||||
return statusDTO.getCpiFileChecksum().toString();
|
||||
} catch (Exception e) {
|
||||
throw new CsdeException("Failed to read CPI checksum from file, with error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkCpiUploaded(String cpiCheckSum) throws CsdeException {
|
||||
|
||||
HttpResponse<JsonNode> response = Unirest.get(pc.baseURL + "/api/v1/cpi")
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if (response.getStatus() != HTTP_OK) {
|
||||
throw new CsdeException("Failed to check cpis, response status: " + response.getStatus());
|
||||
}
|
||||
|
||||
try {
|
||||
GetCPIsResponseDTO cpisResponse = mapper.readValue(
|
||||
response.getBody().toString(), GetCPIsResponseDTO.class);
|
||||
|
||||
for (CpiMetadataDTO cpi: cpisResponse.getCpis()) {
|
||||
if (Objects.equals(cpi.getCpiFileChecksum(), cpiCheckSum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Returns false if no cpis were returned or the cpiCheckSum didnt' match ay results.
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
throw new CsdeException("Failed to check cpis with exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the required virtual nodes have been registered and if not registers them.
|
||||
* @param requiredNodes represents the list of VNodes as specified in the network Config json file (static-network-config.json)
|
||||
*/
|
||||
private void registerVNodes(List<VNode> requiredNodes) throws CsdeException {
|
||||
|
||||
// There appears to be a delay between the successful post /virtualnodes synchronous call and the
|
||||
// vnodes being returned in the GET /virtualnodes call. Putting a thread wait here as a quick fix
|
||||
// as this will move to async mechanism post beta2.
|
||||
utils.rpcWait(2000);
|
||||
List<VirtualNodeInfoDTO> existingVNodes = getExistingNodes();
|
||||
|
||||
for (VNode vn: requiredNodes) {
|
||||
// Match on x500 and cpi name
|
||||
List<VirtualNodeInfoDTO> matches = existingVNodes
|
||||
.stream()
|
||||
.filter(existing ->
|
||||
existing.getHoldingIdentity().getX500Name().equals( vn.getX500Name()) &&
|
||||
existing.getCpiIdentifier().getCpiName().equals(vn.getCpi()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (matches.size() == 0) {
|
||||
throw new CsdeException("Registration failed because virtual node for '" + vn.getX500Name() + "' not found.");
|
||||
} else if (matches.size() >1 ) {
|
||||
throw new CsdeException(("Registration failed because more than virtual node for '" + vn.getX500Name() + "'"));
|
||||
}
|
||||
|
||||
String shortHash = matches.get(0).getHoldingIdentity().getShortHash();
|
||||
|
||||
if (!checkVNodeIsRegistered(shortHash)) {
|
||||
registerVnode(vn, shortHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a virtual node.
|
||||
* @param vnode represents the vnode to be registered.
|
||||
* @param shortHash the shortHash of the virtual node to register.
|
||||
*/
|
||||
private void registerVnode(VNode vnode, String shortHash) throws CsdeException {
|
||||
|
||||
pc.out.println("Registering vNode: " + vnode.getX500Name() + " with shortHash: " + shortHash);
|
||||
|
||||
// Configure the registration body (notary vs non notary)
|
||||
String registrationBody;
|
||||
if (vnode.getServiceX500Name() == null) {
|
||||
registrationBody =
|
||||
"{ \"action\" : \"requestJoin\"," +
|
||||
" \"context\" : {" +
|
||||
" \"corda.key.scheme\" : \"CORDA.ECDSA.SECP256R1\" } }";
|
||||
} else {
|
||||
registrationBody =
|
||||
"{ \"action\" : \"requestJoin\"," +
|
||||
" \"context\" : {" +
|
||||
" \"corda.key.scheme\" : \"CORDA.ECDSA.SECP256R1\", " +
|
||||
" \"corda.roles.0\" : \"notary\", " +
|
||||
" \"corda.notary.service.name\" : \"" + vnode.getServiceX500Name() + "\", " +
|
||||
" \"corda.notary.service.plugin\" : \"net.corda.notary.NonValidatingNotary\" } }";
|
||||
}
|
||||
|
||||
HttpResponse<JsonNode> response = Unirest.post(pc.baseURL + "/api/v1/membership/" + shortHash)
|
||||
.body(registrationBody)
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if (response.getStatus() == HTTP_OK) {
|
||||
pc.out.println("Membership requested for node " + shortHash);
|
||||
} else {
|
||||
throw new CsdeException("Failed to register virtual node " + shortHash + ", response status: " + response.getStatus() );
|
||||
}
|
||||
|
||||
// wait until Vnode registered
|
||||
pollForRegistration(shortHash, 30000, 1000);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a virtual node with given shortHash has been registered
|
||||
* @param shortHash shortHash of the node which is being checked.
|
||||
* @return returns true if the vnode is registered
|
||||
*/
|
||||
private boolean checkVNodeIsRegistered(String shortHash) throws CsdeException {
|
||||
|
||||
// Queries registration status for vnode.
|
||||
HttpResponse<JsonNode> response = Unirest.get(pc.baseURL + "/api/v1/membership/" + shortHash)
|
||||
.basicAuth(pc.rpcUser, pc.rpcPasswd)
|
||||
.asJson();
|
||||
|
||||
if (response.getStatus() != HTTP_OK)
|
||||
throw new CsdeException("Failed to check registration status for virtual node '" + shortHash +
|
||||
"' response status: " + response.getStatus());
|
||||
|
||||
try {
|
||||
// If the response body is not empty check all previous requests for an "APPROVED"
|
||||
if (!response.getBody().getArray().isEmpty()) {
|
||||
List<RegistrationRequestProgressDTO> requests = mapper.readValue(
|
||||
response.getBody().toString(), new TypeReference<>() {
|
||||
});
|
||||
for (RegistrationRequestProgressDTO request : requests) {
|
||||
if (Objects.equals(request.getRegistrationStatus(), "APPROVED")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Returns false if array was empty or "APPROVED" wasn't found
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new CsdeException("Failed to check registration status for " + shortHash +
|
||||
" with exception " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls for registration of a vnode
|
||||
* @param shortHash short hash of the node which is being poled for
|
||||
* @param duration the number of milliseconds before the pollign times out
|
||||
* @param cooldown the number of milliseconds in between poll attempts.
|
||||
*/
|
||||
private void pollForRegistration(String shortHash, int duration, int cooldown) throws CsdeException {
|
||||
|
||||
int timer = 0;
|
||||
while (timer < duration ) {
|
||||
if (checkVNodeIsRegistered(shortHash)){
|
||||
pc.out.println("Vnode " + shortHash +" registered.");
|
||||
return;
|
||||
}
|
||||
utils.rpcWait(cooldown);
|
||||
timer += cooldown;
|
||||
}
|
||||
throw new CsdeException("Vnode " + shortHash + " failed to register in " + duration + " milliseconds");
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class CPIFileStatusDTO {
|
||||
private String status;
|
||||
private String cpiFileChecksum;
|
||||
|
||||
public CPIFileStatusDTO() {}
|
||||
|
||||
public String getStatus() { return status; }
|
||||
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
|
||||
public String getCpiFileChecksum() { return cpiFileChecksum; }
|
||||
|
||||
public void setCpiFileChecksum(String cpiFileChecksum) { this.cpiFileChecksum = cpiFileChecksum; }
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class CpiIdentifierDTO {
|
||||
|
||||
// Note, these DTOs don't cover all returned values, just the ones required for CSDE
|
||||
private String cpiName;
|
||||
private String cpiVersion;
|
||||
private String signerSummaryHash;
|
||||
|
||||
public CpiIdentifierDTO() { }
|
||||
|
||||
public String getCpiName() { return cpiName; }
|
||||
|
||||
public void setCpiName(String cpiName) { this.cpiName = cpiName; }
|
||||
|
||||
public String getCpiVersion() { return cpiVersion; }
|
||||
|
||||
public void setCpiVersion(String cpiVersion) { this.cpiVersion = cpiVersion; }
|
||||
|
||||
public String getSignerSummaryHash() { return signerSummaryHash; }
|
||||
|
||||
public void setSignerSummaryHash(String signerSummaryHash) { this.signerSummaryHash = signerSummaryHash; }
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class CpiMetadataDTO {
|
||||
// Note, these DTOs don't cover all returned values, just the ones required for CSDE.
|
||||
private String cpiFileChecksum;
|
||||
private CpiIdentifierDTO id;
|
||||
|
||||
public CpiMetadataDTO() {}
|
||||
|
||||
public String getCpiFileChecksum() { return cpiFileChecksum; }
|
||||
|
||||
public void setCpiFileChecksum(String cpiFileChecksum) { this.cpiFileChecksum = cpiFileChecksum; }
|
||||
|
||||
public CpiIdentifierDTO getId() { return id; }
|
||||
|
||||
public void setId(CpiIdentifierDTO id) { this.id = id; }
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GetCPIsResponseDTO {
|
||||
|
||||
private List<CpiMetadataDTO> cpis;
|
||||
|
||||
public GetCPIsResponseDTO() {}
|
||||
|
||||
public List<CpiMetadataDTO> getCpis() { return cpis; }
|
||||
|
||||
public void setCpis(List<CpiMetadataDTO> cpis) { this.cpis = cpis; }
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class HoldingIdentityDTO {
|
||||
// Note, these DTOs don't cover all returned values, just the ones required for CSDE.
|
||||
private String fullHash;
|
||||
private String groupId;
|
||||
private String shortHash;
|
||||
private String x500Name;
|
||||
|
||||
public HoldingIdentityDTO() {}
|
||||
|
||||
public String getFullHash() { return fullHash; }
|
||||
|
||||
public void setFullHash(String fullHash) { this.fullHash = fullHash; }
|
||||
|
||||
public String getGroupId() { return groupId; }
|
||||
|
||||
public void setGroupID(String groupID) { this.groupId = groupId; }
|
||||
|
||||
public String getShortHash() { return shortHash; }
|
||||
|
||||
public void setShortHash(String shortHash) { this.shortHash = shortHash; }
|
||||
|
||||
public String getX500Name() { return x500Name; }
|
||||
|
||||
public void setX500Name(String x500Name) { this.x500Name = x500Name; }
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class RegistrationRequestProgressDTO {
|
||||
// Note, these DTOs don't cover all returned values, just the ones required for CSDE.
|
||||
private String registrationStatus;
|
||||
private String reason;
|
||||
|
||||
public RegistrationRequestProgressDTO() {}
|
||||
|
||||
public String getRegistrationStatus() { return registrationStatus; }
|
||||
|
||||
public void setRegistrationStatus(String registrationStatus) { this.registrationStatus = registrationStatus; }
|
||||
|
||||
public String getReason() { return reason; }
|
||||
|
||||
public void setReason(String reason) { this.reason = reason; }
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
public class VirtualNodeInfoDTO {
|
||||
// Note, these DTOs don't cover all returned values, just the ones required for CSDE.
|
||||
private HoldingIdentityDTO holdingIdentity;
|
||||
private CpiIdentifierDTO cpiIdentifier;
|
||||
|
||||
public VirtualNodeInfoDTO() {}
|
||||
|
||||
public HoldingIdentityDTO getHoldingIdentity() { return holdingIdentity; }
|
||||
|
||||
public void setHoldingIdentity(HoldingIdentityDTO holdingIdentity) { this.holdingIdentity = holdingIdentity; }
|
||||
|
||||
public CpiIdentifierDTO getCpiIdentifier() { return cpiIdentifier; }
|
||||
|
||||
public void setCpiIdentifier(CpiIdentifierDTO cpiIdentifier) { this.cpiIdentifier = cpiIdentifier; }
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.r3.csde.dtos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VirtualNodesDTO {
|
||||
|
||||
private List<VirtualNodeInfoDTO> virtualNodes;
|
||||
|
||||
public VirtualNodesDTO() {}
|
||||
|
||||
public List<VirtualNodeInfoDTO> getVirtualNodes() { return virtualNodes; }
|
||||
|
||||
public void setVirtualNodes(List<VirtualNodeInfoDTO> virtualNodes) { this.virtualNodes = virtualNodes; }
|
||||
}
|
@ -1,23 +1,23 @@
|
||||
[
|
||||
{
|
||||
"x500Name" : "CN=Alice, OU=Test Dept, O=R3, L=London, C=GB",
|
||||
"cpi" : "cpi name"
|
||||
"cpi" : "MyCorDapp"
|
||||
},
|
||||
{
|
||||
"x500Name" : "CN=Bob, OU=Test Dept, O=R3, L=London, C=GB",
|
||||
"cpi" : "cpi name"
|
||||
"cpi" : "MyCorDapp"
|
||||
},
|
||||
{
|
||||
"x500Name" : "CN=Charlie, OU=Test Dept, O=R3, L=London, C=GB",
|
||||
"cpi" : "cpi name"
|
||||
"cpi" : "MyCorDapp"
|
||||
},
|
||||
{
|
||||
"x500Name" : "CN=Dave, OU=Test Dept, O=R3, L=London, C=GB",
|
||||
"cpi" : "cpi name"
|
||||
"cpi" : "MyCorDapp"
|
||||
},
|
||||
{
|
||||
"x500Name" : "CN=NotaryRep1, OU=Test Dept, O=R3, L=London, C=GB",
|
||||
"cpi" : "CSDE Notary Server CPI",
|
||||
"cpi" : "NotaryServer",
|
||||
"serviceX500Name": "CN=NotaryService, OU=Test Dept, O=R3, L=London, C=GB"
|
||||
}
|
||||
]
|
||||
|
@ -4,10 +4,6 @@ kotlin.code.style=official
|
||||
# This needs to match the version supported by the Corda Cluster the CorDapp will run on.
|
||||
cordaApiVersion=5.0.0.665-Gecko1.0
|
||||
|
||||
# Settings For Development Utilities
|
||||
combinedWorkerVersion=5.0.0.0-Gecko1.0
|
||||
simulatorVersion=5.0.0.0-Gecko1.0
|
||||
|
||||
# Specify the version of the notary plugins to use.
|
||||
# Currently packaged as part of corda-runtime-os, so should be set to a corda-runtime-os version.
|
||||
cordaNotaryPluginsVersion=5.0.0.0-Gecko1.0
|
||||
@ -15,6 +11,9 @@ cordaNotaryPluginsVersion=5.0.0.0-Gecko1.0
|
||||
# Specify the version of the cordapp-cpb and cordapp-cpk plugins
|
||||
cordaPluginsVersion=7.0.1
|
||||
|
||||
# Specify the version of the CSDE gradle plugin to use
|
||||
csdePluginVersion=1.0.+
|
||||
|
||||
# For the time being this just needs to be set to a dummy value.
|
||||
platformVersion = 999
|
||||
|
||||
@ -31,15 +30,7 @@ mockitoKotlinVersion=4.0.0
|
||||
mockitoVersion=4.6.1
|
||||
hamcrestVersion=2.2
|
||||
|
||||
postgresqlVersion=42.4.3
|
||||
|
||||
cordaClusterURL=https://localhost:8888
|
||||
cordaRpcUser=admin
|
||||
cordaRpcPasswd=admin
|
||||
devEnvWorkspace=workspace
|
||||
dbContainerName=CSDEpostgresql
|
||||
|
||||
# R3 internal repository
|
||||
#S3 version for HC and RC versions published by CD/CD team
|
||||
artifactoryContextUrl=https://staging.download.corda.net/maven/20ede3c6-29c0-11ed-966d-b7c36748b9f6-Gecko-RC03/
|
||||
#artifactoryContextUrl=https://staging.download.corda.net/maven/20ede3c6-29c0-11ed-966d-b7c36748b9f6-Gecko-RC02/
|
||||
# Use this version when pointing to artefacts in artifactory that have not been published to S3
|
||||
artifactoryContextUrl=https://software.r3.com/artifactory
|
@ -3,8 +3,16 @@ pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
url = "$artifactoryContextUrl/"
|
||||
url = "$artifactoryContextUrl/corda-os-maven"
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
username = settings.ext.find('cordaArtifactoryUsername') ?: System.getenv('CORDA_ARTIFACTORY_USERNAME')
|
||||
password = settings.ext.find('cordaArtifactoryPassword') ?: System.getenv('CORDA_ARTIFACTORY_PASSWORD')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +22,7 @@ pluginManagement {
|
||||
id 'net.corda.plugins.cordapp-cpk2' version cordaPluginsVersion
|
||||
id 'net.corda.plugins.cordapp-cpb2' version cordaPluginsVersion
|
||||
id 'net.corda.cordapp.cordapp-configuration' version cordaApiVersion
|
||||
id 'net.corda.plugins.csde' version csdePluginVersion
|
||||
id 'org.jetbrains.kotlin.jvm' version kotlinVersion
|
||||
id 'org.jetbrains.kotlin.plugin.jpa' version kotlinVersion
|
||||
id 'org.jetbrains.kotlin.plugin.allopen' version kotlinVersion
|
||||
|
Loading…
Reference in New Issue
Block a user