概要
LambdaからSSMのRunCommandを実行する処理の作成方法について記述します。言語はJavaScript
でSDKのv3(バージョン3)で書いてあります。
v3では、サービスのインスタンスを作成して、非同期でsend
メソッドを呼び出すというのが全サービス共通の書き方になります。send
メソッドはPromise型を返します。何のアクションを行うかはsend
メソッドの引数の型によって判断されます。
公式ドキュメント
サンプルプログラム
処理の流れ
SSMClient生成 → SendCommandCommand生成 → send実行 → ListCommandsCommand生成 → send実行 (RunCommandが終了するまで繰り返し) → send実行 → send実行 → ...
注意点としては、RunCommandを実行した後その処理がサーバーで正常終了したのか異常終了したのかすぐにわからない点です。RunCommandのsend
メソッドの実行直後のthen
ではステータス1はPending
やIn Progress
になることが多いと思います。その為、RunCommand実行後その実行したコマンドのrunCommandIdを退避し、ステータスがSuccessかそれ以外になるまで繰り返し実行結果を取得する処理2を入れています。
'use strict';
const { SSMClient, SendCommandCommand } = require('@aws-sdk/client-ssm');
const startSsmRunCommandHandler = async (event) => {
// SSMインスタンスを生成
const client = new SSMClient({ region: process.env.AWS_REGION });
// RunCommandのコマンドインスタンスを生成
const commandRunCommand = new SendCommandCommand({
DocumentName: 'AWS-RunShellScript',
InstanceIds: ['i-01234567'],
Parameters: {
commands: ["touch test"],
workingDirectory: ['/root']
},
});
// 実行したRunCommandのIDを格納するための変数
let runCommandId;
// RunCommandを実行
await client
.send(commandRunCommand)
.then((data) => {
console.info(`SSM RunCommand Success: ${data}`);
// RunCommandのIDを取得します。
runCommandId = data.Command.CommandId;
})
.catch((error) => {
console.error(`SSM RunCommand Failed: ${error.message}`);
throw error;
});
// 実行したRunCommandのリスト取得のコマンドインスタンを生成
const commandList = new ListCommandsCommand({
CommandId: runCommandId
});
// ListCommandを実行する関数
const runCommandStatusGetFunction = async () => {
await client
.send(commandList)
.then((data) => {
console.info(`RunCommand List: ${JSON.stringify(data)}`);
const cmd = data.Commands[0];
const status = cmd.Status;
switch (status) {
case 'Pending':
case 'InProgress':
case 'Delayed':
// Pending, InProgress, Delayedの場合はエラーをスローして再実行する。
throw new Error('ListCommand Re-run.');
case 'Success':
console.info(`SSM RunCommand Finished.`);
default:
// 上記ステータス以外はlambdaを異常終了させる。
context.fail(new Error(`SSM RunCommand Failed.`));
}
});
};
// エラーが発生した場合再実行を行う関数
const retry = (func, onError) => {
const _retry = (e) => {
return onError(e)
.catch((e) => {
throw e;
})
.then(func)
.catch(_retry);
};
return func().catch(_retry);
};
// 実行結果が特定できるまで繰り返し処理する。
await retry(runCommandStatusGetFunction, (e) => {
console.error(e);
return new Promise((resolve) => setTimeout(resolve, 2000));
});
};
module.exports = {
startSsmRunCommandHandler: startSsmRunCommandHandler
};