fabric-samples/full-stack-asset-transfer-guide/justfile

521 lines
17 KiB
Makefile

#
# Copyright contributors to the Hyperledgendary Full Stack Asset Transfer project
#
# SPDX-License-Identifier: Apache-2.0
#
# 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.
#
# Main justfile to run all the development scripts
# To install 'just' see https://github.com/casey/just#installation
###############################################################################
# COMMON TARGETS #
###############################################################################
# Ensure all properties are exported as shell env-vars
set export
# set the current directory, and the location of the test dats
CWDIR := justfile_directory()
_default:
@just -f {{justfile()}} --list
# Run the check script to validate tool versions installed
check:
${CWDIR}/check.sh
cluster_name := env_var_or_default("WORKSHOP_CLUSTER_NAME", "kind")
cluster_runtime := env_var_or_default("WORKSHOP_CLUSTER_RUNTIME", "kind")
ingress_domain := env_var_or_default("WORKSHOP_INGRESS_DOMAIN", "localho.st")
storage_class := env_var_or_default("WORKSHOP_STORAGE_CLASS", "standard")
chaincode_name := env_var_or_default("WORKSHOP_CHAINCODE_NAME", "asset-transfer")
internal_repo_endpoint := env_var_or_default("WORKSHOP_INTERNAL_REPO", "localhost:5000")
external_repo_endpoint := env_var_or_default("WORKSHOP_EXTERNAL_REPO", "localhost:5000")
cluster_type := env_var_or_default("WORKSHOP_CLUSTER_TYPE", "k8s")
# Start a local KIND cluster with Traefik, localhost:5000 registry, and *.localho.st alias in kube DNS
kind: unkind
#!/usr/bin/env bash
set -e -o pipefail
infrastructure/kind_with_traefik.sh {{cluster_name}}
ls -lart ~/.kube/config
chmod o+r ~/.kube/config
# check connectivity to local k8s
kubectl cluster-info &>/dev/null
# Shut down the KIND cluster
unkind:
#!/usr/bin/env bash
kind delete cluster --name {{cluster_name}}
if docker inspect kind-registry &>/dev/null; then
echo "Stopping container registry"
docker kill kind-registry
docker rm kind-registry
fi
# Bring up the Traefik ingress controller on the target k8s cluster
traefik:
#!/usr/bin/env bash
kubectl apply -f infrastructure/kind_console_ingress/templates/ingress/traefik-controller.yaml
sleep 20
kubectl wait --namespace traefik \
--for=condition=ready pod \
--selector=app=traefik \
--timeout=3m
# Just start the operator
operator: operator-crds
infrastructure/sample-network/network operator
# Just start the console
console: operator
infrastructure/sample-network/network console
# Just install the operator CRDs
operator-crds: check-kube
kubectl apply -k https://github.com/hyperledger-labs/fabric-operator.git/config/crd
###############################################################################
# TEST TARGETS
###############################################################################
# Run e2e tests of all scenarios
test: test-chaincode test-appdev test-cloud # test-ansible
# Run an e2e test of the SmartContractDev scenario
test-chaincode:
tests/00-chaincode-e2e.sh
# Run an e2e test of the ApplicationDev scenario
test-appdev:
tests/10-appdev-e2e.sh
# Run an e2e test of the CloudNative scenario
test-cloud:
tests/20-cloud-e2e.sh
# Run tests of the network setup with operator, console, and ansible plays
test-ansible:
tests/30-ansible-e2e.sh
# Run tests of the console setup using the direct line to kube API controller (not ansible)
test-console:
tests/40-console.sh
###############################################################################
# MICROFAB / DEV TARGETS #
###############################################################################
# Shut down the microfab (uf) instance
microfab-down:
#!/usr/bin/env bash
if docker inspect microfab &>/dev/null; then
echo "Removing existing microfab container:"
docker kill microfab
fi
# Start a micro fab instance and create configuration in _cfg/uf
microfab: microfab-down
#!/usr/bin/env bash
set -e -o pipefail
export CFG=$CWDIR/_cfg/uf
export MICROFAB_CONFIG='{
"endorsing_organizations":[
{
"name": "org1"
},
{
"name": "org2"
}
],
"channels":[
{
"name": "mychannel",
"endorsing_organizations":[
"org1"
]
},
{
"name": "appchannel",
"endorsing_organizations":[
"org1","org2"
]
}
],
"capability_level":"V2_5"
}'
mkdir -p $CFG
echo
echo "Stating microfab...."
timeout 60s bash -c \
'docker run --name microfab -p 8080:8080 --add-host host.docker.internal:host-gateway --rm -d -e MICROFAB_CONFIG="${MICROFAB_CONFIG}" ghcr.io/hyperledger-labs/microfab:latest \
&& docker logs -f microfab | grep --max-count=1 "Microfab started"'
curl -s http://console.127-0-0-1.nip.io:8080/ak/api/v1/components | weft microfab -w $CFG/_wallets -p $CFG/_gateways -m $CFG/_msp -f
cat << EOF > $CFG/org1admin.env
export CORE_PEER_LOCALMSPID=org1MSP
export CORE_PEER_MSPCONFIGPATH=$CFG/_msp/org1/org1admin/msp
export CORE_PEER_ADDRESS=org1peer-api.127-0-0-1.nip.io:8080
export FABRIC_CFG_PATH=$CWDIR/config
export CORE_PEER_CLIENT_CONNTIMEOUT=15s
export CORE_PEER_DELIVERYCLIENT_CONNTIMEOUT=15s
export ORDERER_ENDPOINT=orderer-api.127-0-0-1.nip.io:8080
EOF
cat << EOF > $CFG/org2admin.env
export CORE_PEER_LOCALMSPID=org2MSP
export CORE_PEER_MSPCONFIGPATH=$CFG/_msp/org2/org2admin/msp
export CORE_PEER_ADDRESS=org2peer-api.127-0-0-1.nip.io:8080
export FABRIC_CFG_PATH=$CWDIR/config
export CORE_PEER_CLIENT_CONNTIMEOUT=15s
export CORE_PEER_DELIVERYCLIENT_CONNTIMEOUT=15s
export ORDERER_ENDPOINT=orderer-api.127-0-0-1.nip.io:8080
EOF
echo
echo "To get an peer cli environment run:"
echo
echo 'source $WORKSHOP_PATH/_cfg/uf/org1admin.env'
# Creates a chaincode package and install/approve/commit
debugcc:
#!/usr/bin/env bash
set -e -o pipefail
export CFG=$CWDIR/_cfg/uf
pushd $CWDIR/contracts/asset-transfer-typescript
# this is the ip address the peer will use to talk to the CHAINCODE_ID
# remember this is relative from where the peer is running.
export CHAINCODE_SERVER_ADDRESS=host.docker.internal:9999
export CHAINCODE_ID=$(weft chaincode package caas --path . --label asset-transfer --address ${CHAINCODE_SERVER_ADDRESS} --archive asset-transfer.tgz --quiet)
export CORE_PEER_LOCALMSPID=org1MSP
export CORE_PEER_MSPCONFIGPATH=$CFG/_msp/org1/org1admin/msp
export CORE_PEER_ADDRESS=org1peer-api.127-0-0-1.nip.io:8080
export CORE_PEER_CLIENT_CONNTIMEOUT=15s
export CORE_PEER_DELIVERYCLIENT_CONNTIMEOUT=15s
export ORDERER_ENDPOINT=orderer-api.127-0-0-1.nip.io:8080
echo "CHAINCODE_ID=${CHAINCODE_ID}"
set -x && peer lifecycle chaincode install asset-transfer.tgz && { set +x; } 2>/dev/null
echo
set -x && peer lifecycle chaincode approveformyorg --channelID mychannel -o $ORDERER_ENDPOINT --name asset-transfer -v 0 --package-id $CHAINCODE_ID --sequence 1 --connTimeout 15s && { set +x; } 2>/dev/null
echo
set -x && peer lifecycle chaincode commit --channelID mychannel -o $ORDERER_ENDPOINT --name asset-transfer -v 0 --sequence 1 --connTimeout 15s && { set +x; } 2>/dev/null
echo
set -x && peer lifecycle chaincode querycommitted --channelID=mychannel && { set +x; } 2>/dev/null
echo
popd
cat << CC_EOF >> $CFG/org1admin.env
export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999
export CHAINCODE_ID=${CHAINCODE_ID}
CC_EOF
echo "Added CHAINCODE_ID and CHAINCODE_SERVER_ADDRESS to org1admin.env"
echo
echo ' source $WORKSHOP_PATH/_cfg/uf/org1admin.env'
###############################################################################
# CLOUD NATIVE TARGETS #
###############################################################################
# Deploy the operator sample network and create a channel
cloud-network: cloud-network-down check-kube
infrastructure/sample-network/network up
# Tear down the operator sample network
cloud-network-down:
infrastructure/sample-network/network down
# Create 'mychannel'
cloud-channel:
infrastructure/sample-network/network channel create
# Check that the cloud setup has been performed
check-setup: check
# Check that the k8s API controller is ready
check-kube: check-setup
checks/check-kube.sh
# Check that the sample network and channel have been deployed
check-network: check-kube
checks/check-network.sh
# Check that the smart contract has been deployed
check-chaincode: check-network
checks/check-chaincode.sh
# Create 'rest-easy'
cloud-rest-easy:
infrastructure/sample-network/network rest-easy
# Create 'frontend'
cloud-frontend:
infrastructure/sample-network/network frontend
###############################################################################
# ANSIBLE PLAYBOOK TARGETS #
###############################################################################
ansible_image := env_var_or_default("ANSIBLE_IMAGE", "ghcr.io/hyperledger-labs/fabric-ansible:latest")
namespace := env_var_or_default("WORKSHOP_NAMESPACE", "fabricinfra")
# just set up everything with Ansible
ansible-doit: ansible-review-config ansible-operator ansible-console ansible-network
# Review the Ansible Blockchain Collection configuration in _cfg/
ansible-review-config:
#!/usr/bin/env bash
mkdir -p ${CWDIR}/_cfg
rm -rf ${CWDIR}/_cfg/* || true
cp ${CWDIR}/infrastructure/configuration/*.yml ${CWDIR}/_cfg
cat ${CWDIR}/infrastructure/configuration/operator-console-vars.yml | envsubst > ${CWDIR}/_cfg/operator-console-vars.yml
echo ""
echo ">> Fabric Common Configuration"
echo ""
cat ${CWDIR}/_cfg/fabric-common-vars.yml
echo ""
echo ">> Fabric Org1 Configuration"
echo ""
cat ${CWDIR}/_cfg/fabric-org1-vars.yml
echo ""
echo ">> Fabric Org2 Configuration"
echo ""
cat ${CWDIR}/_cfg/fabric-org2-vars.yml
echo ""
echo ">> Fabric Orderer Configuration"
echo ""
cat ${CWDIR}/_cfg/fabric-ordering-org-vars.yml
echo ""
echo ">> Fabric Operations Console Configuration"
echo ""
cat ${CWDIR}/_cfg/operator-console-vars.yml
echo ""
# Start the Kubernetes fabric-operator with the Ansible Blockchain Collection
ansible-ingress:
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
docker run \
--rm \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/_cfg:/_cfg \
-v $(pwd)/infrastructure/kind_console_ingress:/playbooks \
--network=host ${EXTRAS} \
--workdir /playbooks \
{{ansible_image}} \
ansible-playbook /playbooks/90-KIND-ingress.yml
# Start the Kubernetes fabric-operator with the Ansible Blockchain Collection
ansible-operator:
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
docker run \
--rm \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/_cfg:/_cfg \
-v $(pwd)/infrastructure/operator_console_playbooks:/playbooks ${EXTRAS} \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/01-operator-install.yml
# Start the Fabric Operations Console with the Ansible Blockchain Collection
ansible-console:
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
docker run \
--rm \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v $(pwd)/infrastructure/operator_console_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/02-console-install.yml
ansible-auth:
#!/usr/bin/env bash
set -ex -o pipefail
AUTH=$(curl -X POST https://{{namespace}}-hlf-console-console.{{ingress_domain}}:443/ak/api/v2/permissions/keys -u admin:password -k -H 'Content-Type: application/json' -d '{"roles": ["writer", "manager"],"description": "newkey"}')
KEY=$(echo $AUTH | jq .api_key | tr -d '"')
SECRET=$(echo $AUTH | jq .api_secret | tr -d '"')
echo "Writing authentication file for Ansible based IBP (Software) network building"
cat << EOF > $CWDIR/_cfg/auth-vars.yml
api_key: $KEY
api_endpoint: https://{{namespace}}-hlf-console-console.{{ingress_domain}}/
api_authtype: basic
api_secret: $SECRET
EOF
cat ${CWDIR}/_cfg/auth-vars.yml
# Build a sample Fabric network with the Ansible Blockchain Collection
ansible-network: ansible-auth
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
docker run \
--rm \
-u $(id -u) \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/infrastructure/fabric_network_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/00-complete.yml
# Bring down the sample network created with the Ansible Blockchain Collection
ansible-network-down:
#!/usr/bin/env bash
set -ex -o pipefail
kubectl delete namespace {{ namespace }} --ignore-not-found
# Build a chaincode package with Ansible Blockchain Collection
ansible-build-chaincode:
#!/usr/bin/env bash
set -ex -o pipefail
pushd ${CWDIR}/contracts/asset-transfer-typescript
if [ "{{cluster_runtime}}" = "openshift" ]; then
export IMAGE_NAME="{{namespace}}/{{chaincode_name}}"
else
export IMAGE_NAME="{{chaincode_name}}"
fi
DOCKER_BUILDKIT=1 docker build -t {{external_repo_endpoint}}/${IMAGE_NAME} . --target k8s
docker push {{external_repo_endpoint}}/${IMAGE_NAME}
# note the double { } for escaping
export IMG_SHA=$(docker inspect --format='{{{{index .RepoDigests 0}}' {{external_repo_endpoint}}/${IMAGE_NAME} | cut -d'@' -f2)
weft chaincode package k8s --name {{internal_repo_endpoint}}/${IMAGE_NAME} --digest ${IMG_SHA} --label {{chaincode_name}}
mv {{chaincode_name}}.tgz ${CWDIR}/_cfg
popd
# Deploy a chaincode package with the Ansible Blockchain Collection
ansible-deploy-chaincode:
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
# cp ${CWDIR}/contracts/asset-transfer-typescript/asset-transfer-chaincode-vars.yml ${CWDIR}/_cfg
docker run \
--rm \
-u $(id -u) \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/infrastructure/production_chaincode_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/19-install-and-approve-chaincode.yml
docker run \
--rm \
-u $(id -u) \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/infrastructure/production_chaincode_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/20-install-and-approve-chaincode.yml
docker run \
--rm \
-u $(id -u) \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/infrastructure/production_chaincode_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/21-commit-chaincode.yml
# Creates a new identity for an application to use
ansible-ready-application:
#!/usr/bin/env bash
set -ex -o pipefail
export EXTRAS=""
if [ -f "/_cfg/k8s_context.yaml" ]; then
export EXTRAS=" -e KUBECONFIG=/_cfg/k8s_context.yaml"
fi
docker run \
--rm \
-u $(id -u) \
-v ${HOME}/.kube/:/home/hlf-user/.kube/ \
-v ${CWDIR}/infrastructure/production_chaincode_playbooks:/playbooks ${EXTRAS} \
-v ${CWDIR}/_cfg:/_cfg \
--network=host \
{{ansible_image}} \
ansible-playbook /playbooks/22-register-application.yml