import * as path from 'path' ; import * as fs from 'fs-extra' ; import { EventEmitter } from 'events' ; import { FabricNode , FabricNodeType } from '../fabricModel/FabricNode' ; export class FabricEnvironment extends EventEmitter { protected name : string ; protected path : string ; constructor ( name , environmentPath ) { super ( ) ; this . path = environmentPath ; this . name = name ; } public getName ( ) { return this . name ; } public getPath ( ) { return this . path ; } public async getAllOrganizationNames ( showOrderer = true ) { const mspIDs = new Set < string > ( ) ; let nodes = await this . getNodes ( ) ; if ( ! showOrderer ) { nodes = nodes . filter ( ( node ) => { return node . type === FabricNodeType . PEER ; } ) ; } for ( const node of nodes ) { if ( node . msp_id ) { mspIDs . add ( node . msp_id ) ; } } return Array . from ( mspIDs ) . sort ( ) ; } public async getNodes ( withoutIdentities = false , showAll = false ) { const rootNodesPath = path . resolve ( this . path , 'nodes' ) ; const nodes = await this . loadNodes ( rootNodesPath ) ; const nodesToUse = showAll ? nodes : nodes . filter ( ( _node ) => { return _node . hidden === undefined || _node . hidden === false ; } ) ; if ( withoutIdentities ) { return nodesToUse . filter ( ( node ) => ( ! node . wallet || ! node . identity ) ) ; } else { return nodesToUse ; } } public async updateNode ( node , isOpsTools = false ) { const nodesPath = path . resolve ( this . path , 'nodes' ) ; const nodesToUpdate = [ ] ; const allNodes = await this . getNodes ( false , true ) ; if ( isOpsTools ) { const allUrls = allNodes . map ( ( _node ) => _node . api_url ) ; const index = allUrls . indexOf ( node . api_url ) ; if ( index > - 1 ) { if ( allNodes [ index ] . wallet !== undefined ) { node . wallet = allNodes [ index ] . wallet ; } if ( allNodes [ index ] . identity !== undefined ) { node . identity = allNodes [ index ] . identity ; } if ( allNodes [ index ] . name !== undefined && node . name !== allNodes [ index ] . name ) { const newNodePath = path . resolve ( nodesPath , `${ node . name }.json` ) ; const oldNodePath = path . resolve ( nodesPath , `${ allNodes [ index ] . name }.json` ) ; await fs . move ( oldNodePath , newNodePath ) ; } } } if ( node . type === FabricNodeType . ORDERER ) { const ordererNodes = allNodes . filter ( ( _node ) => { return _node . type === FabricNodeType . ORDERER && _node . cluster_name && _node . cluster_name === node . cluster_name && _node . name !== node . name ; } ) . map ( ( _node ) => { _node . wallet = node . wallet ; _node . identity = node . identity ; _node . hidden = node . hidden ; return _node ; } ) ; nodesToUpdate . push ( ... ordererNodes ) ; } nodesToUpdate . push ( node ) ; for ( const _node of nodesToUpdate ) { const _nodePath = path . resolve ( nodesPath , `${ _node . name }.json` ) ; await fs . writeJson ( _nodePath , _node ) ; } } public async deleteNode ( node ) { const nodesPath = path . resolve ( this . path , 'nodes' ) ; const nodePath = path . join ( nodesPath , `${ node . name }.json` ) ; await fs . remove ( nodePath ) ; } public async requireSetup ( ) { const filteredNodes = await this . getNodes ( true ) ; return filteredNodes . length > 0 ; } private async loadNodes ( nodesPath ) { const nodesExist = await fs . pathExists ( nodesPath ) ; if ( ! nodesExist ) { return [ ] ; } let nodePaths = await fs . readdir ( nodesPath ) ; nodePaths . sort ( ) ; nodePaths = nodePaths . filter ( ( nodePath ) => ! nodePath . startsWith ( '.' ) ) . map ( ( nodePath ) => path . resolve ( nodesPath , nodePath ) ) ; const nodes = [ ] ; for ( const nodePath of nodePaths ) { const stats = await fs . lstat ( nodePath ) ; if ( stats . isDirectory ( ) ) { const subNodes = await this . loadNodes ( nodePath ) ; nodes . push ( ... subNodes ) ; } else if ( stats . isFile ( ) && nodePath . endsWith ( '.json' ) ) { const node = await fs . readJson ( nodePath ) ; nodes . push ( node ) ; } } return nodes ; } }