From e9b9477a31b9f75968784628949b2d0d183e36fe Mon Sep 17 00:00:00 2001 From: Bret Harrison Date: Fri, 28 Dec 2018 18:31:51 -0500 Subject: [PATCH] FAB-13372 Fabric-Samples return error msg Update the Balance Transfer to return the fabric error. The sample application was updated to both return the error in the REST response and to post the error to the log. The sample was updated with the 'channel.close()' so that users will note how to shutdown a channel and not hold connections open. Change-Id: I49f20a50340adff52cf57db00a121ffd75eb1827 Signed-off-by: Bret Harrison --- balance-transfer/app/create-channel.js | 33 ++++-- balance-transfer/app/install-chaincode.js | 30 +++-- balance-transfer/app/instantiate-chaincode.js | 111 +++++++++--------- balance-transfer/app/invoke-transaction.js | 88 ++++++++------ balance-transfer/app/join-channel.js | 19 ++- balance-transfer/app/query.js | 10 +- balance-transfer/app/update-anchor-peers.js | 19 ++- balance-transfer/testAPIs.sh | 13 +- 8 files changed, 184 insertions(+), 139 deletions(-) diff --git a/balance-transfer/app/create-channel.js b/balance-transfer/app/create-channel.js index 754d18a02c..974944028e 100644 --- a/balance-transfer/app/create-channel.js +++ b/balance-transfer/app/create-channel.js @@ -45,19 +45,32 @@ var createChannel = async function(channelName, channelConfigPath, username, org }; // send to orderer - var response = await client.createChannel(request) - logger.debug(' response ::%j', response); - if (response && response.status === 'SUCCESS') { - logger.debug('Successfully created the channel.'); - let response = { - success: true, - message: 'Channel \'' + channelName + '\' created Successfully' - }; - return response; + const result = await client.createChannel(request) + logger.debug(' result ::%j', result); + if (result) { + if (result.status === 'SUCCESS') { + logger.debug('Successfully created the channel.'); + const response = { + success: true, + message: 'Channel \'' + channelName + '\' created Successfully' + }; + return response; + } else { + logger.error('Failed to create the channel. status:' + result.status + ' reason:' + result.info); + const response = { + success: false, + message: 'Channel \'' + channelName + '\' failed to create status:' + result.status + ' reason:' + result.info + }; + return response; + } } else { logger.error('\n!!!!!!!!! Failed to create the channel \'' + channelName + '\' !!!!!!!!!\n\n'); - throw new Error('Failed to create the channel \'' + channelName + '\''); + const response = { + success: false, + message: 'Failed to create the channel \'' + channelName + '\'', + }; + return response; } } catch (err) { logger.error('Failed to initialize the channel: ' + err.stack ? err.stack : err); diff --git a/balance-transfer/app/install-chaincode.js b/balance-transfer/app/install-chaincode.js index 2bc8bbb706..ea6c4124c5 100644 --- a/balance-transfer/app/install-chaincode.js +++ b/balance-transfer/app/install-chaincode.js @@ -47,23 +47,17 @@ var installChaincode = async function(peers, chaincodeName, chaincodePath, // lets have a look at the responses to see if they are // all good, if good they will also include signatures // required to be committed - var all_good = true; - for (var i in proposalResponses) { - let one_good = false; - if (proposalResponses && proposalResponses[i].response && - proposalResponses[i].response.status === 200) { - one_good = true; + for (const i in proposalResponses) { + if (proposalResponses[i] instanceof Error) { + error_message = util.format('install proposal resulted in an error :: %s', proposalResponses[i].toString()); + logger.error(error_message); + } else if (proposalResponses[i].response && proposalResponses[i].response.status === 200) { logger.info('install proposal was good'); } else { - logger.error('install proposal was bad %j',proposalResponses.toJSON()); + all_good = false; + error_message = util.format('install proposal was bad for an unknown reason %j', proposalResponses[i]); + logger.error(error_message); } - all_good = all_good & one_good; - } - if (all_good) { - logger.info('Successfully sent install Proposal and received ProposalResponse'); - } else { - error_message = 'Failed to send install Proposal or receive valid response. Response null or status is not 200' - logger.error(error_message); } } catch(error) { logger.error('Failed to install due to error: ' + error.stack ? error.stack : error); @@ -74,7 +68,7 @@ var installChaincode = async function(peers, chaincodeName, chaincodePath, let message = util.format('Successfully installed chaincode'); logger.info(message); // build a response to send back to the REST caller - let response = { + const response = { success: true, message: message }; @@ -82,7 +76,11 @@ var installChaincode = async function(peers, chaincodeName, chaincodePath, } else { let message = util.format('Failed to install due to:%s',error_message); logger.error(message); - throw new Error(message); + const response = { + success: false, + message: message + }; + return response; } }; exports.installChaincode = installChaincode; diff --git a/balance-transfer/app/instantiate-chaincode.js b/balance-transfer/app/instantiate-chaincode.js index aa8e040481..022043d7a8 100644 --- a/balance-transfer/app/instantiate-chaincode.js +++ b/balance-transfer/app/instantiate-chaincode.js @@ -14,34 +14,35 @@ * limitations under the License. */ 'use strict'; -var util = require('util'); -var helper = require('./helper.js'); -var logger = helper.getLogger('instantiate-chaincode'); +const util = require('util'); +const helper = require('./helper.js'); +const logger = helper.getLogger('instantiate-chaincode'); -var instantiateChaincode = async function(peers, channelName, chaincodeName, chaincodeVersion, functionName, chaincodeType, args, username, org_name) { +const instantiateChaincode = async function(peers, channelName, chaincodeName, chaincodeVersion, functionName, chaincodeType, args, username, org_name) { logger.debug('\n\n============ Instantiate chaincode on channel ' + channelName + ' ============\n'); - var error_message = null; - + let error_message = null; + let client = null; + let channel = null; try { // first setup the client for this org - var client = await helper.getClientForOrg(org_name, username); + client = await helper.getClientForOrg(org_name, username); logger.debug('Successfully got the fabric client for the organization "%s"', org_name); - var channel = client.getChannel(channelName); + channel = client.getChannel(channelName); if(!channel) { let message = util.format('Channel %s was not defined in the connection profile', channelName); logger.error(message); throw new Error(message); } - var tx_id = client.newTransactionID(true); // Get an admin based transactionID + const tx_id = client.newTransactionID(true); // Get an admin based transactionID // An admin based transactionID will // indicate that admin identity should // be used to sign the proposal request. // will need the transaction ID string for the event registration later - var deployId = tx_id.getTransactionID(); + const deployId = tx_id.getTransactionID(); // send proposal to endorser - var request = { + const request = { targets : peers, chaincodeId: chaincodeName, chaincodeType: chaincodeType, @@ -70,23 +71,24 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha // the returned object has both the endorsement results // and the actual proposal, the proposal will be needed // later when we send a transaction to the orderer - var proposalResponses = results[0]; - var proposal = results[1]; + const proposalResponses = results[0]; + const proposal = results[1]; - // lets have a look at the responses to see if they are - // all good, if good they will also include signatures - // required to be committed - var all_good = true; - for (var i in proposalResponses) { - let one_good = false; - if (proposalResponses && proposalResponses[i].response && - proposalResponses[i].response.status === 200) { - one_good = true; + // look at the responses to see if they are all are good + // response will also include signatures required to be committed + let all_good = true; + for (const i in proposalResponses) { + if (proposalResponses[i] instanceof Error) { + all_good = false; + error_message = util.format('instantiate proposal resulted in an error :: %s', proposalResponses[i].toString()); + logger.error(error_message); + } else if (proposalResponses[i].response && proposalResponses[i].response.status === 200) { logger.info('instantiate proposal was good'); } else { - logger.error('instantiate proposal was bad'); + all_good = false; + error_message = util.format('instantiate proposal was bad for an unknown reason %j', proposalResponses[i]); + logger.error(error_message); } - all_good = all_good & one_good; } if (all_good) { @@ -97,8 +99,8 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha // wait for the channel-based event hub to tell us that the // instantiate transaction was committed on the peer - var promises = []; - let event_hubs = channel.getChannelEventHubsForOrg(); + const promises = []; + const event_hubs = channel.getChannelEventHubsForOrg(); logger.debug('found %s eventhubs for this organization %s',event_hubs.length, org_name); event_hubs.forEach((eh) => { let instantiateEventPromise = new Promise((resolve, reject) => { @@ -138,22 +140,22 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha promises.push(instantiateEventPromise); }); - var orderer_request = { + const orderer_request = { txId: tx_id, // must include the transaction id so that the outbound - // transaction to the orderer will be signed by the admin - // id as was the proposal above, notice that transactionID - // generated above was based on the admin id not the current - // user assigned to the 'client' instance. + // transaction to the orderer will be signed by the admin id + // the same as the proposal above, notice that transactionID + // generated above was based on the admin id not the current + // user assigned to the 'client' instance. proposalResponses: proposalResponses, proposal: proposal }; - var sendPromise = channel.sendTransaction(orderer_request); + const sendPromise = channel.sendTransaction(orderer_request); // put the send to the orderer last so that the events get registered and // are ready for the orderering and committing promises.push(sendPromise); - let results = await Promise.all(promises); + const results = await Promise.all(promises); logger.debug(util.format('------->>> R E S P O N S E : %j', results)); - let response = results.pop(); // orderer results are last in the results + const response = results.pop(); // orderer results are last in the results if (response.status === 'SUCCESS') { logger.info('Successfully sent transaction to the orderer.'); } else { @@ -162,9 +164,9 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha } // now see what each of the event hubs reported - for(let i in results) { - let event_hub_result = results[i]; - let event_hub = event_hubs[i]; + for(const i in results) { + const event_hub_result = results[i]; + const event_hub = event_hubs[i]; logger.debug('Event results for event hub :%s',event_hub.getPeerAddr()); if(typeof event_hub_result === 'string') { logger.debug(event_hub_result); @@ -173,30 +175,31 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha logger.debug(event_hub_result.toString()); } } - } else { - error_message = util.format('Failed to send Proposal and receive all good ProposalResponse'); - logger.debug(error_message); } } catch (error) { logger.error('Failed to send instantiate due to error: ' + error.stack ? error.stack : error); error_message = error.toString(); + } finally { + if (channel) { + channel.close(); + } } - if (!error_message) { - let message = util.format( - 'Successfully instantiate chaincode in organization %s to the channel \'%s\'', - org_name, channelName); - logger.info(message); - // build a response to send back to the REST caller - let response = { - success: true, - message: message - }; - return response; - } else { - let message = util.format('Failed to instantiate. cause:%s',error_message); + let success = true; + let message = util.format('Successfully instantiate chaincode in organization %s to the channel \'%s\'', org_name, channelName); + if (error_message) { + message = util.format('Failed to instantiate the chaincode. cause:%s',error_message); + success = false; logger.error(message); - throw new Error(message); + } else { + logger.info(message); } + + // build a response to send back to the REST caller + const response = { + success: success, + message: message + }; + return response; }; exports.instantiateChaincode = instantiateChaincode; diff --git a/balance-transfer/app/invoke-transaction.js b/balance-transfer/app/invoke-transaction.js index a217620995..5cb2648007 100644 --- a/balance-transfer/app/invoke-transaction.js +++ b/balance-transfer/app/invoke-transaction.js @@ -14,30 +14,32 @@ * limitations under the License. */ 'use strict'; -var util = require('util'); -var helper = require('./helper.js'); -var logger = helper.getLogger('invoke-chaincode'); +const util = require('util'); +const helper = require('./helper.js'); +const logger = helper.getLogger('invoke-chaincode'); -var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, args, username, org_name) { +const invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, args, username, org_name) { logger.debug(util.format('\n============ invoke transaction on channel %s ============\n', channelName)); - var error_message = null; - var tx_id_string = null; + let error_message = null; + let tx_id_string = null; + let client = null; + let channel = null; try { // first setup the client for this org - var client = await helper.getClientForOrg(org_name, username); + client = await helper.getClientForOrg(org_name, username); logger.debug('Successfully got the fabric client for the organization "%s"', org_name); - var channel = client.getChannel(channelName); + channel = client.getChannel(channelName); if(!channel) { let message = util.format('Channel %s was not defined in the connection profile', channelName); logger.error(message); throw new Error(message); } - var tx_id = client.newTransactionID(); + const tx_id = client.newTransactionID(); // will need the transaction ID string for the event registration later tx_id_string = tx_id.getTransactionID(); // send proposal to endorser - var request = { + const request = { targets: peerNames, chaincodeId: chaincodeName, fcn: fcn, @@ -51,23 +53,24 @@ var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, // the returned object has both the endorsement results // and the actual proposal, the proposal will be needed // later when we send a transaction to the orderer - var proposalResponses = results[0]; - var proposal = results[1]; + const proposalResponses = results[0]; + const proposal = results[1]; - // lets have a look at the responses to see if they are - // all good, if good they will also include signatures - // required to be committed - var all_good = true; - for (var i in proposalResponses) { - let one_good = false; - if (proposalResponses && proposalResponses[i].response && - proposalResponses[i].response.status === 200) { - one_good = true; + // look at the responses to see if they are all are good + // response will also include signatures required to be committed + let all_good = true; + for (const i in proposalResponses) { + if (proposalResponses[i] instanceof Error) { + all_good = false; + error_message = util.format('invoke chaincode proposal resulted in an error :: %s', proposalResponses[i].toString()); + logger.error(error_message); + } else if (proposalResponses[i].response && proposalResponses[i].response.status === 200) { logger.info('invoke chaincode proposal was good'); } else { - logger.error('invoke chaincode proposal was bad'); + all_good = false; + error_message = util.format('invoke chaincode proposal failed for an unknown reason %j', proposalResponses[i]); + logger.error(error_message); } - all_good = all_good & one_good; } if (all_good) { @@ -78,7 +81,7 @@ var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, // wait for the channel-based event hub to tell us // that the commit was good or bad on each peer in our organization - var promises = []; + const promises = []; let event_hubs = channel.getChannelEventHubsForOrg(); event_hubs.forEach((eh) => { logger.debug('invokeEventPromise - setting up event'); @@ -118,12 +121,12 @@ var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, promises.push(invokeEventPromise); }); - var orderer_request = { + const orderer_request = { txId: tx_id, proposalResponses: proposalResponses, proposal: proposal }; - var sendPromise = channel.sendTransaction(orderer_request); + const sendPromise = channel.sendTransaction(orderer_request); // put the send to the orderer last so that the events get registered and // are ready for the orderering and committing promises.push(sendPromise); @@ -149,27 +152,34 @@ var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, logger.debug(event_hub_result.toString()); } } - } else { - error_message = util.format('Failed to send Proposal and receive all good ProposalResponse'); - logger.debug(error_message); } } catch (error) { logger.error('Failed to invoke due to error: ' + error.stack ? error.stack : error); error_message = error.toString(); + } finally { + if (channel) { + channel.close(); + } } - if (!error_message) { - let message = util.format( - 'Successfully invoked the chaincode %s to the channel \'%s\' for transaction ID: %s', - org_name, channelName, tx_id_string); - logger.info(message); - - return tx_id_string; - } else { - let message = util.format('Failed to invoke chaincode. cause:%s',error_message); + let success = true; + let message = util.format( + 'Successfully invoked the chaincode %s to the channel \'%s\' for transaction ID: %s', + org_name, channelName, tx_id_string); + if (error_message) { + message = util.format('Failed to invoke chaincode. cause:%s',error_message); + success = false; logger.error(message); - throw new Error(message); + } else { + logger.info(message); } + + // build a response to send back to the REST caller + const response = { + success: success, + message: message + }; + return response; }; exports.invokeChaincode = invokeChaincode; diff --git a/balance-transfer/app/join-channel.js b/balance-transfer/app/join-channel.js index b5eedfe9ad..c050f74865 100644 --- a/balance-transfer/app/join-channel.js +++ b/balance-transfer/app/join-channel.js @@ -66,12 +66,14 @@ var joinChannel = async function(channel_name, peers, username, org_name) { // then each peer results for(let i in peers_results) { let peer_result = peers_results[i]; - if(peer_result.response && peer_result.response.status == 200) { + if (peer_result instanceof Error) { + error_message = util.format('Failed to join peer to the channel with error :: %s', peer_result.toString()); + logger.error(error_message); + } else if(peer_result.response && peer_result.response.status == 200) { logger.info('Successfully joined peer to the channel %s',channel_name); } else { - let message = util.format('Failed to join peer to the channel %s',channel_name); - error_message = message; - logger.error(message); + error_message = util.format('Failed to join peer to the channel %s',channel_name); + logger.error(error_message); } } } catch(error) { @@ -90,7 +92,7 @@ var joinChannel = async function(channel_name, peers, username, org_name) { org_name, channel_name); logger.info(message); // build a response to send back to the REST caller - let response = { + const response = { success: true, message: message }; @@ -98,7 +100,12 @@ var joinChannel = async function(channel_name, peers, username, org_name) { } else { let message = util.format('Failed to join all peers to channel. cause:%s',error_message); logger.error(message); - throw new Error(message); + // build a response to send back to the REST caller + const response = { + success: false, + message: message + }; + return response; } }; exports.joinChannel = joinChannel; diff --git a/balance-transfer/app/query.js b/balance-transfer/app/query.js index 11a5b7a261..a0d3b055f7 100644 --- a/balance-transfer/app/query.js +++ b/balance-transfer/app/query.js @@ -18,11 +18,13 @@ var helper = require('./helper.js'); var logger = helper.getLogger('Query'); var queryChaincode = async function(peer, channelName, chaincodeName, args, fcn, username, org_name) { + let client = null; + let channel = null; try { // first setup the client for this org - var client = await helper.getClientForOrg(org_name, username); + client = await helper.getClientForOrg(org_name, username); logger.debug('Successfully got the fabric client for the organization "%s"', org_name); - var channel = client.getChannel(channelName); + channel = client.getChannel(channelName); if(!channel) { let message = util.format('Channel %s was not defined in the connection profile', channelName); logger.error(message); @@ -51,6 +53,10 @@ var queryChaincode = async function(peer, channelName, chaincodeName, args, fcn, } catch(error) { logger.error('Failed to query due to error: ' + error.stack ? error.stack : error); return error.toString(); + } finally { + if (channel) { + channel.close(); + } } }; var getBlockByNumber = async function(peer, channelName, blockNumber, username, org_name) { diff --git a/balance-transfer/app/update-anchor-peers.js b/balance-transfer/app/update-anchor-peers.js index aa961c87c7..da59ece901 100644 --- a/balance-transfer/app/update-anchor-peers.js +++ b/balance-transfer/app/update-anchor-peers.js @@ -50,7 +50,7 @@ var updateAnchorPeers = async function(channelName, configUpdatePath, username, event_hubs.forEach((eh) => { let anchorUpdateEventPromise = new Promise((resolve, reject) => { logger.debug('anchorUpdateEventPromise - setting up event'); - let event_timeout = setTimeout(() => { + const event_timeout = setTimeout(() => { let message = 'REQUEST_TIMEOUT:' + eh.getPeerAddr(); logger.error(message); eh.disconnect(); @@ -83,8 +83,13 @@ var updateAnchorPeers = async function(channelName, configUpdatePath, username, logger.debug(util.format('------->>> R E S P O N S E : %j', results)); let response = results.pop(); // orderer results are last in the results - if (response && response.status === 'SUCCESS') { - logger.info('Successfully update anchor peers to the channel %s', channelName); + if (response) { + if (response.status === 'SUCCESS') { + logger.info('Successfully update anchor peers to the channel %s', channelName); + } else { + error_message = util.format('Failed to update anchor peers to the channel %s with status: %s reason: %s', channelName, response.status, response.info); + logger.error(error_message); + } } else { error_message = util.format('Failed to update anchor peers to the channel %s', channelName); logger.error(error_message); @@ -99,7 +104,7 @@ var updateAnchorPeers = async function(channelName, configUpdatePath, username, 'Successfully update anchor peers in organization %s to the channel \'%s\'', org_name, channelName); logger.info(message); - let response = { + const response = { success: true, message: message }; @@ -107,7 +112,11 @@ var updateAnchorPeers = async function(channelName, configUpdatePath, username, } else { let message = util.format('Failed to update anchor peers. cause:%s',error_message); logger.error(message); - throw new Error(message); + const response = { + success: false, + message: message + }; + return response; } }; diff --git a/balance-transfer/testAPIs.sh b/balance-transfer/testAPIs.sh index a8ec82bc9d..6526f3f6fe 100755 --- a/balance-transfer/testAPIs.sh +++ b/balance-transfer/testAPIs.sh @@ -185,16 +185,15 @@ echo echo "POST invoke chaincode on peers of Org1 and Org2" echo -TRX_ID=$(curl -s -X POST \ +curl -s -X POST \ http://localhost:4000/channels/mychannel/chaincodes/mycc \ -H "authorization: Bearer $ORG1_TOKEN" \ -H "content-type: application/json" \ - -d '{ - "peers": ["peer0.org1.example.com","peer0.org2.example.com"], - "fcn":"move", - "args":["a","b","10"] -}') -echo "Transaction ID is $TRX_ID" + -d "{ + \"peers\": [\"peer0.org1.example.com\",\"peer0.org2.example.com\"], + \"fcn\":\"move\", + \"args\":[\"a\",\"b\",\"10\"] +}" echo echo