UNPKG

@applitools/execution-grid-tunnel

Version:

Allows user to run tests with exection-grid and navigate to private hosts and ips

160 lines (130 loc) 4.34 kB
const path = require('path') const {createFrpcTunnelController, createTcpTunnelController} = require('./tunnel-controller.js') const TUNNEL_STATUS = require('./tunnel-status') class TunnelProcessManager { constructor({ logFileDirectory, tunnelConfigFileDirectory, runTunnelBinPath, socks5Proxies, portRange, tcpTunnelOptions }) { this._tunnelsMap = new Map() this._logFileDirectory = logFileDirectory this._tunnelConfigFileDirectory = tunnelConfigFileDirectory this._runTunnelBinPath = runTunnelBinPath this._portRange = portRange this._socks5Proxies = socks5Proxies this._tcpTunnelOptions = tcpTunnelOptions // Define proposal-class-properties (because eslint throw error) this._shouldRunTunnel = async (tunnelId) => { const {isStopTunnelCalled} = this._tunnelsMap.get(tunnelId) || {} return !!isStopTunnelCalled } this._updateTunnelMap = (tunnelId, fields) => { const tunnel = this._tunnelsMap.get(tunnelId) || {} this._tunnelsMap.set(tunnelId, {...tunnel, ...fields}) } this._getTunnelByStatus = (states) => Array.from(this._tunnelsMap.keys()).filter((id) => { const {processController} = this._tunnelsMap.get(id) return processController && states.includes(processController.status) }) this.getActiveTunnels = () => this._getTunnelByStatus([TUNNEL_STATUS.RUNNING, TUNNEL_STATUS.RECONNECT]) this.getRunningTunnels = () => this._getTunnelByStatus([TUNNEL_STATUS.RUNNING]) } async start({ tunnelId, type, config }) { try { const logFilePath = path.resolve(this._logFileDirectory, `${tunnelId}.log`) if (!this._shouldRunTunnel(tunnelId)) { return null } this._updateTunnelMap(tunnelId, {type ,config}) let tunnelController if (type === 'tcp'){ const localProxyOptions = { host: '127.0.0.1', port: this._socks5Proxies[0].address().port } tunnelController = createTcpTunnelController({ tunnelId, tunnelConfig: {...config, ...this._tcpTunnelOptions, localProxyOptions}, loggerOptions: this._tcpTunnelOptions.loggerOptions, }) }else{ tunnelController = createFrpcTunnelController({ tunnelId, tunnelConfig: config, configFileRootPath: this._tunnelConfigFileDirectory, logFilePath, binPath: this._runTunnelBinPath, socks5Proxy: this._socks5Proxies[0], portRange: this._portRange, }) } await tunnelController.start() this._updateTunnelMap(tunnelId, {processController: tunnelController}) if (!this._shouldRunTunnel(tunnelId)) { await this.stop(tunnelId) return null } return tunnelId } catch (error) { this._updateTunnelMap(tunnelId, {error}) throw error } } async stop(tunnelId) { if (!this._tunnelsMap.has(tunnelId)) { return } // Update that user want to stop the tunnel this._updateTunnelMap(tunnelId, {isStopTunnelCalled: true}) const {processController} = this._tunnelsMap.get(tunnelId) if (!processController) { return } await processController.stop() this._tunnelsMap.delete(tunnelId) } async stopAll() { const promises = Object.entries(this.getTunnels()) .filter(([_tunnelId, {isStopTunnelCalled}]) => !isStopTunnelCalled) .map(([tunnelId]) => this.stop(tunnelId)) const _result = await Promise.allSettled(promises) //TODO: add log if there is an error return } getTunnels() { return Array.from(this._tunnelsMap.entries()).reduce( (pv, [key, value]) => ({...pv, [key]: value}), {}, ) } getStatus(tunnelId) { const process = this._tunnelsMap.get(tunnelId) if (!process || !process.processController) { return null } return process.processController.status } } module.exports = function createTunnelProcessManager({ logFileDirectory, tunnelConfigFileDirectory, runTunnelBinPath, egTunnelManager, socks5Proxies, portRange, tcpTunnelOptions }) { return new TunnelProcessManager({ logFileDirectory, tunnelConfigFileDirectory, runTunnelBinPath, egTunnelManager, socks5Proxies, portRange, tcpTunnelOptions }) }