Scalable integration test (#57)

* updated Dockerfile-all-in-one

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* adjusted all-in-one.bash and monit conf to work with dockerized setup

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* integration tests pass inconsistently

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added timeout for integration test pass

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* add startup control logic, adjusted tests to wait for transactions

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added pre-config for docker-compose approach, removed remnants of old integration tests

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* reverted changes to pkg, split pre-config, added clean-shared service

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed path in all-in-one.bash

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added ipdb copyright notice

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* chmod planetmint-monit-config

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* removed entrypoint from Dockerfile-all-in-one

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added integration stage to travis matrix

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* removed unused secret

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* changed pre-config and docker-compose.integration.yml to support scaling

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* using env var to control number of nodes

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* make test-integration now scalable

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added make docs-integration, added .gitignore to python integration tests, updated readme and removed clutter

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed linter errors

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* disable planetmint for test purpose

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* test docker-compose down

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* disable every job except integration test

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* need more logs

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* name collision?

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* reverted changes to debug ci

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added TODO for ci optimization

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
Lorenz Herzberger 2022-03-08 14:38:40 +01:00 committed by GitHub
parent 89a9caf597
commit bf5b88fcb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 163 additions and 158 deletions

View File

@ -14,6 +14,7 @@ elif [[ ${PLANETMINT_CI_ABCI} == 'enable' ]]; then
elif [[ ${PLANETMINT_ACCEPTANCE_TEST} == 'enable' ]]; then elif [[ ${PLANETMINT_ACCEPTANCE_TEST} == 'enable' ]]; then
./scripts/run-acceptance-test.sh ./scripts/run-acceptance-test.sh
elif [[ ${PLANETMINT_INTEGRATION_TEST} == 'enable' ]]; then elif [[ ${PLANETMINT_INTEGRATION_TEST} == 'enable' ]]; then
docker-compose down # TODO: remove after ci optimization
./scripts/run-integration-test.sh ./scripts/run-integration-test.sh
else else
docker-compose exec planetmint pytest -v --cov=planetmint --cov-report xml:htmlcov/coverage.xml docker-compose exec planetmint pytest -v --cov=planetmint --cov-report xml:htmlcov/coverage.xml

View File

@ -100,6 +100,10 @@ docs-acceptance: check-deps ## Create documentation for acceptance tests
@$(DC) run --rm python-acceptance pycco -i -s /src -d /docs @$(DC) run --rm python-acceptance pycco -i -s /src -d /docs
$(BROWSER) acceptance/python/docs/index.html $(BROWSER) acceptance/python/docs/index.html
docs-integration: check-deps ## Create documentation for integration tests
@$(DC) run --rm python-integration pycco -i -s /src -d /docs
$(BROWSER) integration/python/docs/index.html
clean: check-deps ## Remove all build, test, coverage and Python artifacts clean: check-deps ## Remove all build, test, coverage and Python artifacts
@$(DC) up clean @$(DC) up clean
@$(ECHO) "Cleaning was successful." @$(ECHO) "Cleaning was successful."

View File

@ -13,7 +13,7 @@ services:
- ./integration/scripts/clean-shared.sh:/scripts/clean-shared.sh - ./integration/scripts/clean-shared.sh:/scripts/clean-shared.sh
- shared:/shared - shared:/shared
planetmint_1: planetmint-all-in-one:
build: build:
context: . context: .
dockerfile: Dockerfile-all-in-one dockerfile: Dockerfile-all-in-one
@ -26,53 +26,27 @@ services:
- "26656" - "26656"
- "26657" - "26657"
- "26658" - "26658"
environment:
ME: "planetmint_1"
OTHER: "planetmint_2"
command: ["/usr/src/app/scripts/pre-config-planetmint.sh", "/usr/src/app/scripts/all-in-one.bash"]
volumes:
- ./integration/scripts:/usr/src/app/scripts
- shared:/shared
planetmint_2:
build:
context: .
dockerfile: Dockerfile-all-in-one
depends_on:
- clean-shared
expose:
- "22"
- "9984"
- "9985"
- "26656"
- "26657"
- "26658"
environment:
ME: "planetmint_2"
OTHER: "planetmint_1"
command: ["/usr/src/app/scripts/pre-config-planetmint.sh", "/usr/src/app/scripts/all-in-one.bash"] command: ["/usr/src/app/scripts/pre-config-planetmint.sh", "/usr/src/app/scripts/all-in-one.bash"]
environment:
SCALE: ${SCALE:-4}
volumes: volumes:
- ./integration/scripts:/usr/src/app/scripts - ./integration/scripts:/usr/src/app/scripts
- shared:/shared - shared:/shared
scale: ${SCALE:-4}
test: test:
build: build:
context: . context: .
dockerfile: integration/python/Dockerfile dockerfile: integration/python/Dockerfile
depends_on: depends_on:
- planetmint_1 - planetmint-all-in-one
- planetmint_2
environment:
ME: "test"
PLANETMINT_ENDPOINT_1: planetmint_1
PLANETMINT_ENDPOINT_2: planetmint_2
command: ["/scripts/pre-config-test.sh", "/scripts/wait-for-planetmint.sh", "/scripts/test.sh", "pytest", "/src"] command: ["/scripts/pre-config-test.sh", "/scripts/wait-for-planetmint.sh", "/scripts/test.sh", "pytest", "/src"]
environment:
SCALE: ${SCALE:-4}
volumes: volumes:
- ./integration/python/src:/src - ./integration/python/src:/src
- ./integration/scripts:/scripts - ./integration/scripts:/scripts
- shared:/shared - shared:/shared
volumes: volumes:
shared: shared:

View File

@ -89,6 +89,7 @@ services:
context: . context: .
dockerfile: ./integration/python/Dockerfile dockerfile: ./integration/python/Dockerfile
volumes: volumes:
- ./integration/python/docs:/docs
- ./integration/python/src:/src - ./integration/python/src:/src
environment: environment:
- PLANETMINT_ENDPOINT_1=https://itest1.planetmint.io - PLANETMINT_ENDPOINT_1=https://itest1.planetmint.io

View File

@ -8,15 +8,16 @@ Code is Apache-2.0 and docs are CC-BY-4.0
# Integration test suite # Integration test suite
This directory contains the integration test suite for Planetmint. This directory contains the integration test suite for Planetmint.
The suite uses Docker Compose to run all tests. The suite uses Docker Compose to spin up multiple Planetmint nodes, run tests with `pytest` as well as cli tests and teardown.
## Running the tests ## Running the tests
Run `make test-integration` in the project root directory. Run `make test-integration` in the project root directory.
During development you can run single test use `pytest` inside the `python-integration` container with: By default the integration test suite spins up four planetmint nodes. If you desire to run a different configuration you can pass `SCALE=<number of nodes>` as an environmental variable.
## Writing and documenting the tests
Tests are sometimes difficult to read. For integration tests, we try to be really explicit on what the test is doing, so please write code that is *simple* and easy to understand. We decided to use literate-programming documentation. To generate the documentation for python tests run:
```bash ```bash
docker-compose run --rm python-integration pytest <use whatever option you need> make docs-integration
``` ```
Note: The `/src` directory contains all the test within the container.

1
integration/python/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
docs

View File

@ -3,5 +3,7 @@ FROM python:3.9
RUN mkdir -p /src RUN mkdir -p /src
RUN pip install --upgrade \ RUN pip install --upgrade \
pytest~=6.2.5 \ pytest~=6.2.5 \
planetmint-driver~=0.9.0 planetmint-driver~=0.9.0 \
pycco
RUN apt-get update && apt-get install -y openssh-client openssh-server RUN apt-get update && apt-get install -y openssh-client openssh-server

View File

@ -7,18 +7,21 @@
from planetmint_driver import Planetmint from planetmint_driver import Planetmint
from planetmint_driver.crypto import generate_keypair from planetmint_driver.crypto import generate_keypair
import time import time
import os
def test_basic(): def test_basic():
# Setup up connection to Planetmint integration test nodes # Setup up connection to Planetmint integration test nodes
pm_itest1_url = os.environ.get('PLANETMINT_ENDPOINT_1') hosts = []
pm_itest2_url = os.environ.get('PLANETMINT_ENDPOINT_1') with open('/shared/hostnames') as f:
pm_itest1 = Planetmint(pm_itest1_url) hosts = f.readlines()
pm_itest2 = Planetmint(pm_itest2_url)
pm_hosts = list(map(lambda x: Planetmint(x), hosts))
pm_alpha = pm_hosts[0]
pm_betas = pm_hosts[1:]
# genarate a keypair # genarate a keypair
alice, bob = generate_keypair(), generate_keypair() alice = generate_keypair()
# create a digital asset for Alice # create a digital asset for Alice
game_boy_token = { game_boy_token = {
@ -29,30 +32,31 @@ def test_basic():
} }
# prepare the transaction with the digital asset and issue 10 tokens to bob # prepare the transaction with the digital asset and issue 10 tokens to bob
prepared_creation_tx = pm_itest1.transactions.prepare( prepared_creation_tx = pm_alpha.transactions.prepare(
operation='CREATE', operation='CREATE',
metadata={ metadata={
'hash': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'hash': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
'storageID': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',}, 'storageID': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', },
signers=alice.public_key, signers=alice.public_key,
recipients=[([alice.public_key], 10)], recipients=[([alice.public_key], 10)],
asset=game_boy_token) asset=game_boy_token)
# fulfill and send the transaction # fulfill and send the transaction
fulfilled_creation_tx = pm_itest1.transactions.fulfill( fulfilled_creation_tx = pm_alpha.transactions.fulfill(
prepared_creation_tx, prepared_creation_tx,
private_keys=alice.private_key) private_keys=alice.private_key)
pm_itest1.transactions.send_commit(fulfilled_creation_tx) pm_alpha.transactions.send_commit(fulfilled_creation_tx)
time.sleep(4) time.sleep(1)
creation_tx_id = fulfilled_creation_tx['id'] creation_tx_id = fulfilled_creation_tx['id']
# retrieve transactions from both planetmint nodes # retrieve transactions from all planetmint nodes
creation_tx_itest1 = pm_itest1.transactions.retrieve(creation_tx_id) creation_tx_alpha = pm_alpha.transactions.retrieve(creation_tx_id)
creation_tx_itest2 = pm_itest2.transactions.retrieve(creation_tx_id) creation_tx_betas = list(map(lambda beta: beta.transactions.retrieve(creation_tx_id), pm_betas))
# Assert that transaction is stored on both planetmint nodes # Assert that transaction is stored on all planetmint nodes
assert creation_tx_itest1 == creation_tx_itest2 for tx in creation_tx_betas:
assert creation_tx_alpha == tx
# Transfer # Transfer
# create the output and inout for the transaction # create the output and inout for the transaction
@ -65,35 +69,28 @@ def test_basic():
'owners_before': output['public_keys']} 'owners_before': output['public_keys']}
# prepare the transaction and use 3 tokens # prepare the transaction and use 3 tokens
prepared_transfer_tx = pm_itest1.transactions.prepare( prepared_transfer_tx = pm_alpha.transactions.prepare(
operation='TRANSFER', operation='TRANSFER',
asset=transfer_asset, asset=transfer_asset,
inputs=transfer_input, inputs=transfer_input,
metadata={'hash': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', metadata={'hash': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
'storageID': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', }, 'storageID': '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', },
recipients=[([alice.public_key], 10)]) recipients=[([alice.public_key], 10)])
# fulfill and send the transaction # fulfill and send the transaction
fulfilled_transfer_tx = pm_itest1.transactions.fulfill( fulfilled_transfer_tx = pm_alpha.transactions.fulfill(
prepared_transfer_tx, prepared_transfer_tx,
private_keys=alice.private_key) private_keys=alice.private_key)
sent_transfer_tx = pm_itest1.transactions.send_commit(fulfilled_transfer_tx) sent_transfer_tx = pm_alpha.transactions.send_commit(fulfilled_transfer_tx)
transfer_tx_id = fulfilled_transfer_tx['id'] time.sleep(1)
transfer_tx_id = sent_transfer_tx['id']
# retrieve transactions from both planetmint nodes # retrieve transactions from both planetmint nodes
transfer_tx_itest1 = pm_itest1.transactions.retrieve(transfer_tx_id) transfer_tx_alpha = pm_alpha.transactions.retrieve(transfer_tx_id)
transfer_tx_itest2 = pm_itest2.transactions.retrieve(transfer_tx_id) transfer_tx_betas = list(map(lambda beta: beta.transactions.retrieve(transfer_tx_id), pm_betas))
# Assert that transaction is stored on both planetmint nodes # Assert that transaction is stored on both planetmint nodes
assert transfer_tx_itest1 == transfer_tx_itest2 for tx in transfer_tx_betas:
assert transfer_tx_alpha == tx

View File

@ -18,21 +18,24 @@
# #
# This integration test is a rip-off of our mutliple signature acceptance tests. # This integration test is a rip-off of our mutliple signature acceptance tests.
# ## Imports # # Imports
# We need some utils from the `os` package, we will interact with
# env variables.
import os
import time import time
# For this test case we need import and use the Python driver # For this test case we need import and use the Python driver
from planetmint_driver import Planetmint from planetmint_driver import Planetmint
from planetmint_driver.crypto import generate_keypair from planetmint_driver.crypto import generate_keypair
from planetmint_driver.exceptions import NotFoundError
def test_multiple_owners(): def test_multiple_owners():
# ## Set up a connection to the Planetmint integration test nodes # Setup up connection to Planetmint integration test nodes
pm_itest1 = Planetmint(os.environ.get('PLANETMINT_ENDPOINT_1')) hosts = []
pm_itest2 = Planetmint(os.environ.get('PLANETMINT_ENDPOINT_2')) with open('/shared/hostnames') as f:
hosts = f.readlines()
pm_hosts = list(map(lambda x: Planetmint(x), hosts))
pm_alpha = pm_hosts[0]
pm_betas = pm_hosts[1:]
# Generate Keypairs for Alice and Bob! # Generate Keypairs for Alice and Bob!
alice, bob = generate_keypair(), generate_keypair() alice, bob = generate_keypair(), generate_keypair()
@ -52,7 +55,7 @@ def test_multiple_owners():
# They prepare a `CREATE` transaction. To have multiple owners, both # They prepare a `CREATE` transaction. To have multiple owners, both
# Bob and Alice need to be the recipients. # Bob and Alice need to be the recipients.
prepared_dw_tx = pm_itest1.transactions.prepare( prepared_dw_tx = pm_alpha.transactions.prepare(
operation='CREATE', operation='CREATE',
signers=alice.public_key, signers=alice.public_key,
recipients=(alice.public_key, bob.public_key), recipients=(alice.public_key, bob.public_key),
@ -60,36 +63,31 @@ def test_multiple_owners():
# Now they both sign the transaction by providing their private keys. # Now they both sign the transaction by providing their private keys.
# And send it afterwards. # And send it afterwards.
fulfilled_dw_tx = pm_itest1.transactions.fulfill( fulfilled_dw_tx = pm_alpha.transactions.fulfill(
prepared_dw_tx, prepared_dw_tx,
private_keys=[alice.private_key, bob.private_key]) private_keys=[alice.private_key, bob.private_key])
pm_itest1.transactions.send_commit(fulfilled_dw_tx) pm_alpha.transactions.send_commit(fulfilled_dw_tx)
# We store the `id` of the transaction to use it later on. # We store the `id` of the transaction to use it later on.
dw_id = fulfilled_dw_tx['id'] dw_id = fulfilled_dw_tx['id']
time.sleep(1)
# Let's retrieve the transaction from both nodes # Let's retrieve the transaction from both nodes
pm_itest1_tx = pm_itest1.transactions.retrieve(dw_id) pm_alpha_tx = pm_alpha.transactions.retrieve(dw_id)
pm_itest2_tx = {} pm_betas_tx = list(map(lambda beta: beta.transactions.retrieve(dw_id), pm_betas))
# TODO: REPLACE WITH ASYNC OR POLL
try:
pm_itest2_tx = pm_itest2.transactions.retrieve(dw_id)
except NotFoundError:
print('TOO FAST')
time.sleep(3)
pm_itest2_tx = pm_itest2.transactions.retrieve(dw_id)
# Both retrieved transactions should be the same # Both retrieved transactions should be the same
assert pm_itest1_tx == pm_itest2_tx for tx in pm_betas_tx:
assert pm_alpha_tx == tx
# Let's check if the transaction was successful. # Let's check if the transaction was successful.
assert pm_itest1.transactions.retrieve(dw_id), \ assert pm_alpha.transactions.retrieve(dw_id), \
'Cannot find transaction {}'.format(dw_id) 'Cannot find transaction {}'.format(dw_id)
# The transaction should have two public keys in the outputs. # The transaction should have two public keys in the outputs.
assert len( assert len(
pm_itest1.transactions.retrieve(dw_id)['outputs'][0]['public_keys']) == 2 pm_alpha.transactions.retrieve(dw_id)['outputs'][0]['public_keys']) == 2
# ## Alice and Bob transfer a transaction to Carol. # ## Alice and Bob transfer a transaction to Carol.
# Alice and Bob save a lot of money living together. They often go out # Alice and Bob save a lot of money living together. They often go out
@ -112,43 +110,37 @@ def test_multiple_owners():
'owners_before': output['public_keys']} 'owners_before': output['public_keys']}
# Now they create the transaction... # Now they create the transaction...
prepared_transfer_tx = pm_itest1.transactions.prepare( prepared_transfer_tx = pm_alpha.transactions.prepare(
operation='TRANSFER', operation='TRANSFER',
asset=transfer_asset, asset=transfer_asset,
inputs=transfer_input, inputs=transfer_input,
recipients=carol.public_key) recipients=carol.public_key)
# ... and sign it with their private keys, then send it. # ... and sign it with their private keys, then send it.
fulfilled_transfer_tx = pm_itest1.transactions.fulfill( fulfilled_transfer_tx = pm_alpha.transactions.fulfill(
prepared_transfer_tx, prepared_transfer_tx,
private_keys=[alice.private_key, bob.private_key]) private_keys=[alice.private_key, bob.private_key])
sent_transfer_tx = pm_itest1.transactions.send_commit(fulfilled_transfer_tx) sent_transfer_tx = pm_alpha.transactions.send_commit(fulfilled_transfer_tx)
time.sleep(1)
# Retrieve the fulfilled transaction from both nodes # Retrieve the fulfilled transaction from both nodes
pm_itest1_tx = pm_itest1.transactions.retrieve(fulfilled_transfer_tx['id']) pm_alpha_tx = pm_alpha.transactions.retrieve(fulfilled_transfer_tx['id'])
pm_itest2_tx pm_betas_tx = list(map(lambda beta: beta.transactions.retrieve(fulfilled_transfer_tx['id']), pm_betas))
# TODO: REPLACE WITH ASYNC OR POLL
try:
pm_itest2_tx = pm_itest2.transactions.retrieve(fulfilled_transfer_tx['id'])
except NotFoundError:
print('TOO FAST')
time.sleep(3)
pm_itest2_tx = pm_itest2.transactions.retrieve(fulfilled_transfer_tx['id'])
# Now compare if both nodes returned the same transaction # Now compare if both nodes returned the same transaction
assert pm_itest1_tx == pm_itest2_tx for tx in pm_betas_tx:
assert pm_alpha_tx == tx
# They check if the transaction was successful. # They check if the transaction was successful.
assert pm_itest1.transactions.retrieve( assert pm_alpha.transactions.retrieve(
fulfilled_transfer_tx['id']) == sent_transfer_tx fulfilled_transfer_tx['id']) == sent_transfer_tx
# The owners before should include both Alice and Bob. # The owners before should include both Alice and Bob.
assert len( assert len(
pm_itest1.transactions.retrieve(fulfilled_transfer_tx['id'])['inputs'][0][ pm_alpha.transactions.retrieve(fulfilled_transfer_tx['id'])['inputs'][0][
'owners_before']) == 2 'owners_before']) == 2
# While the new owner is Carol. # While the new owner is Carol.
assert pm_itest1.transactions.retrieve(fulfilled_transfer_tx['id'])[ assert pm_alpha.transactions.retrieve(fulfilled_transfer_tx['id'])[
'outputs'][0]['public_keys'][0] == carol.public_key 'outputs'][0]['public_keys'][0] == carol.public_key

View File

@ -4,6 +4,8 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
rm /shared/planetmint* rm /shared/hostnames
rm /shared/genesis.json rm /shared/lock
rm /shared/*node_id
rm /shared/*.json
rm /shared/id_rsa.pub rm /shared/id_rsa.pub

View File

@ -5,32 +5,29 @@
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
import json import json
import os import sys
# TODO: CHANGE ME/OTHER VARIABLES
def edit_genesis() -> None: def edit_genesis() -> None:
ME = os.getenv('ME') file_names = sys.argv[1:]
OTHER = os.getenv('OTHER')
if ME == 'planetmint_1':
file_name = '{}_genesis.json'.format(ME)
other_file_name = '{}_genesis.json'.format(OTHER)
file = open(os.path.join('/shared', file_name))
other_file = open(os.path.join('/shared', other_file_name))
validators = []
for file_name in file_names:
file = open(file_name)
genesis = json.load(file) genesis = json.load(file)
other_genesis = json.load(other_file) validators.extend(genesis['validators'])
genesis['validators'] = genesis['validators'] + other_genesis['validators']
file.close() file.close()
other_file.close()
with open(os.path.join('/shared', 'genesis.json'), 'w') as f: genesis_file = open(file_names[0])
json.dump(genesis, f, indent=True) genesis_json = json.load(genesis_file)
genesis_json['validators'] = validators
genesis_file.close()
with open('/shared/genesis.json', 'w') as f:
json.dump(genesis_json, f, indent=True)
return None return None
if __name__ == '__main__': if __name__ == '__main__':
edit_genesis() edit_genesis()

View File

@ -4,6 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
# Write hostname to list
echo $(hostname) >> /shared/hostnames
# Create ssh folder # Create ssh folder
mkdir ~/.ssh mkdir ~/.ssh
@ -26,31 +29,48 @@ service ssh restart
tendermint init tendermint init
# Write node id to shared folder # Write node id to shared folder
HOSTNAME=$(hostname)
NODE_ID=$(tendermint show_node_id | tail -n 1) NODE_ID=$(tendermint show_node_id | tail -n 1)
echo $NODE_ID > /shared/${ME}_node_id echo $NODE_ID > /shared/${HOSTNAME}_node_id
# Wait for other node id # Wait for other node ids
while [ ! -f "/shared/${OTHER}_node_id" ]; do FILES=()
echo "WAIT FOR NODE ID" while [ ! ${#FILES[@]} == $SCALE ]; do
echo "WAIT FOR NODE IDS"
sleep 1 sleep 1
FILES=(/shared/*node_id)
done done
# Write node ids to persistent peers # Write node ids to persistent peers
OTHER_NODE_ID=$(cat /shared/${OTHER}_node_id) PEERS="persistent_peers = \""
PEERS=$(echo "persistent_peers = \"${NODE_ID}@${ME}:26656, ${OTHER_NODE_ID}@${OTHER}:26656\"") for f in ${FILES[@]}; do
ID=$(cat $f)
HOST=$(echo $f | cut -c 9-20)
if [ ! $HOST == $HOSTNAME ]; then
PEERS+="${ID}@${HOST}:26656, "
fi
done
PEERS=$(echo $PEERS | rev | cut -c 2- | rev)
PEERS+="\""
sed -i "/persistent_peers = \"\"/c\\${PEERS}" /tendermint/config/config.toml sed -i "/persistent_peers = \"\"/c\\${PEERS}" /tendermint/config/config.toml
# Copy genesis.json to shared folder # Copy genesis.json to shared folder
cp /tendermint/config/genesis.json /shared/${ME}_genesis.json cp /tendermint/config/genesis.json /shared/${HOSTNAME}_genesis.json
# Await config file of all services to be present # Await config file of all services to be present
while [ ! -f /shared/${OTHER}_genesis.json ]; do FILES=()
echo "WAIT FOR OTHER GENESIS" while [ ! ${#FILES[@]} == $SCALE ]; do
echo "WAIT FOR GENESIS FILES"
sleep 1 sleep 1
FILES=(/shared/*_genesis.json)
done done
# Create genesis.json for nodes # Create genesis.json for nodes
/usr/src/app/scripts/genesis.py if [ ! -f /shared/lock ]; then
echo LOCKING
touch /shared/lock
/usr/src/app/scripts/genesis.py ${FILES[@]}
fi
while [ ! -f /shared/genesis.json ]; do while [ ! -f /shared/genesis.json ]; do
echo "WAIT FOR GENESIS" echo "WAIT FOR GENESIS"

View File

@ -4,7 +4,19 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
result=$(ssh -o "StrictHostKeyChecking=no" -i \~/.ssh/id_rsa root@planetmint_1 'bash -s' < scripts/election.sh elect 2) # Read host names from shared
ssh -o "StrictHostKeyChecking=no" -i ~/.ssh/id_rsa root@planetmint_2 'bash -s' < scripts/election.sh approve $result readarray -t HOSTNAMES < /shared/hostnames
# Split into proposer and approvers
ALPHA=${HOSTNAMES[0]}
BETAS=${HOSTNAMES[@]:1}
# Propose validator upsert
result=$(ssh -o "StrictHostKeyChecking=no" -i \~/.ssh/id_rsa root@${ALPHA} 'bash -s' < scripts/election.sh elect 2)
# Approve validator upsert
for BETA in ${BETAS[@]}; do
ssh -o "StrictHostKeyChecking=no" -i ~/.ssh/id_rsa root@${BETA} 'bash -s' < scripts/election.sh approve $result
done
exec "$@" exec "$@"

View File

@ -5,24 +5,25 @@
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
# Only continue if all services are ready # Only continue if all services are ready
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' planetmint_1:9984/api/v1)" != "200" ]]; do HOSTNAMES=()
echo "WAIT FOR PLANETMINT" while [ ! ${#HOSTNAMES[@]} == $SCALE ]; do
echo "WAIT FOR HOSTNAMES"
sleep 1 sleep 1
readarray -t HOSTNAMES < /shared/hostnames
done done
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' planetmint_1:26657)" != "200" ]]; do for host in ${HOSTNAMES[@]}; do
echo "WAIT FOR TENDERMINT" while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' $host:9984)" != "200" ]]; do
sleep 1 echo "WAIT FOR PLANETMINT $host"
sleep 1
done
done done
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' planetmint_2:9984/api/v1)" != "200" ]]; do for host in ${HOSTNAMES[@]}; do
echo "WAIT FOR PLANETMINT" while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' $host:26657)" != "200" ]]; do
sleep 1 echo "WAIT FOR TENDERMINT $host"
done sleep 1
done
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' planetmint_2:26657)" != "200" ]]; do
echo "WAIT FOR TENDERMINT"
sleep 1
done done
exec "$@" exec "$@"