integ/components/deadline/common/functions/awaitSsmCommand.ts (51 lines of code) (raw):
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
import {SSM, SendCommandRequest } from '@aws-sdk/client-ssm';
// Workaround for AWS SDK v3 bug: https://github.com/aws/aws-sdk-js-v3/issues/3807
declare global {
interface ReadableStream {}
}
const ssm = new SSM({});
interface CommandResponse {
output: string;
responseCode: number;
}
// Custom function to send SSM command to run a particular script on the bastion instance,
// wait for it to finish executing, then return the response.
export async function ssmCommand(bastionId: string, params: SendCommandRequest): Promise<CommandResponse> {
try {
const command = await ssm.sendCommand(params);
const commandId = command.Command!.CommandId;
var listParams = {
CommandId: commandId,
InstanceId: bastionId,
Details: true,
};
while (true) {
// Sleep for 1,000ms = 1s
await new Promise(resolve => setTimeout(resolve, 1000));
const invocations = await ssm.listCommandInvocations(listParams);
if (invocations.CommandInvocations![0]) {
const invocation = invocations.CommandInvocations![0];
switch (invocation.Status) {
case 'Success':
// Workaround: if the output of the script execution is very long, it is truncated by `listCommandInvocations`
// If the truncation string is present, this will get the full output from `getCommandInvocation`
if( /---Output truncated---/.test(invocation.CommandPlugins![0].Output!) ) {
var getParams = {
CommandId: commandId,
InstanceId: bastionId,
};
const getResult = await ssm.getCommandInvocation(getParams);
return {
output: getResult.StandardOutputContent!,
responseCode: getResult.ResponseCode!,
};
}
return {
output: invocation.CommandPlugins![0].Output!,
responseCode: invocation.CommandPlugins![0].ResponseCode!,
};
case 'Failed':
throw invocation.CommandPlugins![0];
default:
break;
}
}
}
} catch (err) {
throw err;
}
}