UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

240 lines (238 loc) 9.49 kB
import { map } from 'rxjs/operators'; import { NodeCimOutput } from './node-connection'; import { PowerShell } from './powershell'; import { PowerShellBatch } from './powershell-batch'; /** * The PowerShell Alternate processing class. */ export class PowerShellAlternate { /** * The key of powershell session. */ static cimAlternateKey = 'cimAlt'; /** * Create alternate PowerShell query for CIM query. * * @param nodeConnection The node connection object. * @param nodeName The node name. * @param options The node request options. * @return Observable<T> if there is no alternate available, return null. */ static create(nodeConnection, nodeName, options) { if (options == null || options.powerShell == null || options.powerShellContext == null) { return null; } const endpoint = nodeConnection.getJeaEndpoint(nodeName); if (endpoint == null && options.powerShellEndpoint == null && !MsftSme.self().Init.powerShellEndpoint) { return null; } const powerShell = PowerShellAlternate.findOrCreateNullPowerShell(nodeName, nodeConnection, options); const command = PowerShell.createCommand(options.powerShell, options.powerShellContext.parameters); return powerShell.run(command) .pipe(map(results => PowerShellAlternate.mapPowerShellToCim(options.powerShellContext.cimOutput, results))); } /** * Create alternate PowerShell Stream query for CIM query. * * @param nodeConnection The node connection object. * @param nodeName The node name. * @param options The node request options. * @return Observable<T> if there is no alternate available, return null. */ static createStream(powerShellStream, nodeName, options) { if (options == null || options.powerShell == null || options.powerShellContext == null) { return null; } const endpoint = powerShellStream.getJeaEndpoint(nodeName); if (endpoint == null && options.powerShellEndpoint == null && !MsftSme.self().Init.powerShellEndpoint) { return null; } if (!options.powerShellEndpoint) { options.powerShellEndpoint = endpoint; } const command = PowerShell.createCommand(options.powerShell, options.powerShellContext.parameters); return powerShellStream.run(nodeName, command, options) .pipe(map(results => PowerShellAlternate.mapPowerShellToCim(options.powerShellContext.cimOutput, results))); } /** * @deprecated * (not supported) * Create alternate PowerShell Batch query for CIM batch query. * * @param nodeConnection the node connection object * @param batchConnection The batch connection object. * @param nodeNames The list of node names. * @param options The node request options. * @return Observable<BatchResponseItem[]> if there is no alternate available, return null. */ static createBatch(nodeConnection, batchConnection, nodeNames, options) { if (options == null || options.powerShell == null || options.powerShellContext == null) { return null; } // TODO: for now we assume all endpoints match. Need to work on a more general solution. const node = nodeNames && nodeNames.length > 0 && nodeNames[0]; const endpoint = nodeConnection.getJeaEndpoint(node); if (endpoint == null && options.powerShellEndpoint == null && !MsftSme.self().Init.powerShellEndpoint) { return null; } if (!options.powerShellEndpoint) { options.powerShellEndpoint = endpoint; } const batchSession = new PowerShellBatch(nodeNames, batchConnection, null, null, options); const command = PowerShell.createCommand(options.powerShell, options.powerShellContext.parameters); return batchSession.runSingleCommand(command, options) .pipe(map(items => items.map(item => ({ sequenceNumber: item.sequenceNumber, nodeName: item.nodeName, response: { response: PowerShellAlternate.mapPowerShellToCim(options.powerShellContext.cimOutput, item.properties), status: item.status } })))); } /** * Reserve a session for all alternate CIM non-batch query. * * @param nodeName the node name. * @param nodeConnection the node connection object. * @param options the node request options. */ static reserveSession(appContext, nodeName, options) { return appContext.powerShell.createSession(nodeName, PowerShellAlternate.cimAlternateKey, options); } /** * Dispose the session for alternate CIM non-batch query. * * @param session the session object. */ static disposeSession(session) { session.dispose(); } /** * Find existing powershell session with the fixed key or create null session. * * @param nodeName the node name. * @param nodeConnection the node connection object. * @param options the node request options. */ static findOrCreateNullPowerShell(nodeName, nodeConnection, options) { let powerShell = PowerShell.find(nodeName, PowerShellAlternate.cimAlternateKey); if (powerShell == null) { powerShell = PowerShell.create(nodeName, nodeConnection, null, null, options); } return powerShell; } /** * Convert the PowerShell results to Cim expected format. * * @param outputType The output data type. * @param data The input data. */ static mapPowerShellToCim(outputType, data) { switch (outputType) { case NodeCimOutput.Single: // single instance result. return { properties: data.results && data.results[0] && PowerShellAlternate.cleanCimInstance(data.results[0]) }; case NodeCimOutput.Multiple: // multiple instances result. return { value: data.results.map(instance => { return { properties: PowerShellAlternate.cleanCimInstance(instance) }; }) }; case NodeCimOutput.Result: return PowerShellAlternate.adjustCimResults(data); case NodeCimOutput.Query: // query results without properties. return { value: data.results.map(instance => { return PowerShellAlternate.cleanCimInstance(instance); }) }; } } /** * Adjust PowerShell CIM results data. * * @param data The result data. */ static adjustCimResults(data) { let response = {}; // invoke method results with free structured but index 0. if (!data.results) { return response; } if (data.results.length === 0) { return response; } // // Packed the same parameterName object into single array. // // parameterName // itemType: 16: Instance // itemValue: Instance Data // psComputerName // const results = []; for (const item of data.results) { if (item['psComputerName'] !== undefined) { delete item['psComputerName']; } if (item.hasOwnProperty('returnValue')) { response = { ...response, ...item }; } if (item.hasOwnProperty('outParameters')) { for (const parameter of item.outParameters) { response[parameter.name] = parameter.value; } } // aggregate the same parameter name object into single array. if (item.hasOwnProperty('itemValue')) { if (item.itemValue.length > 0) { const array = item.itemValue; array.forEach(value => results.push(PowerShellAlternate.cleanCimInstance(value))); } else { results.push(PowerShellAlternate.cleanCimInstance(item.itemValue)); } } } if (results.length > 0) { response.results = results; } return response; } /** * Clean the cim instance object to remove schema/qualifier data. * * @param data The instance object from PowerShell. */ static cleanCimInstance(data) { if (!data) { return data; } if (data['psComputerName'] !== undefined) { delete data['psComputerName']; } if (data['cimClass']) { delete data['cimClass']; } if (data['cimInstanceProperties']) { delete data['cimInstanceProperties']; } if (data['cimSystemProperties']) { const props = data['cimSystemProperties']; data['_Namespace'] = props['namespace']; data['_ServerName'] = props['serverName']; data['_ClassName'] = props['className']; data['_Path'] = props['path']; delete data['cimSystemProperties']; } return data; } } //# sourceMappingURL=powershell-alternate.js.map