@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
240 lines (238 loc) • 9.49 kB
JavaScript
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