Skip to content

Commit

Permalink
Update nano test network
Browse files Browse the repository at this point in the history
Fix minor bugs, add network.sh script to simplify standing up the network, and add an option to run the network in a single container

Note: the updated peerNadmin.sh scripts no longer create or join a channel and now only configure the environment for the relevant peer

Signed-off-by: James Taylor <jamest@uk.ibm.com>
  • Loading branch information
jt-nti committed Mar 15, 2022
1 parent f01eeab commit d1ec79e
Show file tree
Hide file tree
Showing 19 changed files with 348 additions and 23 deletions.
6 changes: 5 additions & 1 deletion ci/scripts/shellcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ set -euo pipefail
scversion="v0.8.0" # or "stable", or "latest"
wget -qO- "https://github.com/koalaman/shellcheck/releases/download/${scversion?}/shellcheck-${scversion?}.linux.x86_64.tar.xz" | tar -xJv "shellcheck-${scversion}/shellcheck"
"./shellcheck-${scversion}/shellcheck" --version
pwd
echo $PATH
which shellcheck
shellcheck --version

"./shellcheck-${scversion}/shellcheck" ./test-network-nano-bash/*.sh
cd ./test-network-nano-bash && shellcheck *.sh
1 change: 1 addition & 0 deletions test-network-nano-bash/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
channel-artifacts/
crypto-config/
data/
logs/
*.gz
45 changes: 45 additions & 0 deletions test-network-nano-bash/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
FROM alpine:3.14 AS build

WORKDIR /build

ENV HLF_VERSION=2.4.3
ENV YQ_VERSION=v4.22.1
ENV YQ_BINARY=yq_linux_amd64

RUN apk --no-cache add curl dumb-init

RUN curl -L --retry 5 --retry-delay 3 "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/${YQ_BINARY}.tar.gz" | tar xz && mv ${YQ_BINARY} /usr/bin/yq
RUN curl -L --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v${HLF_VERSION}/hyperledger-fabric-linux-amd64-${HLF_VERSION}.tar.gz" | tar xz
# TODO this is a temporary hack due to missing builder binaries in the 2.4.3 release. See https://github.com/hyperledger/fabric/issues/3286
RUN curl -L --retry 5 --retry-delay 3 "https://hyperledger-fabric.jfrog.io/artifactory/fabric-binaries/hyperledger-fabric-linux-amd64-2.4-stable.tar.gz" | tar xz bin/ccaas_builder
RUN mv bin/ccaas_builder ccaas_builder

RUN yq -i 'del(.vm.endpoint) | del(.chaincode.externalBuilders) | .chaincode.externalBuilders[0].name = "ccaas_builder" | .chaincode.externalBuilders[0].path = "/home/nanofab/ccbuilders/ccaas" | .chaincode.externalBuilders[0].propagateEnvironment[0] = "CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG"' config/core.yaml

COPY chaincode-external/ ./chaincode-external/

RUN yq -i '.address = "host.docker.internal:9999"' chaincode-external/connection.json
RUN cd chaincode-external && tar cfz code.tar.gz connection.json && tar cfz external-chaincode.tar.gz code.tar.gz metadata.json

FROM alpine:3.14

ENV FABRIC_CFG_PATH /etc/hyperledger/fabric

RUN apk --no-cache add libc6-compat

COPY --from=build /usr/bin/dumb-init /usr/bin/dumb-init
COPY --chown=root:root --from=build /build/bin/* /usr/local/bin/
COPY --chown=root:root --from=build /build/config/* ${FABRIC_CFG_PATH}/

RUN addgroup -g 500 nanofab && adduser -u 500 -D -h /home/nanofab -G nanofab nanofab
USER nanofab
WORKDIR /home/nanofab

RUN mkdir -p ./ccbuilders/ccaas ./network/logs && ln -s /usr/local/bin ./bin && ln -s ${FABRIC_CFG_PATH} ./config
COPY --chown=nanofab:nanofab --from=build /build/ccaas_builder/ /home/nanofab/ccbuilders/ccaas/
COPY --chown=nanofab:nanofab --from=build /build/chaincode-external/ /home/nanofab/chaincode-external/
COPY --chown=nanofab:nanofab *.sh *.yaml ./network/

WORKDIR /home/nanofab/network
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["/home/nanofab/network/network.sh","start"]
106 changes: 100 additions & 6 deletions test-network-nano-bash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ The path must be absolute or relative to where the peer will run so that it can

# Instructions for starting network

## Running each component separately

Open terminal windows for 3 ordering nodes, 4 peer nodes, and 4 peer admins as seen in the following terminal setup. The first two peers and peer admins belong to Org1, the latter two peer and peer admins belong to Org2.
Note, you can start with two ordering nodes and a single Org1 peer node and single Org1 peer admin terminal if you would like to keep things even more minimal (two ordering nodes are required to achieve consensus (2 of 3), while a single peer from Org1 can be utilized since the endorsement policy is set as any single organization).
![Terminal setup](terminal_setup.png)
Expand All @@ -47,12 +49,20 @@ If you have trouble running bash scripts in your environment, you can just as ea
- In the three orderer terminals, run `./orderer1.sh`, `./orderer2.sh`, `./orderer3.sh` respectively
- In the four peer terminals, run `./peer1.sh`, `./peer2.sh`, `./peer3.sh`, `./peer4.sh` respectively
- Note that each orderer and peer write their data (including their ledgers) to their own subdirectory under the `data` directory
- In the four peer admin terminals, run `source peer1admin.sh`, `source peer2admin.sh`, `source peer3admin.sh`, `source peer4admin.sh` respectively
- In the four peer admin terminals, run `source peer1admin.sh && ./create_channel.sh`, `source peer2admin.sh && ./join_channel.sh`, `source peer3admin.sh && ./join_channel.sh`, `source peer4admin.sh && ./join_channel.sh` respectively

Note the syntax of running the scripts. The peer admin scripts set the admin environment variables and must be run with the `source` command in order that the exported environment variables can be utilized by any subsequent user commands.

The `create_channel.sh` script creates the application channel `mychannel`, updates the channel configuration for the gossip anchor peer, and joins the peer to `mychannel`.
The `join_channel.sh` script joins a peer to `mychannel`.

## Starting the network with one command

Note the syntax of running the scripts. The peer admin scripts run with the `source` command in order to source the script files in the respective shells. This is important so that the exported environment variables can be utilized by any subsequent user commands.
Using the individual scripts above gives you more control of the process of starting a Fabric network and demonstrates how all the required components fit together, however the same network can also be started using a single script for convenience.

The `peer1admin.sh` script sets the peer1 admin environment variables, creates the application channel `mychannel`, updates the channel configuration for the org1 gossip anchor peer, and joins peer1 to `mychannel`.
The remaining peer admin scripts join their respective peers to `mychannel`.
```
./network.sh start
```

# Instructions for deploying and running the basic asset transfer sample chaincode

Expand Down Expand Up @@ -103,6 +113,7 @@ In another terminal, navigate to `fabric-samples/asset-transfer-basic/chaincode-

```
npm install
npm run build
```

Set the chaincode package ID again (this is a different terminal):
Expand All @@ -120,7 +131,7 @@ export CHAINCODE_SERVER_ADDRESS=127.0.0.1:9999
And start the chaincode service:

```
npm run start:server-notls
npm run start:server-nontls
```

## Activate the chaincode
Expand All @@ -133,6 +144,10 @@ peer lifecycle chaincode approveformyorg -o 127.0.0.1:6050 --channelID mychannel
peer lifecycle chaincode commit -o 127.0.0.1:6050 --channelID mychannel --name basic --version 1 --sequence 1 --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
```

**Note:** after following the instructions above, the chaincode will only be installed on peer1 and will only be available in the peer1admin shell.
Rerun the `peer lifecycle chaincode install` command in other peer admin shells to install it on the corresponding peer.
You will also need to rerun the `peer lifecycle chaincode approveformyorg` command to use the chaincode on peers in another organisation, e.g. using the peer3admin shell.

## Interact with the chaincode

Invoke the chaincode to create an asset (only a single endorser is required based on the default endorsement policy of any organization).
Expand All @@ -150,4 +165,83 @@ peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","1"]}'

Congratulations, you have deployed a minimal Fabric network! Inspect the scripts if you would like to see the minimal set of commands that were required to deploy the network.

Utilize `Ctrl-C` in the orderer and peer terminal windows to kill the orderer and peer processes. You can run the scripts again to restart the components with their existing data, or run `./generate_artifacts` again to clean up the existing artifacts and data if you would like to restart with a clean environment.
# Stopping the network

If you started the Fabric componentes individually, utilize `Ctrl-C` in the orderer and peer terminal windows to kill the orderer and peer processes. You can run the scripts again to restart the components with their existing data, or run `./generate_artifacts` again to clean up the existing artifacts and data if you would like to restart with a clean environment.

If you used the `network.sh` script, utilize `Ctrl-C` to kill the orderer and peer processes. You can restart the network with the existing data, or run `./network.sh clean` to remove old data before restarting.

# Running the network in a docker container

It's possible to run the nano test network inside a docker container, for example if you do not want to install prereqs first.

The docker image is not currently published anywhere so you'll need to build it using the following command.

```
docker build -t nanofab .
```

Then start the network using the `docker run` command. For example, to start the network with the orderer1 and peer1 ports exposed, and an entry in the hosts file to resolve the internal IP address used by the host.

```
docker run --name nanofab -it --rm -p 6050:6050 -p 7051:7051 --add-host=host.docker.internal:host-gateway nanofab
```

When the network is running, you can use `docker exec` to run peer commands in another terminal, e.g.

```
docker exec -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer channel list'
```

**Note:** `peer1admin.sh` selects which peer to run the command against and there are equivelents for the other three peers.

The following commands demonstrate how to deploy and use the basic asset transfer sample chaincode.
Start by installing the chaincode on peer1.

```
docker exec -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer lifecycle chaincode install /home/nanofab/chaincode-external/external-chaincode.tar.gz'
```

Capture the chaincode ID in an environment variable.

```
export CHAINCODE_ID=basic_1.0:...
```

Start external chaincode outside the container by following the instructions in the "Running the chaincode as a service" section above.

**Important:** you must use the following `CHAINCODE_SERVER_ADDRESS` in order for the peer to be able to connect from inside the container.

```
export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999
```

Approve the chaincode for peer1's organisation.

```
docker exec --env CHAINCODE_ID -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer lifecycle chaincode approveformyorg -o 127.0.0.1:6050 --channelID mychannel --name basic --version 1 --package-id $CHAINCODE_ID --sequence 1 --tls --cafile ${PWD}/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt'
```

Commit the chaincode.

```
docker exec -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer lifecycle chaincode commit -o 127.0.0.1:6050 --channelID mychannel --name basic --version 1 --sequence 1 --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt'
```

If all goes well, you should be able to create an asset.

```
docker exec -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer chaincode invoke -o 127.0.0.1:6050 -C mychannel -n basic -c '\''{"Args":["CreateAsset","1","blue","35","tom","1000"]}'\'' --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt'
```

And read the new asset!

```
docker exec -it nanofab /bin/sh -c '. ./peer1admin.sh ; /usr/local/bin/peer chaincode query -C mychannel -n basic -c '\''{"Args":["ReadAsset","1"]}'\'''
```

If you need the credentials used in the test network, run the following command to copy them out of the running container.

```
docker cp nanofab:/home/nanofab/network/crypto-config ./crypto-config
```
11 changes: 11 additions & 0 deletions test-network-nano-bash/create_channel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#

# create channel and add anchor peer
peer channel create -c mychannel -o 127.0.0.1:6050 -f "${PWD}"/channel-artifacts/mychannel.tx --outputBlock "${PWD}"/channel-artifacts/mychannel.block --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
peer channel update -o 127.0.0.1:6050 -c mychannel -f "${PWD}"/channel-artifacts/Org1MSPanchors.tx --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt

# join peer to channel
peer channel join -b "${PWD}"/channel-artifacts/mychannel.block
3 changes: 3 additions & 0 deletions test-network-nano-bash/generate_artifacts.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#
set -eu

# remove existing artifacts, or proceed on if the directories don't exist
Expand Down
7 changes: 7 additions & 0 deletions test-network-nano-bash/join_channel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#

# join peer to channel
peer channel join -b "${PWD}"/channel-artifacts/mychannel.block
143 changes: 143 additions & 0 deletions test-network-nano-bash/network.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#
set -eu

# Print the usage message
printHelp() {
USAGE="${1:-}"
if [ "$USAGE" = "start" ]; then
echo "Usage: "
echo " network.sh start [Flags]"
echo
echo " Starts the test network"
echo
echo " Flags:"
echo " -d <delay> - CLI delays for a certain number of seconds (defaults to 3)"
echo " -h - Print this message"
elif [ "$USAGE" = "clean" ]; then
echo "Usage: "
echo " network.sh clean [Flags]"
echo
echo " Cleans the test network configuration and data files"
echo
echo " Flags:"
echo " -h - Print this message"
else
echo "Usage: "
echo " network.sh <Mode> [Flags]"
echo " Modes:"
echo " start - Starts the test network"
echo " clean - Cleans the test network configuration and data files"
echo
echo " Flags:"
echo " -h - Print this message"
echo
echo " Examples:"
echo " network.sh start"
fi
}

networkStart() {
: "${CLI_DELAY:=3}"

# Clear up all the Fabric processes we start
# shellcheck disable=SC2064
trap "trap - TERM && kill -- -$$" INT TERM EXIT

if [ -d "${PWD}"/channel-artifacts ] && [ -d "${PWD}"/crypto-config ]; then
echo "Using existing artifacts..."
CREATE_CHANNEL=false
else
echo "Generating artifacts..."
./generate_artifacts.sh
CREATE_CHANNEL=true
fi

echo "Creating logs directory..."
mkdir -p "${PWD}"/logs

sleep $CLI_DELAY

echo "Starting orderers..."
./orderer1.sh > ./logs/orderer1.log 2>&1 &
./orderer2.sh > ./logs/orderer2.log 2>&1 &
./orderer3.sh > ./logs/orderer3.log 2>&1 &

sleep $CLI_DELAY

echo "Starting peers..."
./peer1.sh > ./logs/peer1.log 2>&1 &
./peer2.sh > ./logs/peer2.log 2>&1 &
./peer3.sh > ./logs/peer3.log 2>&1 &
./peer4.sh > ./logs/peer4.log 2>&1 &

sleep $CLI_DELAY

if [ "${CREATE_CHANNEL}" = "true" ]; then
echo "Creating channel (peer1)..."
. ./peer1admin.sh && ./create_channel.sh

echo "Joining channel (peer2)..."
. ./peer2admin.sh && ./join_channel.sh

echo "Joining channel (peer3)..."
. ./peer3admin.sh && ./join_channel.sh

echo "Joining channel (peer4)..."
. ./peer4admin.sh && ./join_channel.sh
fi

echo "Fabric network running, use Ctrl-C to stop"
wait
}

networkClean() {
echo "Removing directories: channel-artifacts crypto-config data logs"
rm -r "${PWD}"/channel-artifacts || true
rm -r "${PWD}"/crypto-config || true
rm -r "${PWD}"/data || true
rm -r "${PWD}"/logs || true
}

# Parse commandline args

## Parse mode
if [ $# -lt 1 ] ; then
printHelp
exit 0
else
MODE=$1
shift
fi

# parse flags
while [ $# -ge 1 ] ; do
key="$1"
case $key in
-d )
CLI_DELAY="$2"
shift
;;
-h )
printHelp "$MODE"
exit 0
;;
* )
echo "Unknown flag: $key"
printHelp
exit 1
;;
esac
shift
done

if [ "$MODE" = "start" ]; then
networkStart
elif [ "$MODE" = "clean" ]; then
networkClean
else
printHelp
exit 1
fi
3 changes: 3 additions & 0 deletions test-network-nano-bash/orderer1.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#
set -eu

# look for binaries in local dev environment /build/bin directory and then in local samples /bin directory
Expand Down
3 changes: 3 additions & 0 deletions test-network-nano-bash/orderer2.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env sh
#
# SPDX-License-Identifier: Apache-2.0
#
set -eu

# look for binaries in local dev environment /build/bin directory and then in local samples /bin directory
Expand Down
Loading

0 comments on commit d1ec79e

Please sign in to comment.