Removing quickstart code and CI pipeline (#616)

Removing quickstart folder and CI pipeline and parallel test in pipeline as there's only one test now

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Nicolas MASSART 6 years ago committed by GitHub
parent f0f8c54501
commit 44ca364ea9
  1. 102
      Jenkinsfile
  2. 1
      quickstart/README.md
  3. 1
      quickstart/block-explorer-light/.gitignore
  4. 4
      quickstart/block-explorer-light/Dockerfile
  5. 561
      quickstart/block-explorer-light/dist/css/_base.css
  6. 1
      quickstart/block-explorer-light/dist/css/app.f776fd31.css
  7. 4
      quickstart/block-explorer-light/dist/css/buefy.min.css
  8. 2
      quickstart/block-explorer-light/dist/css/materialdesignicons.min.css
  9. 7
      quickstart/block-explorer-light/dist/css/materialdesignicons.min.css.map
  10. BIN
      quickstart/block-explorer-light/dist/favicon.ico
  11. BIN
      quickstart/block-explorer-light/dist/fonts/materialdesignicons-webfont.eot
  12. 8394
      quickstart/block-explorer-light/dist/fonts/materialdesignicons-webfont.svg
  13. BIN
      quickstart/block-explorer-light/dist/fonts/materialdesignicons-webfont.ttf
  14. BIN
      quickstart/block-explorer-light/dist/fonts/materialdesignicons-webfont.woff
  15. BIN
      quickstart/block-explorer-light/dist/fonts/materialdesignicons-webfont.woff2
  16. 1
      quickstart/block-explorer-light/dist/index.html
  17. 2
      quickstart/block-explorer-light/dist/js/app.769a0f91.js
  18. 1
      quickstart/block-explorer-light/dist/js/app.769a0f91.js.map
  19. 80
      quickstart/block-explorer-light/dist/js/chunk-vendors.79a7999a.js
  20. 1
      quickstart/block-explorer-light/dist/js/chunk-vendors.79a7999a.js.map
  21. 37
      quickstart/block-explorer-light/nginx.vh.conf
  22. 35
      quickstart/build.gradle
  23. 56
      quickstart/docker-compose.yml
  24. 63
      quickstart/listQuickstartServices.sh
  25. 2
      quickstart/pantheon/.gitignore
  26. 18
      quickstart/pantheon/Dockerfile
  27. 18
      quickstart/pantheon/bootnode_start.sh
  28. 35
      quickstart/pantheon/node_start.sh
  29. 26
      quickstart/removePantheonPrivateNetwork.sh
  30. 25
      quickstart/resumePantheonPrivateNetwork.sh
  31. 79
      quickstart/runPantheonPrivateNetwork.sh
  32. 337
      quickstart/src/test/java/tech/pegasys/pantheon/tests/quickstart/DockerQuickstartTest.java
  33. 16
      quickstart/src/test/resources/log4j2.xml
  34. 25
      quickstart/stopPantheonPrivateNetwork.sh

102
Jenkinsfile vendored

@ -19,70 +19,48 @@ if (env.BRANCH_NAME == "master") {
}
try {
stage('Pantheon tests') {
parallel javaTests: {
node {
checkout scm
docker.image('docker:18.06.0-ce-dind').withRun('--privileged') { d ->
docker.image('pegasyseng/pantheon-build:0.0.3').inside("--link ${d.id}:docker") {
try {
stage('Compile') {
sh './gradlew --no-daemon --parallel clean compileJava'
}
stage('compile tests') {
sh './gradlew --no-daemon --parallel compileTestJava'
}
stage('assemble') {
sh './gradlew --no-daemon --parallel assemble'
}
stage('Build') {
sh './gradlew --no-daemon --parallel build'
}
stage('Reference tests') {
sh './gradlew --no-daemon --parallel referenceTest'
}
stage('Integration Tests') {
sh './gradlew --no-daemon --parallel integrationTest'
}
stage('Acceptance Tests') {
sh './gradlew --no-daemon --parallel acceptanceTest'
}
stage('Check Licenses') {
sh './gradlew --no-daemon --parallel checkLicenses'
}
stage('Check javadoc') {
sh './gradlew --no-daemon --parallel javadoc'
}
stage('Jacoco root report') {
sh './gradlew --no-daemon jacocoRootReport'
}
} finally {
archiveArtifacts '**/build/reports/**'
archiveArtifacts '**/build/test-results/**'
archiveArtifacts 'build/reports/**'
archiveArtifacts 'build/distributions/**'
junit '**/build/test-results/**/*.xml'
}
node {
checkout scm
docker.image('docker:18.06.0-ce-dind').withRun('--privileged') { d ->
docker.image('pegasyseng/pantheon-build:0.0.3').inside("--link ${d.id}:docker") {
try {
stage('Compile') {
sh './gradlew --no-daemon --parallel clean compileJava'
}
}
}
}, quickstartTests: {
node {
checkout scm
docker.image('docker:18.06.0-ce-dind').withRun('--privileged') { d ->
docker.image('pegasyseng/pantheon-build:0.0.3').inside("--link ${d.id}:docker") {
try {
stage('Docker quickstart Tests') {
sh 'DOCKER_HOST=tcp://docker:2375 ./gradlew --no-daemon --parallel clean dockerQuickstartTest'
}
} finally {
archiveArtifacts '**/build/test-results/**'
archiveArtifacts '**/build/reports/**'
junit '**/build/test-results/**/*.xml'
}
stage('compile tests') {
sh './gradlew --no-daemon --parallel compileTestJava'
}
stage('assemble') {
sh './gradlew --no-daemon --parallel assemble'
}
stage('Build') {
sh './gradlew --no-daemon --parallel build'
}
stage('Reference tests') {
sh './gradlew --no-daemon --parallel referenceTest'
}
stage('Integration Tests') {
sh './gradlew --no-daemon --parallel integrationTest'
}
stage('Acceptance Tests') {
sh './gradlew --no-daemon --parallel acceptanceTest'
}
stage('Check Licenses') {
sh './gradlew --no-daemon --parallel checkLicenses'
}
stage('Check javadoc') {
sh './gradlew --no-daemon --parallel javadoc'
}
stage('Jacoco root report') {
sh './gradlew --no-daemon jacocoRootReport'
}
} finally {
archiveArtifacts '**/build/reports/**'
archiveArtifacts '**/build/test-results/**'
archiveArtifacts 'build/reports/**'
archiveArtifacts 'build/distributions/**'
junit '**/build/test-results/**/*.xml'
}
}
}

@ -1 +0,0 @@
For complete and up-to-date documentation, please see [Docker quick-start, on the Pantheon wiki](https://github.com/PegaSysEng/pantheon/wiki/Docker-Quickstart).

@ -1,4 +0,0 @@
FROM nginx:alpine
COPY dist /usr/share/nginx/html
RUN sed -i 's@NODE_ENV:"production",BASE_URL:"/"@NODE_URL:"/jsonrpc",CONNECTION_TYPE:"json_rpc"@g' /usr/share/nginx/html/js/*.js
COPY nginx.vh.conf /etc/nginx/conf.d/default.conf

@ -1,561 +0,0 @@
html, body {
font-family: 'Barlow', sans-serif;
margin: 0;
overflow: auto;
}
div {
overflow: visible;
}
#app {
overflow: auto;
}
.flex-box {
display: flex;
}
.blockSidebar {
width: 240px !important;
min-width: 240px !important;
overflow: visible;
}
.block-logo-container {
padding: 55px 56px 0 72px;
}
.block-logo {
padding: 18px 27px 18px 9px;
}
.block-logo-bg {
padding: 17px 19px 21px 20px;
background-color: #357CFF;
}
.block-logo-text {
font-weight: 700;
font-size: 32px;
line-height: 38px;
color: white;
}
.blocks-list {
margin: 52px 83px 0 81px;
max-width: 76px;
overflow: visible;
}
.content {
width: 100%;
}
.block-content {
padding-top: 55px;
padding-left: 50px;
}
.pair {
display: flex;
align-items: center;
}
.minW140 {
min-width: 140px;
}
.label {
font-size: 12px;
line-height: 14px;
letter-spacing: 0.4px;
font-weight: 600;
text-transform: uppercase;
text-align: right;
padding: 16px;
color: #A7B5D1;
}
.value {
color: #273656;
font-weight: 500;
font-size: 20px;
line-height: 24px;
letter-spacing: 0.2px;
padding: 11px 16px 13px;
}
.counter-container {
padding: 10px 8px;
}
.tx-counter {
background-color: #273656;
padding: 1px 8px 3px;
color: white;
font-size: 20px;
line-height: 24px;
letter-spacing: 0.2px;
font-weight: 500;
}
.uncle-counter {
padding: 1px 8px 3px;
font-size: 20px;
line-height: 24px;
letter-spacing: 0.2px;
font-weight: 500;
border: 1px solid #357CFF;
color: #357CFF;
}
.erc-counter {
background-color: #48E2A2;
padding: 1px 8px 3px;
color: white;
font-size: 20px;
line-height: 24px;
letter-spacing: 0.2px;
font-weight: 500;
}
.txs-table-container {
padding-top: 16px;
}
tr:nth-child(odd) {
background: white;
}
tr:nth-child(even) {
background: #F7F8FA;
}
.table {
width: 100%;
border-bottom: solid 1px #D9E4EF;
border-spacing: 0;
}
.first-column {
padding: 7px 32px 8px;
text-align: right;
font-weight: 500;
font-size: 14px;
line-height: 17px;
letter-spacing: 0.2px;
color: #273656;
border-right: 1px solid #D0DEF2;
}
.normal-column {
padding: 7px 32px 8px;
font-weight: 500;
font-size: 14px;
line-height: 17px;
letter-spacing: 0.2px;
color: #273656;
text-align: center;
border-right: 1px solid #D0DEF2;
}
.last-column {
text-align: left;
padding: 7px 32px 8px;
font-weight: 500;
font-size: 14px;
line-height: 17px;
letter-spacing: 0.2px;
color: #273656;
}
.normal-column a {
text-decoration: none;
color: #357CFF;
}
.normal-column a:visited {
color: #357CFF;
}
.th-wrap {
padding: 9px 32px 10px;
font-weight: 600;
font-size: 12px;
line-height: 14px;
letter-spacing: 0.4px;
color: #A7B5D1;
background-color: #F7F8FA;
border-right: 1px solid #D0DEF2;
border-bottom: 1px solid #D0DEF2;
border-spacing: 0;
margin: 0;
cursor: pointer;
}
.is-sortable {
padding: 0;
}
.is-current-sort .th-wrap {
padding: 9px 32px;
margin: 0;
}
.table-mobile-sort {
display: none;
}
.pagination {
display: flex;
align-items: center;
}
.is-desc i:before {
transform: rotate(180deg);
}
th:first-child {
text-align: right;
}
th:last-child {
text-align: left;
}
.tx-logo-container {
padding: 55px 56px 45px 72px;
}
.tx-logo {
padding: 15px 24px 15px 6px;
}
.tx-logo-bg {
border-radius: 50%;
background-color: #273656;
padding: 20px 25px 24px;
font-size: 32px;
line-height: 38px;
letter-spacing: -1px;
font-weight: 700;
color: white;
}
.tx-value-label {
margin: 15px 8px;
font-size: 12px;
line-height: 12px;
height: 12px;
text-transform: uppercase;
background-color: rgb(72, 226, 162);
font-weight: 600;
letter-spacing: 0.5px;
margin-right: 10px;
color: rgb(255, 255, 255);
position: relative;
padding: 4px 8px;
overflow: visible;
}
.tx-value-label:before {
content: "";
position: absolute;
top: 0;
right: -10px;
transform: scaleX(0.8);
transform-origin: left center 0px;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid rgb(72, 226, 162);
}
.tx-sideBar {
padding-bottom: 40px;
box-sizing: border-box;
}
.separated {
padding-top: 56px;
}
.gray {
color: #A7B5D1;
}
.value-grayed {
background-color: #D0DEF2;
}
.value-grayed:before {
border-left-color: #D0DEF2;
}
.percentage {
padding-left: 10px;
color: #FF9F1C;
}
.txList {
max-width: 144px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.account-avatar-container {
padding: 55px 115px 0 72px;
}
.account-avatar {
padding: 10px 27px 18px 9px;
}
.identicon-container {
border: 1px solid rgb(208, 222, 242);
max-height: 74px;
}
.account-content {
padding-top: 55px;
height: max-content;
}
.account-code {
padding: 12px 60px 40px 17px;
font-family: 'Roboto Mono', monospace;
word-break: break-all;
}
.top-menu {
position: fixed;
z-index: 9999;
width: 100%;
display: flex;
align-items: center;
background: #FFFFFF;
border: 1px solid #D9E4EF;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.04);
padding-bottom: 5px;
margin: 0;
}
.modal {
position: fixed;
top: 0;
left: 0;
z-index: 10000;
width: 100%;
height: 100%;
margin: 0;
}
.modal-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255,255, 255, 0.8);
filter: blur(8px);
-webkit-filter: blur(8px);
}
.modal-card-body {
display: flex;
align-items: center;
flex-direction: column;
}
.modal-card {
border: 1px solid #D9E4EF;
border-radius: 4px;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.04);
padding: 32px;
background-color: white;
position: absolute;
left: 30%;
width: 40%;
height: 230px;
top: calc(50% - 150px);
margin: auto;
box-sizing: border-box;
}
.media {
display: flex;
}
.media-content p {
color: #273656;
font-weight: 500;
font-size: 20px;
line-height: 24px;
letter-spacing: 0.2px;
padding-bottom: 32px;
margin: 0;
}
.control input:focus {
outline: none;
}
.control input {
background: #FFFFFF;
border: 1px solid #D9E4EF;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.04);
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
line-height: 20px;
font-weight: 500;
color: #273656;
width: 415px;
}
.button {
cursor: pointer;
}
.button:active {
outline: none;
}
.modal-card-foot .is-primary {
margin-right: 30px;
background-color: #357CFF;
transition: background-color 0.2s ease-in-out 0s;
}
.modal-card-foot .is-primary:hover{
background-color: rgba(53, 124, 255, 0.8);
}
.modal-card-foot {
display: flex;
flex-direction: row-reverse;
width: max-content;
margin: 0 auto;
}
.left-header {
min-width: 80px;
width: 80px;
min-height: 100%;
border-right: 1px solid #D0DEF2;
padding-top: 24px;
box-sizing: border-box;
}
.iconAlethio {
cursor: pointer;
fill: #273656 !important;
overflow: visible;
}
.iconAlethio svg {
overflow: visible;
}
.iconSearch {
cursor: pointer;
fill: #D0DEF2 !important;
transition: fill linear 0.2s;
}
.iconSearch:hover {
fill: #357CFF !important;
}
.search-icon-container {
padding: 32px 20px;
}
.min100 {
min-height: max-content;
height: 100%;
}
.home {
background-color: #F7F8FA;
display: flex;
flex-direction: column;
position: relative;
}
.centered-absolute {
position: absolute;
top: calc(50% - 65px);
left: 0;
right: 0;
margin: 0 auto;
width: 830px;
}
.home-search-container {
margin-top: 24px;
box-sizing: border-box;
padding: 16px;
background-color: #FFFFFF;
box-shadow: 0 8px 16px 0 rgba(51,69,100,0.07);
display: flex;
justify-content: space-between;
align-items: center;
}
.searchbar-alethio-logo {
fill: #273656 !important;
}
.home-search-container input:focus {
outline: none;
}
.home-search-container input {
box-sizing: border-box;
font-family: 'Barlow', sans-serif !important;
width: 663px;
min-width: 663px;
border: none;
padding: 0 56px 4px 12px;
font-size: 18px;
line-height: 22px;
letter-spacing: 0;
font-weight: 500;
color: #273656;
}
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
font-family: 'Barlow', sans-serif !important;
color: #273656;;
}
::-moz-placeholder { /* Firefox 19+ */
font-family: 'Barlow', sans-serif !important;
color: #273656;;
}
:-ms-input-placeholder { /* IE 10+ */
font-family: 'Barlow', sans-serif !important;
color: #273656;;
}
:-moz-placeholder { /* Firefox 18- */
font-family: 'Barlow', sans-serif !important;
color: #273656;;
}
.submit-container {
cursor: pointer;
display: flex;
background-color: #357CFF;
border-radius: 4px;
transition: background-color 0.2s ease-in-out 0s;
color: white;
padding: 8px 16px 6px 8px;
text-transform: uppercase;
font-size: 12px;
line-height: 14px;
font-weight: 600;
letter-spacing: 0.4px;
}
.submit-container:hover {
background-color: rgba(53, 124, 255, 0.8);
}
.searchbar-search-icon {
fill: white !important;
}
.search-text {
padding-left: 12px;
}
.white-bg-value {
background-color: white;
padding: 1px 8px 3px;
}
.error-container {
box-sizing: border-box;
position: absolute;
top: calc(50% - 100px);
left: calc(50% - 240px);
height: 200px;
width: 480px;
border: 1px solid #D0DEF2;
background-color: #FFFFFF;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.04);
padding-top: 45px;
display: flex;
flex-direction: column;
align-items: center;
}
.error-text {
padding: 20px 45px 45px;
font-size: 16px;
letter-spacing: -0.16px;
line-height: 20px;
text-align: center;
color: #A7B5D1;
}
.is-empty {
background: #F7F8FA !important;
}
.no-txs {
padding-left: 222px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.0 MiB

@ -1 +0,0 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><link rel=stylesheet href=/css/_base.css><link href=/css/materialdesignicons.min.css media=all rel=stylesheet type=text/css><link href="https://fonts.googleapis.com/css?family=Barlow:400,500,600,700" rel=stylesheet><link href="https://fonts.googleapis.com/css?family=Roboto+Mono:400,500,700" rel=stylesheet><title>ethstats-light</title><link href=/css/app.f776fd31.css rel=preload as=style><link href=/js/app.769a0f91.js rel=preload as=script><link href=/js/chunk-vendors.79a7999a.js rel=preload as=script><link href=/css/app.f776fd31.css rel=stylesheet></head><body><noscript><strong>We're sorry but ethstats-light doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.79a7999a.js></script><script src=/js/app.769a0f91.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,37 +0,0 @@
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location /jsonrpc {
rewrite /jsonrpc/?(.*) /$1 break;
proxy_pass http://rpcnode:8545;
proxy_redirect off;
proxy_set_header Host $host;
}
location /jsonws {
rewrite /jsonws/?(.*) /$1 break;
proxy_pass http://rpcnode:8546;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
root /usr/share/nginx/html;
try_files $uri /index.html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

@ -1,35 +0,0 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
dependencies {
testRuntime 'org.apache.logging.log4j:log4j-core'
testRuntime 'org.apache.logging.log4j:log4j-slf4j-impl'
testImplementation project(':pantheon')
testImplementation 'com.google.guava:guava'
testImplementation 'com.squareup.okhttp3:okhttp'
testImplementation 'io.vertx:vertx-core'
testImplementation 'junit:junit'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.awaitility:awaitility'
testImplementation 'org.web3j:core'
}
test.enabled = false
task dockerQuickstartTest(type: Test) {
mustRunAfter rootProject.subprojects*.test
description = 'Runs Pantheon Docker quickstart tests.'
group = 'verification'
}

@ -1,56 +0,0 @@
version: '2.2'
services:
bootnode:
build:
context: ../
dockerfile: quickstart/pantheon/Dockerfile
args:
- JENKINS_URL=${JENKINS_URL:-null}
image: quickstart/pantheon:latest
entrypoint: /opt/pantheon/bootnode_start.sh --dev-mode
volumes:
- public-keys:/opt/pantheon/public-keys
minernode:
image: quickstart/pantheon:latest
# The address 0xfe3b557e8fb62b89f4916b721be55ceb828dbd73 is one of the addresses in the
# dev mode genesys file
command: ["--dev-mode",
"--miner-enabled",
"--miner-coinbase=0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"]
volumes:
- public-keys:/opt/pantheon/public-keys
depends_on:
- bootnode
node:
image: quickstart/pantheon:latest
command: ["--dev-mode"]
volumes:
- public-keys:/opt/pantheon/public-keys
depends_on:
- bootnode
rpcnode:
image: quickstart/pantheon:latest
command: ["--dev-mode",
"--rpc-enabled",
"--rpc-listen=0.0.0.0:8545",
"--ws-enabled",
"--ws-listen=0.0.0.0:8546",
"--rpc-cors-origins=*"]
volumes:
- public-keys:/opt/pantheon/public-keys
depends_on:
- bootnode
ports:
- "8545"
- "8546"
explorer:
build:
context: block-explorer-light
dockerfile: Dockerfile
image: quickstart/block-explorer-light:latest
depends_on:
- rpcnode
ports:
- "${EXPLORER_PORT_MAPPING}80"
volumes:
public-keys:

@ -1,63 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
QUICKSTART_FOLDER=quickstart
me=`basename "$0"`
if [ ! -f gradlew ]; then
echo "Please run this script from the project root using : ${QUICKSTART_FOLDER}/${me}"
exit 1
fi
COMPOSE_CONFIG_FILE_OPTION="-f ${QUICKSTART_FOLDER}/docker-compose.yml"
EXPLORER_SERVICE=explorer
HOST=${DOCKER_PORT_2375_TCP_ADDR:-"localhost"}
# Displays services list with port mapping
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} ps
# Get individual port mapping for exposed services
explorerMapping=`docker-compose ${COMPOSE_CONFIG_FILE_OPTION} port explorer 80`
#Check if we run in a tty before using exec and otherwise set $TERM as it fails if not set.
if [ ! -t 1 ] ;
then
export TERM=xterm-color
fi
# Displays links to exposed services
ORANGE='\033[0;33m'
CYAN='\033[0;36m'
BOLD=$(tput bold)
NORMAL=$(tput sgr0)
echo "${CYAN}****************************************************************"
dots=""
maxRetryCount=50
while [ "$(curl -m 1 -s -o /dev/null -w ''%{http_code}'' http://${HOST}:${explorerMapping##*:})" != "200" ] && [ ${#dots} -le ${maxRetryCount} ]
do
dots=$dots"."
printf "${CYAN} Block explorer is starting, please wait ${ORANGE}$dots${NORMAL}\\r"
sleep 1
done
if [ ${#dots} -gt ${maxRetryCount} ]; then
(>&2 echo "${ORANGE}ERROR: Web block explorer is not started at http://${HOST}:${explorerMapping##*:}$ !${CYAN} * ")
echo "****************************************************************${NORMAL}"
else
echo "JSON-RPC ${BOLD}HTTP${NORMAL}${CYAN} service endpoint : ${ORANGE}http://${HOST}:${explorerMapping##*:}/jsonrpc${CYAN} *"
echo "JSON-RPC ${BOLD}WebSocket${NORMAL}${CYAN} service endpoint : ${ORANGE}ws://${HOST}:${explorerMapping##*:}/jsonws${CYAN} *"
echo "${CYAN}Web block explorer address : ${ORANGE}http://${HOST}:${explorerMapping##*:}${CYAN} * "
echo "****************************************************************${NORMAL}"
fi

@ -1,2 +0,0 @@
# Created by .ignore support plugin (hsz.mobi)
/pantheon/

@ -1,18 +0,0 @@
FROM openjdk:8-jdk as builder
ARG JENKINS_URL
ENV JENKINS_URL $JENKINS_URL
COPY . /tmp/pantheon
WORKDIR /tmp/pantheon
RUN ./gradlew installDist -x test
FROM openjdk:8-jre
# copy application (with libraries inside)
COPY quickstart/pantheon/*_start.sh /opt/pantheon/
COPY --from=builder /tmp/pantheon/build/install/pantheon /opt/pantheon/
# List Exposed Ports
EXPOSE 8546 8545 30303
# specify default command
ENTRYPOINT ["/opt/pantheon/node_start.sh"]

@ -1,18 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# write pub key for making other nodes able to connect to bootnode
/opt/pantheon/bin/pantheon $@ --no-discovery export-pub-key /opt/pantheon/public-keys/bootnode
# run bootnode with discovery but no bootnodes as it's our bootnode.
/opt/pantheon/bin/pantheon $@

@ -1,35 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# write pub key for checking that network works
node_id=`hostname`
/opt/pantheon/bin/pantheon $@ export-pub-key "/opt/pantheon/public-keys/${node_id}"
BOOTNODE_KEY_FILE=/opt/pantheon/public-keys/bootnode
# sleep loop to wait for the public key file to be written
while [ ! -f $BOOTNODE_KEY_FILE ]
do
sleep 1
done
# get bootnode enode address
bootnode_pubkey=`sed 's/^0x//' $BOOTNODE_KEY_FILE`
boonode_ip=`getent hosts bootnode | awk '{ print $1 }'`
BOOTNODE_P2P_PORT="30303"
bootnode_enode_address="enode://${bootnode_pubkey}@${boonode_ip}:${BOOTNODE_P2P_PORT}"
# run with bootnode param
/opt/pantheon/bin/pantheon $@ --bootnodes=$bootnode_enode_address

@ -1,26 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
QUICKSTART_FOLDER=quickstart
me=`basename "$0"`
if [ ! -f gradlew ]; then
echo "Please run this script from the project root using : ${QUICKSTART_FOLDER}/${me}"
exit 1
fi
COMPOSE_CONFIG_FILE_OPTION="-f ${QUICKSTART_FOLDER}/docker-compose.yml"
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} down
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} rm -sfv

@ -1,25 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
QUICKSTART_FOLDER=quickstart
me=`basename "$0"`
if [ ! -f gradlew ]; then
echo "Please run this script from the project root using : ${QUICKSTART_FOLDER}/${me}"
exit 1
fi
COMPOSE_CONFIG_FILE_OPTION="-f ${QUICKSTART_FOLDER}/docker-compose.yml"
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} start

@ -1,79 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
me=`basename "$0"`
PARAMS=""
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
echo "Usage:"
exit 0
;;
-s|--skip-build)
SKIP_BUILD=true
shift 1
;;
-d|--use-default-static-ports)
export RPC_PORT_MAPPING="8545:"
export WS_PORT_MAPPING="8546:"
export EXPLORER_PORT_MAPPING="3000:"
break 2
;;
--rpc-port)
export RPC_PORT_MAPPING="${2}:"
shift 2
;;
--ws-port)
export WS_PORT_MAPPING="${2}:"
shift 2
;;
--explorer-port)
export EXPLORER_PORT_MAPPING="${2}:"
shift 2
;;
--) # end argument parsing
shift
break
;;
-*|--*=) # unsupported flags
echo "Error: Unsupported flag $1, try ${me} -h or ${me} --help for complete usage help." >&2
exit 1
;;
*) # preserve positional arguments
PARAMS="$PARAMS $1"
shift
;;
esac
done
# set positional arguments in their proper place
eval set -- "$PARAMS"
QUICKSTART_FOLDER=quickstart
if [ ! -f gradlew ]; then
echo "Please, run this script from the project root using : ${QUICKSTART_FOLDER}/${me}"
exit 1
fi
COMPOSE_CONFIG_FILE_OPTION="-f ${QUICKSTART_FOLDER}/docker-compose.yml"
# Build and run containers and network
if [ ! ${SKIP_BUILD} ];then
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} build --force-rm
fi
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} up -d --scale node=4
${QUICKSTART_FOLDER}/listQuickstartServices.sh

@ -1,337 +0,0 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.quickstart;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.PantheonInfo;
import tech.pegasys.pantheon.tests.quickstart.DockerQuickstartTest.Service.ExposedPort;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Splitter;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.RequestOptions;
import io.vertx.core.http.WebSocket;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Async;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DockerQuickstartTest {
private static final String PROJECT_ROOT =
Paths.get(System.getProperty("user.dir")).getParent().toString();
private static final String DOCKER_COMPOSE_PROJECT_PREFIX = "quickstart_";
private static final int DEFAULT_HTTP_RPC_PORT = 8545;
private static final int DEFAULT_WS_RPC_PORT = 8546;
private static final String DEFAULT_RPC_HOST =
Optional.ofNullable(System.getenv("DOCKER_PORT_2375_TCP_ADDR")).orElse("localhost");
private static final String DEFAULT_HTTP_RPC_HOST = "http://" + DEFAULT_RPC_HOST;
private static final String DEFAULT_HOST_HEADER = "localhost";
private final Map<ServicesIdentifier, Service> services = new EnumMap<>(ServicesIdentifier.class);
private final Map<EndpointsIdentifier, String> endpoints =
new EnumMap<>(EndpointsIdentifier.class);
private Web3j web3HttpClient;
@BeforeClass
public static void runPantheonPrivateNetwork() throws IOException, InterruptedException {
final ProcessBuilder processBuilder =
new ProcessBuilder("quickstart/runPantheonPrivateNetwork.sh");
processBuilder.directory(new File(PROJECT_ROOT)); // going up one level is the project root
processBuilder.inheritIO(); // redirect all output to logs
final Process process = processBuilder.start();
final int exitValue = process.waitFor();
if (exitValue != 0) {
// check for errors, error messages and causes are redirected to logs already
throw new RuntimeException("execution of script failed!");
}
}
@Before
public void listQuickstartServices() throws IOException, InterruptedException {
final ProcessBuilder processBuilder =
new ProcessBuilder("quickstart/listQuickstartServices.sh");
processBuilder.directory(new File(PROJECT_ROOT)); // going up one level is the project root
// redirect only error output to logs as we want to be able to
// keep the standard output available for reading
processBuilder.redirectError(Redirect.INHERIT);
final Process process = processBuilder.start();
final int exitValue = process.waitFor();
if (exitValue != 0) {
// check for errors, error messages and causes are redirected to logs already
throw new RuntimeException("execution of script failed!");
}
final BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream(), UTF_8));
reader.lines().forEach(this::populateServicesAndEndpoints);
reader.close();
assertThat(services).isNotNull().isNotEmpty();
assertThat(endpoints).isNotNull().isNotEmpty();
final HttpService httpService =
new HttpService(
DEFAULT_HTTP_RPC_HOST
+ ":"
+ services
.get(ServicesIdentifier.RPCNODE)
.exposedPorts
.get(DEFAULT_HTTP_RPC_PORT)
.externalPort);
httpService.addHeader("Host", DEFAULT_HOST_HEADER);
web3HttpClient = Web3j.build(httpService, 2000, Async.defaultExecutorService());
assertThat(web3HttpClient).isNotNull();
}
private void populateServicesAndEndpoints(final String line) {
// We check that the output of the script displays the right endpoints and services states
// each endpoint and service will be stored in a map for later use.
for (final ServicesIdentifier servicesIdentifier : ServicesIdentifier.values()) {
final Matcher regexMatcher = servicesIdentifier.pattern.matcher(line);
if (regexMatcher.find()) {
final Service service = new Service();
service.name = regexMatcher.group(1);
service.state = regexMatcher.group(2).toLowerCase();
final String[] portMappings = regexMatcher.group(3).split(",", -1);
for (final String mapping : portMappings) {
final ExposedPort port = new ExposedPort(mapping);
service.exposedPorts.put(port.internalPort, port);
}
services.put(servicesIdentifier, service);
}
}
for (final EndpointsIdentifier endpointsIdentifier : EndpointsIdentifier.values()) {
final Matcher regexMatcher = endpointsIdentifier.pattern.matcher(line);
if (regexMatcher.find()) {
final String endpoint = regexMatcher.group(1);
endpoints.put(endpointsIdentifier, endpoint);
}
}
}
@After
public void closeConnections() {
assertThat(web3HttpClient).isNotNull();
web3HttpClient.shutdown();
}
@AfterClass
public static void removePantheonPrivateNetwork() throws IOException, InterruptedException {
final ProcessBuilder processBuilder =
new ProcessBuilder("quickstart/removePantheonPrivateNetwork.sh");
processBuilder.inheritIO(); // redirect all output to logs
processBuilder.directory(new File(PROJECT_ROOT)); // going up one level is the project root
final Process process = processBuilder.start();
final int exitValue = process.waitFor();
if (exitValue != 0) {
// check for errors, all output and then also error messages and causes are redirected to logs
throw new RuntimeException("execution of script failed!");
}
}
@Test
// Method starts with an underscore so it lexicographically sorts first.
public void _servicesShouldBeUp() {
Awaitility.await()
.ignoreExceptions()
.atMost(90, TimeUnit.SECONDS)
.untilAsserted(
() ->
Arrays.stream(ServicesIdentifier.values())
.forEach(
servicesIdentifier ->
assertThat(services.get(servicesIdentifier).state).isEqualTo("up")));
}
@Test
public void servicesEndpointsShouldBeExposed() {
Awaitility.await()
.ignoreExceptions()
.atMost(60, TimeUnit.SECONDS)
.untilAsserted(
() ->
Arrays.stream(EndpointsIdentifier.values())
.forEach(
endpointsIdentifier ->
assertThat(endpoints.get(endpointsIdentifier))
.isNotNull()
.isNotEmpty()));
}
@Test
public void rpcNodeShouldFindPeers() {
// Peers are those defined in docker-compose.yml and launched with scaling of 4 regular nodes
// which gives us 6 peers of the RPC node: bootnode, minernode and 4 regular nodes.
final int expectecNumberOfPeers = 6;
Awaitility.await()
.ignoreExceptions()
.atMost(60, TimeUnit.SECONDS)
.untilAsserted(
() ->
assertThat(web3HttpClient.netPeerCount().send().getQuantity().intValueExact())
.isEqualTo(expectecNumberOfPeers));
}
@Test
public void rpcNodeShouldReturnCorrectVersion() {
final Iterator<String> versionParts = Splitter.on("/").split(PantheonInfo.version()).iterator();
final String versionPrefix = versionParts.next() + "/" + versionParts.next() + "/";
Awaitility.await()
.ignoreExceptions()
.atMost(60, TimeUnit.SECONDS)
.untilAsserted(
() ->
assertThat(web3HttpClient.web3ClientVersion().send().getWeb3ClientVersion())
.startsWith(versionPrefix));
}
@Test
public void mustMineSomeBlocks() {
// A bug occurred that failed mining after 2 blocks, so testing at least 10.
final int expectedAtLeastBlockNumber = 10;
Awaitility.await()
.ignoreExceptions()
.atMost(5, TimeUnit.MINUTES)
.untilAsserted(
() ->
assertThat(web3HttpClient.ethBlockNumber().send().getBlockNumber().intValueExact())
.isGreaterThan(expectedAtLeastBlockNumber));
}
@Test
public void webSocketRpcServiceMustConnect() {
final RequestOptions options = new RequestOptions();
options.setPort(
services
.get(ServicesIdentifier.RPCNODE)
.exposedPorts
.get(DEFAULT_WS_RPC_PORT)
.externalPort);
options.setHost(DEFAULT_RPC_HOST);
final WebSocket[] wsConnection = new WebSocket[1];
final Vertx vertx = Vertx.vertx();
try {
vertx
.createHttpClient(new HttpClientOptions())
.websocket(options, websocket -> wsConnection[0] = websocket);
Awaitility.await()
.ignoreExceptions()
.atMost(45, TimeUnit.SECONDS)
.untilAsserted(() -> assertThat(wsConnection[0]).isNotNull());
} finally {
assertThat(wsConnection[0]).isNotNull();
wsConnection[0].close();
}
}
private enum ServicesIdentifier {
BOOTNODE,
EXPLORER,
MINERNODE,
NODE,
RPCNODE;
final Pattern pattern;
ServicesIdentifier() {
pattern =
Pattern.compile(
"(^"
+ DOCKER_COMPOSE_PROJECT_PREFIX
+ this.name().toLowerCase()
+ "_[0-9]+)\\s+.+\\s{3,}(\\w+)\\s+(.+)",
Pattern.DOTALL);
}
}
private enum EndpointsIdentifier {
EXPLORER("Web block explorer address"),
HTTP_RPC("JSON-RPC.+HTTP.+service endpoint"),
WS_RPC("JSON-RPC.+WebSocket.+service endpoint");
final Pattern pattern;
EndpointsIdentifier(final String lineLabel) {
pattern =
Pattern.compile(lineLabel + ".+((http|ws)://.+:[0-9]+/{0,1}[a-z]*)", Pattern.DOTALL);
}
}
static class Service {
String name;
String state;
Map<Integer, ExposedPort> exposedPorts = new HashMap<>();
static class ExposedPort {
final Integer internalPort;
final Integer externalPort;
private final Pattern pattern = Pattern.compile("[0-9]+", Pattern.DOTALL);
ExposedPort(final String portDescription) {
if (portDescription.contains("->")) {
final String[] ports = portDescription.split("->", 2);
final String[] internalPortInfos = ports[1].split("/", 2);
internalPort = Integer.valueOf(internalPortInfos[0]);
final String[] externalPortInfos = ports[0].split(":", 2);
externalPort = Integer.valueOf(externalPortInfos[1]);
} else {
final Matcher regexMatcher = pattern.matcher(portDescription);
internalPort = regexMatcher.find() ? Integer.valueOf(regexMatcher.group(0)) : null;
externalPort = null;
}
}
}
}
}

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">
<Properties>
<Property name="root.log.level">INFO</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="${sys:root.log.level}">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

@ -1,25 +0,0 @@
#!/bin/sh -e
# Copyright 2018 ConsenSys AG.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
QUICKSTART_FOLDER=quickstart
me=`basename "$0"`
if [ ! -f gradlew ]; then
echo "Please run this script from the project root using : ${QUICKSTART_FOLDER}/${me}"
exit 1
fi
COMPOSE_CONFIG_FILE_OPTION="-f ${QUICKSTART_FOLDER}/docker-compose.yml"
docker-compose ${COMPOSE_CONFIG_FILE_OPTION} stop
Loading…
Cancel
Save