mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
Run a basic-asset-transfer CI test on Kubernetes (#637)
Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>
This commit is contained in:
parent
19b8f6bcbd
commit
fee6a44fcd
5 changed files with 212 additions and 14 deletions
|
|
@ -11,29 +11,35 @@ import { promises as fs } from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { TextDecoder } from 'util';
|
import { TextDecoder } from 'util';
|
||||||
|
|
||||||
const channelName = 'mychannel';
|
const channelName = envOrDefault('CHANNEL_NAME', 'mychannel');
|
||||||
const chaincodeName = 'basic';
|
const chaincodeName = envOrDefault('CHAINCODE_NAME', 'basic');
|
||||||
const mspId = 'Org1MSP';
|
const mspId = envOrDefault('MSP_ID', 'Org1MSP');
|
||||||
|
|
||||||
// Path to crypto materials.
|
// Path to crypto materials.
|
||||||
const cryptoPath = path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com');
|
const cryptoPath = envOrDefault('CRYPTO_PATH', path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com'));
|
||||||
|
|
||||||
// Path to user private key directory.
|
// Path to user private key directory.
|
||||||
const keyDirectoryPath = path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'keystore');
|
const keyDirectoryPath = envOrDefault('KEY_DIRECTORY_PATH', path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'keystore'));
|
||||||
|
|
||||||
// Path to user certificate.
|
// Path to user certificate.
|
||||||
const certPath = path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem');
|
const certPath = envOrDefault('CERT_PATH', path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem'));
|
||||||
|
|
||||||
// Path to peer tls certificate.
|
// Path to peer tls certificate.
|
||||||
const tlsCertPath = path.resolve(cryptoPath, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt');
|
const tlsCertPath = envOrDefault('TLS_CERT_PATH', path.resolve(cryptoPath, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt'));
|
||||||
|
|
||||||
// Gateway peer endpoint.
|
// Gateway peer endpoint.
|
||||||
const peerEndpoint = 'localhost:7051';
|
const peerEndpoint = envOrDefault('PEER_ENDPOINT', 'localhost:7051');
|
||||||
|
|
||||||
|
// Gateway peer SSL host name override.
|
||||||
|
const peerHostAlias = envOrDefault('PEER_HOST_ALIAS', 'peer0.org1.example.com');
|
||||||
|
|
||||||
const utf8Decoder = new TextDecoder();
|
const utf8Decoder = new TextDecoder();
|
||||||
const assetId = `asset${Date.now()}`;
|
const assetId = `asset${Date.now()}`;
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
|
|
||||||
|
await displayInputParameters();
|
||||||
|
|
||||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint.
|
// The gRPC client connection should be shared by all Gateway connections to this endpoint.
|
||||||
const client = await newGrpcConnection();
|
const client = await newGrpcConnection();
|
||||||
|
|
||||||
|
|
@ -86,13 +92,16 @@ async function main(): Promise<void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch(error => console.error('******** FAILED to run the application:', error));
|
main().catch(error => {
|
||||||
|
console.error('******** FAILED to run the application:', error);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
|
|
||||||
async function newGrpcConnection(): Promise<grpc.Client> {
|
async function newGrpcConnection(): Promise<grpc.Client> {
|
||||||
const tlsRootCert = await fs.readFile(tlsCertPath);
|
const tlsRootCert = await fs.readFile(tlsCertPath);
|
||||||
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
|
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
|
||||||
return new grpc.Client(peerEndpoint, tlsCredentials, {
|
return new grpc.Client(peerEndpoint, tlsCredentials, {
|
||||||
'grpc.ssl_target_name_override': 'peer0.org1.example.com',
|
'grpc.ssl_target_name_override': peerHostAlias,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,3 +214,25 @@ async function updateNonExistentAsset(contract: Contract): Promise<void>{
|
||||||
console.log('*** Successfully caught the error: \n', error);
|
console.log('*** Successfully caught the error: \n', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* envOrDefault() will return the value of an environment variable, or a default value if the variable is undefined.
|
||||||
|
*/
|
||||||
|
function envOrDefault(key: string, defaultValue: string): string {
|
||||||
|
return process.env[key] || defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* displayInputParameters() will print the global scope parameters used by the main driver routine.
|
||||||
|
*/
|
||||||
|
async function displayInputParameters(): Promise<void> {
|
||||||
|
console.log(`channelName: ${channelName}`);
|
||||||
|
console.log(`chaincodeName: ${chaincodeName}`);
|
||||||
|
console.log(`mspId: ${mspId}`);
|
||||||
|
console.log(`cryptoPath: ${cryptoPath}`);
|
||||||
|
console.log(`keyDirectoryPath: ${keyDirectoryPath}`);
|
||||||
|
console.log(`certPath: ${certPath}`);
|
||||||
|
console.log(`tlsCertPath: ${tlsCertPath}`);
|
||||||
|
console.log(`peerEndpoint: ${peerEndpoint}`);
|
||||||
|
console.log(`peerHostAlias: ${peerHostAlias}`);
|
||||||
|
}
|
||||||
|
|
@ -127,6 +127,20 @@ jobs:
|
||||||
workingDirectory: test-network
|
workingDirectory: test-network
|
||||||
displayName: Run Test Network Basic Chaincode
|
displayName: Run Test Network Basic Chaincode
|
||||||
|
|
||||||
|
- job: KubeTestNetworkBasic
|
||||||
|
displayName: Kube Test Network Basic
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
Docker-Typescript:
|
||||||
|
CLIENT_LANGUAGE: typescript
|
||||||
|
steps:
|
||||||
|
- template: templates/install-k8s-deps.yml
|
||||||
|
- script: ../ci/scripts/run-k8s-test-network-basic.sh
|
||||||
|
workingDirectory: test-network-k8s
|
||||||
|
displayName: Run Kubernetes Test Network Basic Asset Transfer
|
||||||
|
|
||||||
- job: TestNetworkLedger
|
- job: TestNetworkLedger
|
||||||
displayName: Test Network
|
displayName: Test Network
|
||||||
pool:
|
pool:
|
||||||
|
|
|
||||||
144
ci/scripts/run-k8s-test-network-basic.sh
Executable file
144
ci/scripts/run-k8s-test-network-basic.sh
Executable file
|
|
@ -0,0 +1,144 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Copyright IBM Corp All Rights Reserved
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Test matrix parameters
|
||||||
|
export CONTAINER_CLI=${CONTAINER_CLI:-docker}
|
||||||
|
export CLIENT_LANGUAGE=${CLIENT_LANGUAGE:-typescript}
|
||||||
|
|
||||||
|
# Fabric version and Docker registry source: use the latest stable tag image from JFrog
|
||||||
|
export FABRIC_VERSION=${FABRIC_VERSION:-2.4}
|
||||||
|
export TEST_NETWORK_FABRIC_CONTAINER_REGISTRY=hyperledger-fabric.jfrog.io
|
||||||
|
export TEST_NETWORK_FABRIC_VERSION=amd64-${FABRIC_VERSION}-stable
|
||||||
|
export TEST_NETWORK_FABRIC_CA_VERSION=amd64-${FABRIC_VERSION}-stable
|
||||||
|
|
||||||
|
# test-network-k8s parameters
|
||||||
|
export TEST_TAG=$(git describe)
|
||||||
|
export TEST_NETWORK_KIND_CLUSTER_NAME=${TEST_NETWORK_KIND_CLUSTER_NAME:-kind}
|
||||||
|
export TEST_NETWORK_CHAINCODE_NAME=${TEST_NETWORK_CHAINCODE_NAME:-asset-transfer-basic}
|
||||||
|
export TEST_NETWORK_CHAINCODE_IMAGE=${TEST_NETWORK_CHAINCODE_NAME}:${TEST_TAG}
|
||||||
|
export TEST_NETWORK_CHAINCODE_PATH=${TEST_NETWORK_CHAINCODE_PATH:-../asset-transfer-basic/chaincode-external}
|
||||||
|
|
||||||
|
# gateway client application parameters
|
||||||
|
export GATEWAY_CLIENT_APPLICATION_PATH=${GATEWAY_CLIENT_APPLICATION_PATH:-../asset-transfer-basic/application-gateway-${CLIENT_LANGUAGE}}
|
||||||
|
export CHANNEL_NAME=${TEST_NETWORK_CHANNEL_NAME:-mychannel}
|
||||||
|
export CHAINCODE_NAME=${TEST_NETWORK_CHAINCODE_NAME:-asset-transfer-basic}
|
||||||
|
export MSP_ID=${MSP_ID:-Org1MSP}
|
||||||
|
export CRYPTO_PATH=${CRYPTO_PATH:-../../test-network-k8s/build/organizations/peerOrganizations/org1.example.com}
|
||||||
|
export KEY_DIRECTORY_PATH=${KEY_DIRECTORY_PATH:-../../test-network-k8s/build/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore}
|
||||||
|
export CERT_PATH=${CERT_PATH:-../../test-network-k8s/build/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem}
|
||||||
|
export TLS_CERT_PATH=${TLS_CERT_PATH:-../../test-network-k8s/build/organizations/peerOrganizations/org1.example.com/msp/tlscacerts/org1-tls-ca.pem}
|
||||||
|
export PEER_ENDPOINT=${PEER_ENDPOINT:-localhost:7051}
|
||||||
|
export PEER_HOST_ALIAS=${PEER_HOST_ALIAS:-org1-peer1}
|
||||||
|
|
||||||
|
function print() {
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}${1}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function touteSuite() {
|
||||||
|
createCluster
|
||||||
|
buildChaincodeImage
|
||||||
|
}
|
||||||
|
|
||||||
|
function quitterLaScene() {
|
||||||
|
destroyCluster
|
||||||
|
scrubCCImages
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCluster() {
|
||||||
|
print "Initializing KIND Kubernetes cluster"
|
||||||
|
./network kind
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroyCluster() {
|
||||||
|
print "Destroying KIND Kubernetes cluster"
|
||||||
|
./network unkind
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildChaincodeImage() {
|
||||||
|
print "Building chaincode image $TEST_NETWORK_CHAINCODE_IMAGE"
|
||||||
|
${CONTAINER_CLI} build -t $TEST_NETWORK_CHAINCODE_IMAGE $TEST_NETWORK_CHAINCODE_PATH
|
||||||
|
|
||||||
|
# todo: work with local reg, or k3s, or KIND, or ...
|
||||||
|
kind load docker-image $TEST_NETWORK_CHAINCODE_IMAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrubCCImages() {
|
||||||
|
print "Scrubbing chaincode images"
|
||||||
|
${CONTAINER_CLI} rmi $TEST_NETWORK_CHAINCODE_IMAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNetwork() {
|
||||||
|
print "Launching network"
|
||||||
|
./network up
|
||||||
|
./network channel create
|
||||||
|
|
||||||
|
print "Opening gateway port-forward to 'localhost:7051'"
|
||||||
|
kubectl -n test-network port-forward svc/org1-peer1 7051:7051 &
|
||||||
|
|
||||||
|
print "Deploying chaincode"
|
||||||
|
./network chaincode deploy
|
||||||
|
|
||||||
|
print "Extracting certificates"
|
||||||
|
kubectl \
|
||||||
|
-n test-network \
|
||||||
|
exec deploy/org1-peer1 \
|
||||||
|
-c main \
|
||||||
|
-- tar zcf - -C /var/hyperledger/fabric organizations/peerOrganizations/org1.example.com \
|
||||||
|
| tar zxvf - -C ../test-network-k8s/build/
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopNetwork() {
|
||||||
|
pkill -f "port-forward"
|
||||||
|
|
||||||
|
print "Stopping network"
|
||||||
|
./network down
|
||||||
|
|
||||||
|
print "Cleaning client certificates"
|
||||||
|
rm -rf ../test-network-k8s/build/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up the suite with a KIND cluster
|
||||||
|
touteSuite
|
||||||
|
trap "quitterLaScene" EXIT
|
||||||
|
|
||||||
|
# invoke / query
|
||||||
|
createNetwork
|
||||||
|
|
||||||
|
print "Inserting and querying assets"
|
||||||
|
( ./network chaincode invoke '{"Args":["InitLedger"]}' \
|
||||||
|
&& sleep 5 \
|
||||||
|
&& ./network chaincode query '{"Args":["ReadAsset","asset1"]}' )
|
||||||
|
print "OK"
|
||||||
|
|
||||||
|
print "Running rest-easy test"
|
||||||
|
( ./network rest-easy \
|
||||||
|
&& sleep 5 \
|
||||||
|
&& export SAMPLE_APIKEY='97834158-3224-4CE7-95F9-A148C886653E' \
|
||||||
|
&& curl -s --header "X-Api-Key: ${SAMPLE_APIKEY}" "http://localhost/api/assets/asset1" | jq \
|
||||||
|
&& curl -s --insecure --header "X-Api-Key: ${SAMPLE_APIKEY}" "https://localhost/api/assets/asset1" | jq )
|
||||||
|
print "OK"
|
||||||
|
|
||||||
|
stopNetwork
|
||||||
|
|
||||||
|
# Run the basic-asset-transfer basic application
|
||||||
|
createNetwork
|
||||||
|
print "Running Gateway client application"
|
||||||
|
( pushd ${GATEWAY_CLIENT_APPLICATION_PATH} \
|
||||||
|
&& npm install \
|
||||||
|
&& npm start )
|
||||||
|
print "OK"
|
||||||
|
stopNetwork
|
||||||
|
|
||||||
|
# Run additional test ...
|
||||||
|
# Run additional test ...
|
||||||
|
# Run additional test ...
|
||||||
|
|
||||||
|
# destroyCluster will be invoked on EXIT trap handler at the end of this suite.
|
||||||
9
ci/templates/install-k8s-deps.yml
Normal file
9
ci/templates/install-k8s-deps.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
inputs:
|
||||||
|
versionSpec: $(NODE_VER)
|
||||||
|
displayName: Install Node.js
|
||||||
|
|
@ -91,8 +91,8 @@ function create_org1_local_MSP() {
|
||||||
fabric-ca-client register --id.name org1-peer2 --id.secret peerpw --id.type peer --url https://org1-ca --mspdir $FABRIC_CA_CLIENT_HOME/org1-ca/rcaadmin/msp
|
fabric-ca-client register --id.name org1-peer2 --id.secret peerpw --id.type peer --url https://org1-ca --mspdir $FABRIC_CA_CLIENT_HOME/org1-ca/rcaadmin/msp
|
||||||
fabric-ca-client register --id.name org1-admin --id.secret org1adminpw --id.type admin --url https://org1-ca --mspdir $FABRIC_CA_CLIENT_HOME/org1-ca/rcaadmin/msp --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert"
|
fabric-ca-client register --id.name org1-admin --id.secret org1adminpw --id.type admin --url https://org1-ca --mspdir $FABRIC_CA_CLIENT_HOME/org1-ca/rcaadmin/msp --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert"
|
||||||
|
|
||||||
fabric-ca-client enroll --url https://org1-peer1:peerpw@org1-ca --csr.hosts org1-peer1,org1-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/peers/org1-peer1.org1.example.com/msp
|
fabric-ca-client enroll --url https://org1-peer1:peerpw@org1-ca --csr.hosts localhost,org1-peer1,org1-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/peers/org1-peer1.org1.example.com/msp
|
||||||
fabric-ca-client enroll --url https://org1-peer2:peerpw@org1-ca --csr.hosts org1-peer2,org1-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/peers/org1-peer2.org1.example.com/msp
|
fabric-ca-client enroll --url https://org1-peer2:peerpw@org1-ca --csr.hosts localhost,org1-peer2,org1-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/peers/org1-peer2.org1.example.com/msp
|
||||||
fabric-ca-client enroll --url https://org1-admin:org1adminpw@org1-ca --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
|
fabric-ca-client enroll --url https://org1-admin:org1adminpw@org1-ca --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
|
||||||
|
|
||||||
cp /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/*_sk /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/server.key
|
cp /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/*_sk /var/hyperledger/fabric/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/server.key
|
||||||
|
|
@ -130,8 +130,8 @@ function create_org2_local_MSP() {
|
||||||
fabric-ca-client register --id.name org2-peer2 --id.secret peerpw --id.type peer --url https://org2-ca --mspdir $FABRIC_CA_CLIENT_HOME/org2-ca/rcaadmin/msp
|
fabric-ca-client register --id.name org2-peer2 --id.secret peerpw --id.type peer --url https://org2-ca --mspdir $FABRIC_CA_CLIENT_HOME/org2-ca/rcaadmin/msp
|
||||||
fabric-ca-client register --id.name org2-admin --id.secret org2adminpw --id.type admin --url https://org2-ca --mspdir $FABRIC_CA_CLIENT_HOME/org2-ca/rcaadmin/msp --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert"
|
fabric-ca-client register --id.name org2-admin --id.secret org2adminpw --id.type admin --url https://org2-ca --mspdir $FABRIC_CA_CLIENT_HOME/org2-ca/rcaadmin/msp --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert"
|
||||||
|
|
||||||
fabric-ca-client enroll --url https://org2-peer1:peerpw@org2-ca --csr.hosts org2-peer1,org2-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/peers/org2-peer1.org2.example.com/msp
|
fabric-ca-client enroll --url https://org2-peer1:peerpw@org2-ca --csr.hosts localhost,org2-peer1,org2-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/peers/org2-peer1.org2.example.com/msp
|
||||||
fabric-ca-client enroll --url https://org2-peer2:peerpw@org2-ca --csr.hosts org2-peer2,org2-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/peers/org2-peer2.org2.example.com/msp
|
fabric-ca-client enroll --url https://org2-peer2:peerpw@org2-ca --csr.hosts localhost,org2-peer2,org2-peer-gateway-svc --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/peers/org2-peer2.org2.example.com/msp
|
||||||
fabric-ca-client enroll --url https://org2-admin:org2adminpw@org2-ca --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
|
fabric-ca-client enroll --url https://org2-admin:org2adminpw@org2-ca --mspdir /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
|
||||||
|
|
||||||
cp /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/*_sk /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/server.key
|
cp /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/*_sk /var/hyperledger/fabric/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/server.key
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue