I have built a Hyperledger Fabric Network and the network is set up fine. The chaincode has also been deployed. Now, I want to call a function of the chaincode. If I have to do it via terminal, then it goes like:
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["a0", "b0", "c0", "d0", "e0"]}'
This works perfectly fine. However, I want to call this function from a shell script where the arguments of the functions would be variables. This shell script file be called by another shell script. Hence, my shell script file looks like this:
#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'
}
invokeCC $1 $2 $3 $4 $5
It is eveident the term:
'{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'
is taken as a whole string and the variables can't be passed. Therefore, I tried a variant:
#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051
QUOTE="'"
args="{\"function\":\"StorePacketData\",\"Args\":[\"$arg1\", \"$arg2\", \"$arg3\", \"$arg4\", \"$arg5\"]}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c $QUOTE$args$QUOTE
}
invokeCC $1 $2 $3 $4 $5
This gives error as well which is
Error: chaincode argument error: invalid character '\'' looking for beginning of value
I know that I am going wrong in the second method but I don't know what else can be done.
Please suggest what I should do here to invoke the chaincode. Let me know if I need to provide any other information.
Thanks in advance!
CodePudding user response:
To generate well-formed, syntactically-valid JSON with an arbitrary list of command-line arguments, use jq
version 1.6 with $ARGS.positional
:
#!/usr/bin/env bash
invokeCC() {
args=$(jq '{"function":"StorePacketData", "Args": $ARGS.positional}' --args "$@")
peer chaincode invoke ... --args "$args"
}
invokeCC "$@"
CodePudding user response:
As @Charles Duffy suggested, I used jq
for passing the argument. So, I changed my shell script to this:
#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051
echo hello
args=$(jq \
-n --arg val1 "$arg1" \
-n --arg val2 "$arg2" \
-n --arg val3 "$arg3" \
-n --arg val4 "$arg4" \
-n --arg val5 "$arg5" \
'{"function":"StorePacketData", "Args": [$val1, $val2, $val3, $val4, $val5]}'
)
echo $args
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "$args"
}
invokeCC "$1" "$2" "$3" "$4" "$5"
This worked absolutely fine. However, the solution suggested by @Charles Duffy is a much better one.