import * as vscode from 'vscode' ; import { FabricEnvironmentRegistryEntry , FabricEnvironmentRegistry } from 'ibm-blockchain-platform-common' ; import { SettingConfigurations } from '../../configurations' ; import { LocalMicroEnvironment } from './LocalMicroEnvironment' ; import { UserInputUtil } from '../../commands/UserInputUtil' ; export class LocalMicroEnvironmentManager { public static findFreePort : any = require ( 'find-free-port' ) ; public static instance ( ) { return this . _instance ; } private static _instance : LocalMicroEnvironmentManager = new LocalMicroEnvironmentManager ( ) ; public runtimes : Map < string , LocalMicroEnvironment > = new Map ( ) ; private constructor ( ) { } public updateRuntime ( name , runtime ) { this . runtimes . set ( name , runtime ) ; } public removeRuntime ( name ) { this . runtimes . delete ( name ) ; } public getRuntime ( name ) { return this . runtimes . get ( name ) ; } public async ensureRuntime ( name , port ? , numberOfOrgs ? , fabricCapabilities ? ) { let runtime = this . getRuntime ( name ) ; if ( ! runtime ) { runtime = await this . addRuntime ( name , port , numberOfOrgs , fabricCapabilities ) ; } return runtime ; } public async addRuntime ( name , port ? , numberOfOrgs ? , fabricCapabilities ? ) { let portToUse ; if ( ! port ) { const settingPorts = vscode . workspace . getConfiguration ( ) . get ( SettingConfigurations . FABRIC_RUNTIME , vscode . ConfigurationTarget . Global ) ; if ( settingPorts [ name ] ) { portToUse = settingPorts [ name ] ; } else { settingPorts [ name ] = await this . generatePortConfiguration ( ) ; portToUse = settingPorts [ name ] ; await vscode . workspace . getConfiguration ( ) . update ( SettingConfigurations . FABRIC_RUNTIME , settingPorts , vscode . ConfigurationTarget . Global ) ; } } else { portToUse = port ; } let orgsToUse ; if ( ! numberOfOrgs ) { let entry ; try { entry = await FabricEnvironmentRegistry . instance ( ) . get ( name ) ; } catch ( error ) { throw new Error ( `Unable to add runtime as environment '${ name }' does not exist.` ) ; } if ( entry . numberOfOrgs ) { orgsToUse = entry . numberOfOrgs ; } else { throw new Error ( `Unable to add runtime as environment '${ name }' does not have 'numberOfOrgs' property.` ) ; } } else { orgsToUse = numberOfOrgs ; } const runtime = new LocalMicroEnvironment ( name , portToUse , orgsToUse , fabricCapabilities ) ; this . runtimes . set ( name , runtime ) ; return runtime ; } public async initialize ( name , numberOfOrgs , fabricCapabilities = UserInputUtil . V2_0 ) { let port = this . getPort ( name ) ; let runtime ; if ( port ) { runtime = await this . addRuntime ( name , port , numberOfOrgs , fabricCapabilities ) ; } else { port = await this . generatePortConfiguration ( ) ; runtime = await this . addRuntime ( name , port , numberOfOrgs , fabricCapabilities ) ; await runtime . updateUserSettings ( name ) ; } const created = await runtime . isCreated ( ) ; if ( ! created ) { await runtime . create ( ) ; } else { const entry = await FabricEnvironmentRegistry . instance ( ) . get ( name ) ; if ( ! entry . url . includes ( `${ port }` ) ) { await runtime . teardown ( ) ; } } } private getPort ( name ) { const runtimeSettings = vscode . workspace . getConfiguration ( ) . get ( SettingConfigurations . FABRIC_RUNTIME ) ; if ( name && runtimeSettings [ name ] ) { return runtimeSettings [ name ] ; } else { return ; } } private async generatePortConfiguration ( ) { let port ; const settings = vscode . workspace . getConfiguration ( ) . get ( SettingConfigurations . FABRIC_RUNTIME ) ; let startPort ; if ( Object . keys ( settings ) . length !== 0 ) { const ports = Object . values ( settings ) ; const largestPort = Math . max ( ... ports ) ; startPort = largestPort + 1 ; } else { startPort = 8080 ; } const freePorts = await LocalMicroEnvironmentManager . findFreePort ( startPort , null , null , 20 ) ; port = freePorts [ 0 ] ; return port ; } }