Skip to content

Commit

Permalink
FABN-1098 NodeSDK allow multiple targets
Browse files Browse the repository at this point in the history
Allow mulitple targets on the channel initialize()

Change-Id: Ifb06d301c9ff516758df309613c09e5c654eff80
Signed-off-by: Bret Harrison <[email protected]>
  • Loading branch information
harrisob committed Jan 15, 2019
1 parent 0fd719d commit 2a93c9b
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 72 deletions.
162 changes: 93 additions & 69 deletions fabric-client/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ const Channel = class {
this._discovery_interests = new Map();
this._discovery_results = null;
this._last_discover_timestamp = null;
this._discovery_peer = null;
this._use_discovery = sdk_utils.getConfigSetting('initialize-with-discovery', false);
this._as_localhost = sdk_utils.getConfigSetting('discovery-as-localhost', true);
this._endorsement_handler = null; // will be setup during initialization
Expand All @@ -153,6 +152,13 @@ const Channel = class {
* @typedef {Object} InitializeRequest
* @property {string | Peer | ChannelPeer} target - Optional. The target peer to be used
* to make the initialization requests for configuration information.
* When used with `targets` parameter, the peer referenced here will be
* added to the `targets` array.
* Default is to use the first ChannelPeer assigned to this channel.
* @property {Array[Peer | ChannelPeer]} targets - Optional. The target peers to be used
* to make the initialization requests for configuration information.
* When used with `target` parameter, the peer referenced there will be
* added to the `targets` array.
* Default is to use the first ChannelPeer assigned to this channel.
* @property {boolean} discover - Optional. Use the discovery service on the
* the target peer to load the configuration and network information.
Expand Down Expand Up @@ -263,95 +269,113 @@ const Channel = class {
this._discovery_results = null;
this._last_discover_timestamp = null;
this._last_refresh_request = Object.assign({}, request);
let target_peer = this._discovery_peer;
let target_peers = [];

if (request && request.target) {
target_peer = request.target;
target_peers.push(request.target);
}
if (request && Array.isArray(request.targets)) {
target_peers = target_peers.concat(request.targets);
}

if (this._use_discovery) {
logger.debug('%s - starting discovery', method);
try {
target_peer = this._getTargetForDiscovery(target_peer);
} catch (error) {
logger.debug('Problem getting a target peer for discovery service :: %s', error);
}
if (!target_peer) {
throw new Error('No target provided for discovery services');
if (target_peers.length === 0) {
if (this._use_discovery) {
target_peers = this._getTargets(null, Constants.NetworkConfig.DISCOVERY_ROLE, true);
} else {
target_peers = this._getTargets(null, Constants.NetworkConfig.ALL_ROLES, true);
}
}

let final_error = null;
for (let target_peer of target_peers) {
try {
let discover_request = {
target: target_peer,
config: true
};

const discovery_results = await this._discover(discover_request);
if (discovery_results.msps) {
this._buildDiscoveryMSPs(discovery_results);
} else {
throw Error('No MSP information found');
}
if (discovery_results.orderers) {
this._buildDiscoveryOrderers(discovery_results, discovery_results.msps, request);
}
if (discovery_results.peers_by_org) {
this._buildDiscoveryPeers(discovery_results, discovery_results.msps, request);
}

discovery_results.endorsement_plans = [];
logger.debug('%s - target peer %s starting', method, target_peer);

const interests = [];
const plan_ids = [];
this._discovery_interests.forEach((interest, plan_id) => {
logger.debug('%s - have interest of:%s', method, plan_id);
plan_ids.push(plan_id);
interests.push(interest);
});
if (this._use_discovery) {
logger.debug('%s - starting discovery', method);
target_peer = this._getTargetForDiscovery(target_peer);

for (const i in plan_ids) {
const plan_id = plan_ids[i];
const interest = interests[i];

discover_request = {
if (!target_peer) {
throw new Error('No target provided for discovery services');
}
let discover_request = {
target: target_peer,
interests: [interest]
config: true
};

let discover_interest_results = null;
try {
discover_interest_results = await this._discover(discover_request);
} catch (error) {
logger.error('Not able to get an endorsement plan for %s', plan_id);
const discovery_results = await this._discover(discover_request);
if (discovery_results.msps) {
this._buildDiscoveryMSPs(discovery_results);
} else {
throw Error('No MSP information found');
}
if (discovery_results.orderers) {
this._buildDiscoveryOrderers(discovery_results, discovery_results.msps, request);
}
if (discovery_results.peers_by_org) {
this._buildDiscoveryPeers(discovery_results, discovery_results.msps, request);
}

if (discover_interest_results && discover_interest_results.endorsement_plans && discover_interest_results.endorsement_plans[0]) {
const plan = this._buildDiscoveryEndorsementPlan(discover_interest_results, plan_id, discovery_results.msps, request);
discovery_results.endorsement_plans.push(plan);
logger.debug('Added an endorsement plan for %s', plan_id);
} else {
logger.debug('Not adding an endorsement plan for %s', plan_id);
discovery_results.endorsement_plans = [];

const interests = [];
const plan_ids = [];
this._discovery_interests.forEach((interest, plan_id) => {
logger.debug('%s - have interest of:%s', method, plan_id);
plan_ids.push(plan_id);
interests.push(interest);
});

for (const i in plan_ids) {
const plan_id = plan_ids[i];
const interest = interests[i];

discover_request = {
target: target_peer,
interests: [interest]
};

try {
const discover_interest_results = await this._discover(discover_request);
if (discover_interest_results &&
discover_interest_results.endorsement_plans &&
discover_interest_results.endorsement_plans[0]) {
const plan = this._buildDiscoveryEndorsementPlan(discover_interest_results, plan_id, discovery_results.msps, request);
discovery_results.endorsement_plans.push(plan);
logger.debug('%s - Added an endorsement plan for %s', method, plan_id);
} else {
logger.debug('%s - Not adding an endorsement plan for %s', method, plan_id);
}
} catch (error) {
logger.debug('%s - trying to get a plan for plan %s :: interest:%s error:%s', method, plan_id, interest, error);
}

}
}
discovery_results.timestamp = Date.now();
this._discovery_results = discovery_results;
this._last_discover_timestamp = discovery_results.timestamp;

discovery_results.timestamp = Date.now();
this._discovery_results = discovery_results;
this._discovery_peer = target_peer;
this._last_discover_timestamp = discovery_results.timestamp;
return discovery_results;
} else {
target_peer = this._getFirstAvailableTarget(target_peer);
const config_envelope = await this.getChannelConfig(target_peer);
logger.debug('%s - got config envelope from getChannelConfig :: %j', method, config_envelope);
const config_items = this.loadConfigEnvelope(config_envelope);

return discovery_results;
return config_items;
}
} catch (error) {
logger.error(error);
throw Error('Failed to discover ::' + error.toString());
logger.error(error.toString());
final_error = error;
}
} else {
target_peer = this._getFirstAvailableTarget(target_peer);
const config_envelope = await this.getChannelConfig(target_peer);
logger.debug('initialize - got config envelope from getChannelConfig :: %j', config_envelope);
const config_items = this.loadConfigEnvelope(config_envelope);

return config_items;
logger.debug('%s - target peer %s failed %s:', method, target_peer, final_error);
}

if (final_error) {
throw final_error;
} else {
throw new Error('Initialization failed to complete');
}
}

Expand Down
11 changes: 11 additions & 0 deletions test/integration/discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ test('\n\n***** D I S C O V E R Y *****\n\n', async (t) => {
let data = fs.readFileSync(path.join(__dirname, 'e2e', '../../fixtures/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlscacerts/org1.example.com-cert.pem'));
let pem = Buffer.from(data).toString();
const peer_org1 = client_org1.newPeer('grpcs://localhost:7051', {pem: pem, 'ssl-target-name-override': 'peer0.org1.example.com', name: 'peer0.org1.example.com'});
const peer_bad = client_org1.newPeer('grpcs://localhost:9999', {pem: pem, 'ssl-target-name-override': 'peer9.org1.example.com', name: 'peer9.org1.example.com'});

data = fs.readFileSync(path.join(__dirname, 'e2e', '../../fixtures/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlscacerts/org2.example.com-cert.pem'));
pem = Buffer.from(data).toString();
Expand Down Expand Up @@ -211,6 +212,16 @@ test('\n\n***** D I S C O V E R Y *****\n\n', async (t) => {

// This will call the discovery under the covers and load the channel with msps, orderers, and peers
results = await channel_org1.initialize({asLocalhost: true, discover: true, target: peer_org1});
t.equal(channel_org1.getOrderers().length, 2, 'Checking that there are two orderers assigned to the channel');

// This will call the discovery under the covers and load the channel with msps, orderers, and peers
// after if fails with the bad peer
results = await channel_org1.initialize({asLocalhost: true, discover: true, target: peer_bad, targets: [peer_org1]});
t.equal(channel_org1.getOrderers().length, 2, 'Checking that there are two orderers assigned to the channel');

// This will call the discovery under the covers and load the channel with msps, orderers, and peers
// after it fails with the bad peer
results = await channel_org1.initialize({asLocalhost: true, discover: true, targets: [peer_bad, peer_org1]});

t.equal(channel_org1.getOrderers().length, 2, 'Checking that there are two orderers assigned to the channel');
const msps = channel_org1.getMSPManager().getMSPs();
Expand Down
6 changes: 3 additions & 3 deletions test/unit/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1071,8 +1071,8 @@ test('\n\n ** Channel Discovery tests **\n\n', async (t) => {
async () => {
await channel.initialize();
},
/No target provided for discovery services/,
'Channel tests, sendTransactionProposal(): "target" parameter not specified and no peers are set on this Channel'
/"target" parameter not specified and no peers are set on this Channel/,
'Channel tests, initialize(): "target" parameter not specified and no peers are set on this Channel'
);


Expand All @@ -1087,7 +1087,7 @@ test('\n\n ** Channel Discovery tests **\n\n', async (t) => {
});
},
/No identity has been assigned to this client/,
'Channel tests, sendTransactionProposal(): No identity has been assigned to this client'
'Channel tests, initialize(): No identity has been assigned to this client'
);

await testutil.tapeAsyncThrow(t,
Expand Down

0 comments on commit 2a93c9b

Please sign in to comment.