Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 117a00f

Browse files
committed
Fix issue installing chaincode package
Client.installChaincode is supposed to support installing both from source (which creates a chaincode package behind the scenes) as well as installing an existing package. The code was wrapping an existing package as as a ChaincodeDeploymentSpec rather than just using the package bytes directly when invoking install. This fixes that issue and adds a unit test as well. Fixes FABN-855 Change-Id: Ie8d5b7205e6248600bd80188169871d871702a9e Signed-off-by: Gari Singh <gari.r.singh@gmail.com>
1 parent 36710ae commit 117a00f

File tree

4 files changed

+175
-129
lines changed

4 files changed

+175
-129
lines changed

fabric-client/lib/Client.js

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -985,36 +985,15 @@ const Client = class extends BaseClient {
985985
throw new Error(error_msg);
986986
}
987987

988-
const ccSpec = {
989-
type: clientUtils.translateCCType(request.chaincodeType),
990-
chaincode_id: {
991-
name: request.chaincodeId,
992-
path: request.chaincodePath,
993-
version: request.chaincodeVersion
994-
}
995-
};
996-
logger.debug(`installChaincode - ccSpec ${JSON.stringify(ccSpec)} `);
997-
998-
// step 2: construct the ChaincodeDeploymentSpec
999-
const chaincodeDeploymentSpec = new _ccProto.ChaincodeDeploymentSpec();
1000-
chaincodeDeploymentSpec.setChaincodeSpec(ccSpec);
1001-
1002-
const data = await _getChaincodePackageData(request, this.isDevMode());
1003-
// DATA may or may not be present depending on devmode settings
1004-
if (data) {
1005-
chaincodeDeploymentSpec.setCodePackage(data);
1006-
logger.debug('installChaincode - found packaged data');
1007-
}
1008-
logger.debug(`installChaincode - sending deployment spec ${chaincodeDeploymentSpec} `);
1009-
988+
const cdsBytes = await _getChaincodeDeploymentSpec(request, this.isDevMode());
1010989
// TODO add ESCC/VSCC info here ??????
1011990
const lcccSpec = {
1012-
type: ccSpec.type,
991+
type: clientUtils.translateCCType(request.chaincodeType),
1013992
chaincode_id: {
1014993
name: Constants.LSCC
1015994
},
1016995
input: {
1017-
args: [Buffer.from('install', 'utf8'), chaincodeDeploymentSpec.toBuffer()]
996+
args: [Buffer.from('install', 'utf8'), cdsBytes]
1018997
}
1019998
};
1020999

@@ -1683,15 +1662,38 @@ function readFile(path) {
16831662
});
16841663
}
16851664

1686-
// internal utility method to get the chaincodePackage data in bytes
1687-
async function _getChaincodePackageData(request, devMode) {
1688-
if (!request.chaincodePackage) {
1689-
logger.debug('_getChaincodePackageData - build package with chaincodepath %s, chaincodeType %s, devMode %s, metadataPath %s',
1690-
request.chaincodePath, request.chaincodeType, devMode, request.metadataPath);
1691-
return Packager.package(request.chaincodePath, request.chaincodeType, devMode, request.metadataPath);
1692-
} else {
1693-
logger.debug('_getChaincodePackageData - working with included chaincodePackage');
1665+
// internal utility to get the serialized deployment spec for installing chaincode
1666+
async function _getChaincodeDeploymentSpec(request, devMode) {
1667+
1668+
if (request.chaincodePackage && Buffer.isBuffer(request.chaincodePackage)) {
1669+
logger.debug('installChaincode - using included package');
16941670
return request.chaincodePackage;
1671+
} else {
1672+
return new Promise((resolve, reject) => {
1673+
return Packager.package(request.chaincodePath, request.chaincodeType, devMode)
1674+
.then((data) => {
1675+
let ccSpec = {
1676+
type: clientUtils.translateCCType(request.chaincodeType),
1677+
chaincode_id: {
1678+
name: request.chaincodeId,
1679+
path: request.chaincodePath,
1680+
version: request.chaincodeVersion
1681+
}
1682+
};
1683+
logger.debug('installChaincode - ccSpec %s ', JSON.stringify(ccSpec));
1684+
let chaincodeDeploymentSpec = new _ccProto.ChaincodeDeploymentSpec();
1685+
chaincodeDeploymentSpec.setChaincodeSpec(ccSpec);
1686+
// DATA may or may not be present depending on devmode settings
1687+
if (data) {
1688+
chaincodeDeploymentSpec.setCodePackage(data);
1689+
logger.debug('installChaincode - created new package');
1690+
}
1691+
resolve(chaincodeDeploymentSpec.toBuffer());
1692+
})
1693+
.catch((err) => {
1694+
reject(err);
1695+
});
1696+
});
16951697
}
16961698
}
16971699

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"elliptic": "^6.3.2",
2929
"eslint": "^5.1.0",
3030
"fabric-ca-client": "file:./fabric-ca-client",
31-
"fabric-client": "file:./fabric-client",
32-
"fabric-network": "file:./fabric-network",
31+
"fabric-client": "file:./fabric-client",
32+
"fabric-network": "file:./fabric-network",
3333
"fs-extra": "^6.0.1",
3434
"gulp": "^3.9.1",
3535
"gulp-add-src": "^1.0.0",

test/integration/install.js

Lines changed: 98 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// in a happy-path scenario
99
'use strict';
1010

11+
var rewire = require('rewire');
1112
var utils = require('fabric-client/lib/utils.js');
1213
var logger = utils.getLogger('install');
1314

@@ -51,33 +52,33 @@ test('\n\n** Test chaincode install using chaincodePath to create chaincodePacka
5152
t.end();
5253
}
5354
},
54-
(err) => {
55-
t.fail('install reject: '+err);
56-
t.end();
57-
}).catch((err) => {
58-
t.fail('install error. ' + err.stack ? err.stack : err);
59-
t.end();
60-
}).then (() => {
61-
params.channelName = params.channelName+'0';
62-
params.testDesc = params.testDesc+'0';
63-
installChaincode(params, t)
64-
.then((info) => {
65-
if (info && info instanceof Error && info.message.includes('install.'+params.chaincodeVersion+' exists')) {
66-
t.pass('passed check for exists on install again');
67-
t.end();
68-
} else {
69-
t.fail('failed check for exists on install again');
70-
t.end();
71-
}
72-
},
73-
(err) => {
74-
t.fail('install reject: '+err);
75-
t.end();
76-
}).catch((err) => {
77-
t.fail('install error. ' + err.stack ? err.stack : err);
78-
t.end();
79-
});
80-
});
55+
(err) => {
56+
t.fail('install reject: ' + err);
57+
t.end();
58+
}).catch((err) => {
59+
t.fail('install error. ' + err.stack ? err.stack : err);
60+
t.end();
61+
}).then(() => {
62+
params.channelName = params.channelName + '0';
63+
params.testDesc = params.testDesc + '0';
64+
installChaincode(params, t)
65+
.then((info) => {
66+
if (info && info instanceof Error && info.message.includes('install.' + params.chaincodeVersion + ' exists')) {
67+
t.pass('passed check for exists on install again');
68+
t.end();
69+
} else {
70+
t.fail('failed check for exists on install again');
71+
t.end();
72+
}
73+
},
74+
(err) => {
75+
t.fail('install reject: ' + err);
76+
t.end();
77+
}).catch((err) => {
78+
t.fail('install error. ' + err.stack ? err.stack : err);
79+
t.end();
80+
});
81+
});
8182
});
8283

8384
test('\n\n** Test chaincode install using chaincodePackage[byte] **\n\n', (t) => {
@@ -86,54 +87,57 @@ test('\n\n** Test chaincode install using chaincodePackage[byte] **\n\n', (t) =>
8687
testDesc: 'using chaincodePackage',
8788
channelName: 'test-install-package',
8889
chaincodeId: 'install-package',
89-
chaincodePath: testUtil.CHAINCODE_PATH+'_pkg',//not an existing path
90+
chaincodePath: testUtil.CHAINCODE_PATH,
9091
chaincodeVersion: testUtil.getUniqueVersion()
9192
};
9293

93-
Packager.package(testUtil.CHAINCODE_PATH, null, false) //use good path here to get data
94-
.then((data) => {
95-
params.chaincodePackage = data;
94+
let _getChaincodeDeploymentSpec = rewire('fabric-client/lib/Client.js').__get__('_getChaincodeDeploymentSpec');
9695

96+
// install from source
97+
let p = _getChaincodeDeploymentSpec(params, false)
98+
.then((cdsBytes) => {
99+
params.chaincodePackage = cdsBytes;
97100
installChaincode(params, t)
98101
.then((info) => {
99102
if (info === 'success') {
100-
t.pass(params.testDesc+' - success');
103+
t.pass(params.testDesc + ' - success');
101104
return true;
102105
} else {
103-
t.fail(params.testDesc+' - '+info);
106+
t.fail(params.testDesc + ' - ' + info);
104107
t.end();
105108
}
106109
},
107-
(err) => {
108-
t.fail(params.testDesc+' - install reject: '+err);
109-
t.end();
110-
}).catch((err) => {
111-
t.fail(params.testDesc+' - install error. ' + err.stack ? err.stack : err);
112-
t.end();
113-
}).then (() => {
114-
params.channelName = params.channelName+'0';
115-
params.testDesc = params.testDesc+'0';
116-
installChaincode(params, t)
117-
.then((info) => {
118-
if (info && info instanceof Error && info.message.includes('install-package.'+params.chaincodeVersion+' exists')) {
119-
t.pass('passed check for exists same code again');
120-
t.end();
121-
} else {
122-
t.fail('failed check for exists same code again');
123-
t.end();
124-
}
125-
},
126-
(err) => {
127-
t.fail(params.testDesc+' - install same chaincode again - reject, error');
128-
logger.error(err.stack ? err.stack : err);
129-
t.end();
130-
}).catch((err) => {
131-
t.fail(params.testDesc+' - install same chaincode again - error');
132-
logger.error(err.stack ? err.stack : err);
133-
t.end();
134-
});
135-
});
110+
(err) => {
111+
t.fail(params.testDesc + ' - install reject: ' + err);
112+
t.end();
113+
}).catch((err) => {
114+
t.fail(params.testDesc + ' - install error. ' + err.stack ? err.stack : err);
115+
t.end();
116+
}).then(() => {
117+
params.channelName = params.channelName + '0';
118+
params.testDesc = params.testDesc + '0';
119+
installChaincode(params, t)
120+
.then((info) => {
121+
if (info && info instanceof Error && info.message.includes('install-package.' + params.chaincodeVersion + ' exists')) {
122+
t.pass('passed check for exists same code again');
123+
t.end();
124+
} else {
125+
t.fail('failed check for exists same code again');
126+
t.end();
127+
}
128+
},
129+
(err) => {
130+
t.fail(params.testDesc + ' - install same chaincode again - reject, error');
131+
logger.error(err.stack ? err.stack : err);
132+
t.end();
133+
}).catch((err) => {
134+
t.fail(params.testDesc + ' - install same chaincode again - error');
135+
logger.error(err.stack ? err.stack : err);
136+
t.end();
137+
});
138+
});
136139
});
140+
t.end();
137141
});
138142

139143
function installChaincode(params, t) {
@@ -153,14 +157,14 @@ function installChaincode(params, t) {
153157
t.pass('Successfully retrieved TLS certificate');
154158
tlsInfo = enrollment;
155159
client.setTlsClientCertAndKey(tlsInfo.certificate, tlsInfo.key);
156-
return Client.newDefaultKeyValueStore({path: testUtil.storePathForOrg(orgName)});
160+
return Client.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) });
157161
}).then((store) => {
158162
client.setStateStore(store);
159163

160164
// get the peer org's admin required to send install chaincode requests
161165
return testUtil.getSubmitter(client, t, true /* get peer org admin */, org);
162166
}).then(() => {
163-
t.pass(params.testDesc+' - Successfully enrolled user \'admin\'');
167+
t.pass(params.testDesc + ' - Successfully enrolled user \'admin\'');
164168

165169
channel.addOrderer(
166170
client.newOrderer(
@@ -204,38 +208,38 @@ function installChaincode(params, t) {
204208

205209
return client.installChaincode(request);
206210
},
207-
(err) => {
208-
t.fail(params.testDesc+' - Failed to enroll user \'admin\'. ' + err);
209-
throw new Error(params.testDesc+' - Failed to enroll user \'admin\'. ' + err);
210-
}).then((results) => {
211-
var proposalResponses = results[0];
212-
213-
//var proposal = results[1];
214-
var all_good = true;
215-
var error = null;
216-
for(var i in proposalResponses) {
217-
let one_good = false;
218-
if (proposalResponses && proposalResponses[i].response && proposalResponses[i].response.status === 200) {
219-
one_good = true;
220-
logger.info(params.testDesc+' - install proposal was good');
221-
} else {
222-
logger.error(params.testDesc+' - install proposal was bad');
223-
error = proposalResponses[i];
211+
(err) => {
212+
t.fail(params.testDesc + ' - Failed to enroll user \'admin\'. ' + err);
213+
throw new Error(params.testDesc + ' - Failed to enroll user \'admin\'. ' + err);
214+
}).then((results) => {
215+
var proposalResponses = results[0];
216+
217+
//var proposal = results[1];
218+
var all_good = true;
219+
var error = null;
220+
for (var i in proposalResponses) {
221+
let one_good = false;
222+
if (proposalResponses && proposalResponses[i].response && proposalResponses[i].response.status === 200) {
223+
one_good = true;
224+
logger.info(params.testDesc + ' - install proposal was good');
225+
} else {
226+
logger.error(params.testDesc + ' - install proposal was bad');
227+
error = proposalResponses[i];
228+
}
229+
all_good = all_good & one_good;
224230
}
225-
all_good = all_good & one_good;
226-
}
227-
if (all_good) {
228-
return 'success';
229-
} else {
230-
if (error) {
231-
return error;
231+
if (all_good) {
232+
return 'success';
233+
} else {
234+
if (error) {
235+
return error;
236+
}
237+
else return 'fail';
232238
}
233-
else return 'fail';
234-
}
235-
},
236-
(err) => {
237-
return new Error(err.stack ? err.stack : err);
238-
});
239+
},
240+
(err) => {
241+
return new Error(err.stack ? err.stack : err);
242+
});
239243
} catch (err) {
240244
return Promise.reject(new Error(err.stack ? err.stack : err));
241245
}

test/unit/client.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ test('\n\n ** Test per-call timeout support [client] **\n', (t) => {
844844
sandbox.stub(clientUtils, 'buildProposal').returns(Buffer.from('dummyProposal'));
845845
sandbox.stub(clientUtils, 'signProposal').returns(Buffer.from('dummyProposal'));
846846
ClientRewired.__set__(
847-
'_getChaincodePackageData',
847+
'_getChaincodeDeploymentSpec',
848848
() => {
849849
return Promise.resolve(Buffer.from('dummyChaincodePackage'));
850850
});
@@ -1120,3 +1120,43 @@ test('\n\n*** Test Client.getPeersForOrgOnChannel ***\n', (t) => {
11201120

11211121
t.end();
11221122
});
1123+
1124+
1125+
test('\n\n Test _getChaincodeDeploymentSpec ***\n', function (t) {
1126+
let ccPath = testutil.NODE_CHAINCODE_PATH;
1127+
let ccInstallRequest = {
1128+
chaincodeType: 'node',
1129+
chaincodePath: ccPath,
1130+
chaincodeId: 'example_cc',
1131+
chaincodeVersion: '1.0.0'
1132+
};
1133+
let _getChaincodeDeploymentSpec = rewire('fabric-client/lib/Client.js').__get__('_getChaincodeDeploymentSpec');
1134+
1135+
// install from source
1136+
_getChaincodeDeploymentSpec(ccInstallRequest, false)
1137+
.then((cdsBytes) => {
1138+
t.pass('Successfully got chaincode deployment spec from source');
1139+
// capture the cdsBytes for next test
1140+
return Buffer.from(cdsBytes);
1141+
})
1142+
.then((packageBytes) => {
1143+
// install using existing package
1144+
ccInstallRequest.chaincodePackage = packageBytes;
1145+
_getChaincodeDeploymentSpec(ccInstallRequest, false)
1146+
.then((cdsBytes) => {
1147+
// should get back what was passed in
1148+
if (packageBytes.equals(cdsBytes)) {
1149+
t.pass('Successfully got chaincode deployment spec from existing package');
1150+
} else {
1151+
t.fail('Failed to get correct deployment spec from existing package ' + cdsBytes.length + ' | ' + packageBytes.length);
1152+
}
1153+
})
1154+
.catch((err) => {
1155+
t.fail('Failed to get deployment spec from existing package. Error: ' + err.stack ? err.stack : err);
1156+
});
1157+
})
1158+
.catch((err) => {
1159+
t.fail('Failed to get deployment spec. Error: ' + err.stack ? err.stack : err);
1160+
});
1161+
t.end();
1162+
});

0 commit comments

Comments
 (0)