diff --git a/tools/docker/corda-all-in-one/README.md b/tools/docker/corda-all-in-one/README.md index 3890bb6467..7ba5dd1331 100644 --- a/tools/docker/corda-all-in-one/README.md +++ b/tools/docker/corda-all-in-one/README.md @@ -48,6 +48,21 @@ DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_8-flowdb docker run --rm --privileged caio48-flowdb ``` +# cactus-corda-4-12-all-in-one + +> This docker image is for `testing` and `development` only. +> Do NOT use in production! + +## Usage + +### Build and Run Image Locally + +```sh +DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_12/ -f ./tools/docker/corda-all-in-one/corda-v4_12/Dockerfile -t caio412 +docker run --rm --privileged caio412 +``` + + # cactus-corda-5-all-in-one-solar > This docker image is for `testing` and `development` only. diff --git a/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile b/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile new file mode 100644 index 0000000000..893dba2c2e --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile @@ -0,0 +1,118 @@ +FROM ubuntu:22.04 as builder + +RUN apt update && apt install openjdk-17-jdk git curl augeas-tools -y +WORKDIR /opt/ +RUN git clone https://github.com/corda/corda.git +WORKDIR /opt/corda/ + +# commit c7514e1c603c077b49987fd79bd77060612967ed (HEAD -> release/os/4.12, upstream/release/os/4.12) +# Author: Chris Cochrane <78791827+chriscochrane@users.noreply.github.com> +# Date: Wed Feb 7 14:46:18 2024 +0000 +# +# ENT-11443 Function sig changes to support removing enterprise compiler warnings (#7671) +RUN git switch release/os/4.12 +RUN git checkout c7514e1c603c077b49987fd79bd77060612967ed +RUN ./gradlew jar -x test + +FROM ubuntu:22.04 + +RUN apt update && apt install openjdk-17-jdk supervisor openssh-server sudo git curl iputils-ping netcat augeas-tools -y + +RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 test + +RUN echo 'root:root' | chpasswd + +RUN mkdir /var/run/sshd + +ARG CORDA_TOOLS_SHELL_CLI_VERSION=4.8.11 + +WORKDIR / + +ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus +RUN mkdir -p $CACTUS_CFG_PATH + +RUN curl https://download.corda.net/maven/corda-releases/net/corda/corda-tools-shell-cli/${CORDA_TOOLS_SHELL_CLI_VERSION}/corda-tools-shell-cli-${CORDA_TOOLS_SHELL_CLI_VERSION}-all.jar --output /corda-tools-shell-cli-all.jar +# Make the "corda-shell" alias avaialble on the terminal +RUN java -jar /corda-tools-shell-cli-all.jar install-shell-extensions + +# The image has a bleeding edge version of corda baked in for testing conveniece +RUN mkdir -p /opt/bin/ +COPY --from=builder /opt/corda/node/capsule/build/libs/corda-4.12-SNAPSHOT.jar /opt/bin/corda.jar + +RUN git clone https://github.com/corda/samples-kotlin.git +WORKDIR /samples-kotlin + +ARG SAMPLES_KOTLIN_SHA=219750f8da2fd491c3b55c8eea821b1f345fef7d +ARG SAMPLES_KOTLIN_BRANCH=arshadm/ent-6914-upgrade-kotlin19-jdk17 + +RUN git switch ${SAMPLES_KOTLIN_BRANCH} +RUN git checkout ${SAMPLES_KOTLIN_SHA} + +ARG SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH="./Advanced/negotiation-cordapp/" +WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH} + +COPY ./negotiation-cordapp/build.gradle /samples-kotlin/Advanced/negotiation-cordapp/build.gradle + +RUN ./gradlew build deployNodes + +WORKDIR / + +# Configure the OpenSSH server we just installed +RUN augtool 'set /files/etc/ssh/sshd_config/AuthorizedKeysFile ".ssh/authorized_keys /etc/authorized_keys/%u"' && \ + augtool 'set /files/etc/ssh/sshd_config/PermitRootLogin yes' && \ + augtool 'set /files/etc/ssh/sshd_config/PasswordAuthentication yes' && \ + augtool 'set /files/etc/ssh/sshd_config/PermitEmptyPasswords yes' && \ + augtool 'set /files/etc/ssh/sshd_config/Port 22' && \ + augtool 'set /files/etc/ssh/sshd_config/LogLevel DEBUG2' && \ + augtool 'set /files/etc/ssh/sshd_config/LoginGraceTime 10' + +# Create the server's key - without this sshd will refuse to start +RUN ssh-keygen -A + +# Generate an RSA keypair on the fly to avoid having to hardcode one in the image +# which technically does not pose a security threat since this is only a development +# image, but we do it like this anyway. +RUN mkdir ~/.ssh && \ + chmod 700 ~/.ssh/ && \ + touch ~/.ssh/authorized_keys + +RUN ["/bin/bash", "-c", "ssh-keygen -t rsa -N '' -f $CACTUS_CFG_PATH/corda-aio-image"] +RUN mv $CACTUS_CFG_PATH/corda-aio-image $CACTUS_CFG_PATH/corda-aio-image.key +RUN cp $CACTUS_CFG_PATH/corda-aio-image.pub ~/.ssh/authorized_keys + +WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH} + +# OpenSSH server +EXPOSE 22 + +# supervisord web ui/dashboard +EXPOSE 9001 + +# Party Notary, Party A, Party B RPC ports +EXPOSE 10003 10006 10009 + +# Jolokia for Party A,B,C and Notary +EXPOSE 7005 7006 7007 7008 + +# JVM remote debug port +EXPOSE 5005 5006 5008 + +COPY supervisord.conf /etc/supervisord.conf +COPY run-party-b-node.sh run-notary-node.sh healthcheck.sh run-party-a-node.sh / +COPY ./negotiation-cordapp/log4j2.xml /samples-kotlin/Advanced/negotiation-cordapp/config/dev/log4j2.xml + +# By default we only run the absolute minimum which is a single partys node. +# For more complex tests everything else can also be enabled via the env vars +# below so that if needed there is 2 parties, a notary and a dedicated web server +# for all 3 of those nodes. +# "Web server" => the same one as in the official corda samples-kotlin repo +ENV PARTY_A_NODE_ENABLED="true" + +ENV PARTY_B_NODE_ENABLED="true" + +ENV NOTARY_NODE_ENABLED="true" + +ENTRYPOINT ["/usr/bin/supervisord"] +CMD ["--configuration", "/etc/supervisord.conf", "--nodaemon"] + +HEALTHCHECK --interval=1s --timeout=5s --start-period=5s --retries=120 CMD /healthcheck.sh diff --git a/tools/docker/corda-all-in-one/corda-v4_12/healthcheck.sh b/tools/docker/corda-all-in-one/corda-v4_12/healthcheck.sh new file mode 100755 index 0000000000..96b8975722 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/healthcheck.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +if [ "$PARTY_A_WEB_SRV_ENABLED" = "true" ] +then + curl -vv -i -X OPTIONS http://127.0.0.1:10009/web/iou/ +fi + +if [ "$PARTY_B_WEB_SRV_ENABLED" = "true" ] +then + curl -vv -i -X OPTIONS http://127.0.0.1:10012/web/iou/ +fi + + +if [ "$PARTY_A_NODE_ENABLED" = "true" ] +then + curl -v 'http://localhost:7005/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/' +fi + +if [ "$PARTY_B_NODE_ENABLED" = "true" ] +then + curl -v 'http://localhost:7006/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/' +fi + +curl -v 'http://localhost:7008/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/' diff --git a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle new file mode 100644 index 0000000000..70235fb10a --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle @@ -0,0 +1,161 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +import static org.gradle.api.JavaVersion.VERSION_17 +import static org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 +import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8 + +buildscript { //properties that you need to build the project + + Properties constants = new Properties() + file("$projectDir/../constants.properties").withInputStream { constants.load(it) } + + ext { + corda_release_group = constants.getProperty("cordaReleaseGroup") + corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup") + corda_release_version = constants.getProperty("cordaVersion") + corda_shell_version = corda_release_version + corda_core_release_version = constants.getProperty("cordaCoreVersion") + corda_gradle_plugins_version = constants.getProperty("gradlePluginsVersion") + kotlin_version = constants.getProperty("kotlinVersion") + junit_version = constants.getProperty("junitVersion") + quasar_version = constants.getProperty("quasarVersion") + log4j_version = constants.getProperty("log4jVersion") + slf4j_version = constants.getProperty("slf4jVersion") + corda_platform_version = constants.getProperty("platformVersion").toInteger() + rxjava_version = constants.getProperty("rxJavaVersion") + snappy_version = constants.getProperty("snappyVersion") + //springboot + spring_boot_version = '2.0.2.RELEASE' + spring_boot_gradle_plugin_version = '2.0.2.RELEASE' + + testJvmArgs = ['--add-opens', 'java.base/java.time=ALL-UNNAMED', '--add-opens', 'java.base/java.io=ALL-UNNAMED', + '--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.net=ALL-UNNAMED', + '--add-opens', 'java.base/java.nio=ALL-UNNAMED', '--add-opens', 'java.base/java.lang.invoke=ALL-UNNAMED', + '--add-opens', 'java.base/java.security.cert=ALL-UNNAMED', '--add-opens', 'java.base/java.security=ALL-UNNAMED', + '--add-opens', 'java.base/javax.net.ssl=ALL-UNNAMED', '--add-opens', 'java.base/java.lang=ALL-UNNAMED', + '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', '--add-opens', 'java.sql/java.sql=ALL-UNNAMED',] + testJvmFxArgs = [ '--add-exports', 'java.base/sun.nio.ch=ALL-UNNAMED', + '--add-exports', 'javafx.base/com.sun.javafx=ALL-UNNAMED', + '--add-exports', 'javafx.base/com.sun.javafx.collections=ALL-UNNAMED'] + } + + repositories { + mavenLocal() + mavenCentral() + + maven { url 'https://download.corda.net/maven/corda-releases' } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version" + classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version" + classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version" + classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_gradle_plugin_version" + } +} + +allprojects { //Properties that you need to compile your project (The application) + apply from: "${rootProject.projectDir}/repositories.gradle" + apply plugin: 'org.jetbrains.kotlin.jvm' + + repositories { + mavenLocal() + maven { url 'https://download.corda.net/maven/corda-releases' } + mavenCentral() + maven { url 'https://download.corda.net/maven/corda-dependencies' } + maven { url 'https://jitpack.io' } + } + + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + compilerOptions { + languageVersion = KOTLIN_1_8 + apiVersion = KOTLIN_1_8 + jvmTarget = JVM_17 + javaParameters = true // Useful for reflection. + freeCompilerArgs = ['-Xjvm-default=all-compatibility'] + allWarningsAsErrors = true + } + } + + jar { + // This makes the JAR's SHA-256 hash repeatable. + preserveFileTimestamps = false + reproducibleFileOrder = true + } +} + +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.cordformation' +apply plugin: 'net.corda.plugins.quasar-utils' + +sourceSets { + main { + resources { + srcDir rootProject.file("config/dev") + } + } +} + +//Module dependencis +dependencies { + // Corda dependencies. + cordaProvided "$corda_release_group:corda-core:$corda_release_version" + cordaBootstrapper("$corda_release_group:corda-node-api:$corda_release_version") { + exclude group: "ch.qos.logback", module: "logback-classic" + } + corda "$corda_release_group:corda:$corda_release_version" + + // CorDapp dependencies. + cordapp("$corda_release_group:corda-finance-contracts:$corda_release_version") + cordapp("$corda_release_group:corda-finance-workflows:$corda_release_version") + cordapp project(":workflows") + cordapp project(":contracts") + + cordaProvided "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" + cordaProvided "org.apache.logging.log4j:log4j-web:${log4j_version}" + cordaProvided "org.slf4j:jul-to-slf4j:$slf4j_version" + cordaDriver "net.corda:corda-shell:$corda_shell_version" +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() +} + + +task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { + nodeDefaults { + + cordapp project(':contracts') + cordapp project(':workflows') + runSchemaMigration = true + } + node { + name "O=Notary,L=London,C=GB" + notary = [validating : false] + p2pPort 10002 + rpcSettings { + address("0.0.0.0:10003") + adminAddress("0.0.0.0:10043") + } + } + node { + name "O=PartyA,L=London,C=GB" + p2pPort 10005 + rpcSettings { + address("0.0.0.0:10006") + adminAddress("0.0.0.0:10046") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } + node { + name "O=PartyB,L=New York,C=US" + p2pPort 10008 + rpcSettings { + address("0.0.0.0:10009") + adminAddress("0.0.0.0:10049") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } +} diff --git a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/log4j2.xml b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/log4j2.xml new file mode 100644 index 0000000000..5aae263c69 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/log4j2.xml @@ -0,0 +1,63 @@ + + + + + logs + node-${hostName} + ${log-path}/archive + + + + + + + + + %highlight{%level{length=1} %d{HH:mm:ss} %T %c{1}.%M - %msg%n}{INFO=white,WARN=red,FATAL=bright red blink} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/docker/corda-all-in-one/corda-v4_12/run-notary-node.sh b/tools/docker/corda-all-in-one/corda-v4_12/run-notary-node.sh new file mode 100755 index 0000000000..add8399b78 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/run-notary-node.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +if [ "$NOTARY_NODE_ENABLED" = "true" ] +then + java \ + -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5008 -javaagent:drivers/jolokia-jvm-1.6.2-agent.jar=port=7008,logHandlerClass=net.corda.node.JolokiaSlf4jAdapter" \ + -Dname=Notary \ + -Dlog4j2.configurationFile=/samples-kotlin/Advanced/negotiation-cordapp/config/dev/log4j2.xml \ + -jar /opt/bin/corda.jar +else + sleep infinity +fi diff --git a/tools/docker/corda-all-in-one/corda-v4_12/run-party-a-node.sh b/tools/docker/corda-all-in-one/corda-v4_12/run-party-a-node.sh new file mode 100755 index 0000000000..2384e75635 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/run-party-a-node.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +if [ "$PARTY_A_NODE_ENABLED" = "true" ] +then + java \ + -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -javaagent:drivers/jolokia-jvm-1.6.2-agent.jar=port=7005,logHandlerClass=net.corda.node.JolokiaSlf4jAdapter" \ + -Dname=PartyA \ + -Dlog4j2.configurationFile=/samples-kotlin/Advanced/negotiation-cordapp/config/dev/log4j2.xml \ + -jar /opt/bin/corda.jar +else + sleep infinity +fi diff --git a/tools/docker/corda-all-in-one/corda-v4_12/run-party-b-node.sh b/tools/docker/corda-all-in-one/corda-v4_12/run-party-b-node.sh new file mode 100755 index 0000000000..50024d6cff --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/run-party-b-node.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +if [ "$PARTY_B_NODE_ENABLED" = "true" ] +then + java \ + -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006 -javaagent:drivers/jolokia-jvm-1.6.2-agent.jar=port=7006,logHandlerClass=net.corda.node.JolokiaSlf4jAdapter" \ + -Dname=PartyB \ + -Dlog4j2.configurationFile=/samples-kotlin/Advanced/negotiation-cordapp/config/dev/log4j2.xml \ + -jar /opt/bin/corda.jar +else + sleep infinity +fi diff --git a/tools/docker/corda-all-in-one/corda-v4_12/supervisord.conf b/tools/docker/corda-all-in-one/corda-v4_12/supervisord.conf new file mode 100644 index 0000000000..596c19eae7 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/supervisord.conf @@ -0,0 +1,60 @@ +[supervisord] +logfile = /var/log/supervisord.log +logfile_maxbytes = 50MB +logfile_backups=10 +loglevel = info + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=http://127.0.0.1:9001 + +[inet_http_server] +port = 0.0.0.0:9001 + +[program:sshd] +command=/usr/sbin/sshd -D -ddd +autostart=true +autorestart=true +stdout_logfile=/var/log/sshd.out.log +stderr_logfile=/var/log/sshd.err.log +; stdout_logfile=/dev/stdout +; stdout_logfile_maxbytes=0 +; stderr_logfile=/dev/stderr +; stderr_logfile_maxbytes=0 + + +[program:corda-a] +directory=/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/PartyA/ +command=/run-party-a-node.sh +autostart=true +autorestart=false +exitcodes=0 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:corda-b] +directory=/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/PartyB +command=/run-party-b-node.sh +autostart=true +autorestart=false +exitcodes=0 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:corda-n] +directory=/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/Notary +command=/run-notary-node.sh +autostart=true +autorestart=false +exitcodes=0 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +