Skip to content

Commit

Permalink
[FAB-7540] Simplifies Reconfigure Your Network tutorial
Browse files Browse the repository at this point in the history
This change brings a new set of scripts and configuration files to the
first-network sample to make it easier for people to follow the new
tutorial on how to add a third org to the network setup in BYFN.

To function properly the new Extend You First Network script (eyfn.sh)
must be run after byfn.sh is run and with the same parameters. So,
valid uses include:

./byfn.sh up
./eyfn.sh up

or

./byfn.sh up -c testchannel -s couchdb -l node
./eyfn.sh up -c testchannel -s couchdb -l node

A single './eyfn.sh down' command is however necessary to take the
whole network down.

Patch-set #2: fixes ./eyfn.sh down
Patch-set #3: removed unused option from Usage and spurious whitespaces
Patch-set #4: added missing test file

Change-Id: I9c926b52f2243dda1c5f9368112c314a6c5c6929
Signed-off-by: Arnaud J Le Hors <lehors@us.ibm.com>
  • Loading branch information
lehors committed Feb 10, 2018
1 parent 1883ae9 commit 1d69e9e
Show file tree
Hide file tree
Showing 9 changed files with 831 additions and 155 deletions.
2 changes: 1 addition & 1 deletion first-network/byfn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ else
exit 1
fi

while getopts "h?c:t:d:f:s:l:a?" opt; do
while getopts "h?c:t:d:f:s:l:" opt; do
case "$opt" in
h|\?)
printHelp
Expand Down
64 changes: 64 additions & 0 deletions first-network/docker-compose-couch-org3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

networks:
byfn:

services:
couchdb4:
container_name: couchdb4
image: hyperledger/fabric-couchdb
# Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
# for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode.
environment:
- COUCHDB_USER=
- COUCHDB_PASSWORD=
# Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
# for example map it to utilize Fauxton User Interface in dev environments.
ports:
- "9984:5984"
networks:
- byfn

peer0.org3.example.com:
environment:
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984
# The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
# provide the credentials for ledger to connect to CouchDB. The username and password must
# match the username and password set for the associated CouchDB.
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
depends_on:
- couchdb4

couchdb5:
container_name: couchdb5
image: hyperledger/fabric-couchdb
# Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
# for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode.
environment:
- COUCHDB_USER=
- COUCHDB_PASSWORD=
# Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
# for example map it to utilize Fauxton User Interface in dev environments.
ports:
- "10984:5984"
networks:
- byfn

peer1.org3.example.com:
environment:
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984
# The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
# provide the credentials for ledger to connect to CouchDB. The username and password must
# match the username and password set for the associated CouchDB.
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
depends_on:
- couchdb5
310 changes: 310 additions & 0 deletions first-network/eyfn.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
#!/bin/bash
#
# Copyright IBM Corp All Rights Reserved
#
# SPDX-License-Identifier: Apache-2.0
#

# This script extends the Hyperledger Fabric By Your First Network by
# adding a third organization to the network previously setup in the
# BYFN tutorial.
#

# prepending $PWD/../bin to PATH to ensure we are picking up the correct binaries
# this may be commented out to resolve installed version of tools if desired
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}

# Print the usage message
function printHelp () {
echo "Usage: "
echo " eyfn.sh up|down|restart|generate [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>]"
echo " eyfn.sh -h|--help (print this message)"
echo " <mode> - one of 'up', 'down', 'restart' or 'generate'"
echo " - 'up' - bring up the network with docker-compose up"
echo " - 'down' - clear the network with docker-compose down"
echo " - 'restart' - restart the network"
echo " - 'generate' - generate required certificates and genesis block"
echo " -c <channel name> - channel name to use (defaults to \"mychannel\")"
echo " -t <timeout> - CLI timeout duration in seconds (defaults to 10)"
echo " -d <delay> - delay duration in seconds (defaults to 3)"
echo " -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)"
echo " -s <dbtype> - the database backend to use: goleveldb (default) or couchdb"
echo " -l <language> - the chaincode language: golang (default) or node"
echo
echo "Typically, one would first generate the required certificates and "
echo "genesis block, then bring up the network. e.g.:"
echo
echo " eyfn.sh generate -c mychannel"
echo " eyfn.sh up -c mychannel -s couchdb"
echo " eyfn.sh up -l node"
echo " eyfn.sh down -c mychannel"
echo
echo "Taking all defaults:"
echo " eyfn.sh generate"
echo " eyfn.sh up"
echo " eyfn.sh down"
}

# Ask user for confirmation to proceed
function askProceed () {
read -p "Continue? [Y/n] " ans
case "$ans" in
y|Y|"" )
echo "proceeding ..."
;;
n|N )
echo "exiting..."
exit 1
;;
* )
echo "invalid response"
askProceed
;;
esac
}

# Obtain CONTAINER_IDS and remove them
# TODO Might want to make this optional - could clear other containers
function clearContainers () {
CONTAINER_IDS=$(docker ps -aq)
if [ -z "$CONTAINER_IDS" -o "$CONTAINER_IDS" == " " ]; then
echo "---- No containers available for deletion ----"
else
docker rm -f $CONTAINER_IDS
fi
}

# Delete any images that were generated as a part of this setup
# specifically the following images are often left behind:
# TODO list generated image naming patterns
function removeUnwantedImages() {
DOCKER_IMAGE_IDS=$(docker images | grep "dev\|none\|test-vp\|peer[0-9]-" | awk '{print $3}')
if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then
echo "---- No images available for deletion ----"
else
docker rmi -f $DOCKER_IMAGE_IDS
fi
}

# Generate the needed certificates, the genesis block and start the network.
function networkUp () {
# generate artifacts if they don't exist
if [ ! -d "org3-artifacts/crypto-config" ]; then
generateCerts
generateChannelArtifacts
createConfigTx
fi
# start org3 peers
if [ "${IF_COUCHDB}" == "couchdb" ]; then
docker-compose -f $COMPOSE_FILE_ORG3 -f $COMPOSE_FILE_COUCH_ORG3 up -d 2>&1
else
docker-compose -f $COMPOSE_FILE_ORG3 up -d 2>&1
fi
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start Org3 network"
exit 1
fi
echo
echo "###############################################################"
echo "############### Have Org3 peers join network ##################"
echo "###############################################################"
docker exec Org3cli ./scripts/step2org3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to have Org3 peers join network"
exit 1
fi
echo
echo "###############################################################"
echo "##### Upgrade chaincode to have Org3 peers on the network #####"
echo "###############################################################"
docker exec cli ./scripts/step3org3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to add Org3 peers on network"
exit 1
fi
# finish by running the test
docker exec Org3cli ./scripts/testorg3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to run test"
exit 1
fi
}

# Tear down running network
function networkDown () {
docker-compose -f $COMPOSE_FILE_ORG3 down
docker-compose -f $COMPOSE_FILE_ORG3 -f $COMPOSE_FILE_COUCH_ORG3 down
docker-compose -f $COMPOSE_FILE down
docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH down
# Don't remove containers, images, etc if restarting
if [ "$MODE" != "restart" ]; then
#Cleanup the chaincode containers
clearContainers
#Cleanup images
removeUnwantedImages
# remove orderer block and other channel configuration transactions and certs
rm -rf channel-artifacts/*.block channel-artifacts/*.tx crypto-config ./org3-artifacts/crypto-config/ channel-artifacts/org3.json
# remove the docker-compose yaml file that was customized to the example
rm -f docker-compose-e2e.yaml
fi
}

# Use the CLI container to create the configuration transaction needed to add
# Org3 to the network
function createConfigTx () {
echo
echo "###############################################################"
echo "####### Generate and submit config tx to add Org3 #############"
echo "###############################################################"
docker exec cli scripts/step1org3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to create config tx"
exit 1
fi
}

# We use the cryptogen tool to generate the cryptographic material
# (x509 certs) for the new org. After we run the tool, the certs will
# be parked in the BYFN folder titled ``crypto-config``.

# Generates Org3 certs using cryptogen tool
function generateCerts (){
which cryptogen
if [ "$?" -ne 0 ]; then
echo "cryptogen tool not found. exiting"
exit 1
fi
echo
echo "###############################################################"
echo "##### Generate Org3 certificates using cryptogen tool #########"
echo "###############################################################"

(cd org3-artifacts
cryptogen generate --config=./org3-crypto.yaml
if [ "$?" -ne 0 ]; then
echo "Failed to generate certificates..."
exit 1
fi
)
echo
}

# Generate channel configuration transaction
function generateChannelArtifacts() {
which configtxgen
if [ "$?" -ne 0 ]; then
echo "configtxgen tool not found. exiting"
exit 1
fi
echo "##########################################################"
echo "######### Generating Org3 config material ###############"
echo "##########################################################"
(cd org3-artifacts
export FABRIC_CFG_PATH=$PWD
configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json
if [ "$?" -ne 0 ]; then
echo "Failed to generate Org3 config material..."
exit 1
fi
)
cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
echo
}


# If BYFN wasn't run abort
if [ ! -d crypto-config ]; then
echo
echo "ERROR: Please, run byfn.sh first."
echo
exit 1
fi

# Obtain the OS and Architecture string that will be used to select the correct
# native binaries for your platform
OS_ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}')
# timeout duration - the duration the CLI should wait for a response from
# another container before giving up
CLI_TIMEOUT=10
#default for delay
CLI_DELAY=3
# channel name defaults to "mychannel"
CHANNEL_NAME="mychannel"
# use this as the default docker-compose yaml definition
COMPOSE_FILE=docker-compose-cli.yaml
#
COMPOSE_FILE_COUCH=docker-compose-couch.yaml
# use this as the default docker-compose yaml definition
COMPOSE_FILE_ORG3=docker-compose-org3.yaml
#
COMPOSE_FILE_COUCH_ORG3=docker-compose-couch-org3.yaml
# use golang as the default language for chaincode
LANGUAGE=golang

# Parse commandline args
if [ "$1" = "-m" ];then # supports old usage, muscle memory is powerful!
shift
fi
MODE=$1;shift
# Determine whether starting, stopping, restarting or generating for announce
if [ "$MODE" == "up" ]; then
EXPMODE="Starting"
elif [ "$MODE" == "down" ]; then
EXPMODE="Stopping"
elif [ "$MODE" == "restart" ]; then
EXPMODE="Restarting"
elif [ "$MODE" == "generate" ]; then
EXPMODE="Generating certs and genesis block for"
else
printHelp
exit 1
fi
while getopts "h?c:t:d:f:s:l:" opt; do
case "$opt" in
h|\?)
printHelp
exit 0
;;
c) CHANNEL_NAME=$OPTARG
;;
t) CLI_TIMEOUT=$OPTARG
;;
d) CLI_DELAY=$OPTARG
;;
f) COMPOSE_FILE=$OPTARG
;;
s) IF_COUCHDB=$OPTARG
;;
l) LANGUAGE=$OPTARG
;;
esac
done

# Announce what was requested

if [ "${IF_COUCHDB}" == "couchdb" ]; then
echo
echo "${EXPMODE} with channel '${CHANNEL_NAME}' and CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds and using database '${IF_COUCHDB}'"
else
echo "${EXPMODE} with channel '${CHANNEL_NAME}' and CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds"
fi
# ask for confirmation to proceed
askProceed

#Create the network using docker compose
if [ "${MODE}" == "up" ]; then
networkUp
elif [ "${MODE}" == "down" ]; then ## Clear the network
networkDown
elif [ "${MODE}" == "generate" ]; then ## Generate Artifacts
generateCerts
generateChannelArtifacts
createConfigTx
elif [ "${MODE}" == "restart" ]; then ## Restart the network
networkDown
networkUp
else
printHelp
exit 1
fi
Loading

0 comments on commit 1d69e9e

Please sign in to comment.