この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
CloudFormationのリソースタイプとして用意されていないものは、カスタムリソースを使用します。
カスタムリソースでlambdaを使用すれば、ちょっと、トリッキーなので注意が必要ですが、たいがい何でもできてしまいます。
今回は、AWS CDKでカスタムリソース(Lambda)を使用する方法を確認してみました。
ちなみに、lambdaは、S3に置く方法とインラインで記述する方法の2種類がありますが、カスタムリソースの応答オブジェクトがcfn-responseモジュールで簡単に返せるインラインでの設置となってます。
2 スタック
スタック生成のコードです。
カスタムリソースは、cfn.CustomResource()で作成できます。providerにインラインのLambda、そして、パラメータは、propertiesから送ることができます。
cdk_custom_resource_lambda.ts
import cdk = require('@aws-cdk/core');
import cfn = require('@aws-cdk/aws-cloudformation');
import lambda = require('@aws-cdk/aws-lambda');
import fs = require('fs');
export class CdkCustomResourceStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const customResourse = new cfn.CustomResource(this, 'function', {
provider: cfn.CustomResourceProvider.lambda(new lambda.SingletonFunction(this, 'singleton', {
functionName: "customResourceLambdaFunction",
uuid: '7731874a-3a77-80d5-cd8e-6350510edf90',
code: new lambda.InlineCode(fs.readFileSync('lambda/index.js', { encoding: 'utf-8' })),
handler: 'index.handler',
timeout: cdk.Duration.seconds(300),
runtime: lambda.Runtime.NODEJS_8_10
})),
properties: {"Message": "bod boy"}
});
new cdk.CfnOutput(this, "response", {
value: customResourse.getAtt('Response').toString()
});
}
}
const app = new cdk.App();
new CdkCustomResourceStack(app, 'CdkCustomResourceLambdaStack');
カスタムリソースに送ったパラメータを、再び戻り値で受け取って出力しています。
3 カスタムリソース
カスタムリソースのLambdaです。
cfn-responseモジュールを使用して、レスポンスを生成しています。
CDKからのパラメータは、 event['ResourceProperties'] で受け取り、send()の第4パラメータで戻り値を返すことができます。
すいません、今回は試していませんが、event['RequestType'] で、Create/Delete/Updateに対応した処理も記述可能のようです。
"use strict";
const cfnresponse = require('cfn-response');
exports.handler = (event, context) => {
console.log(JSON.stringify(event));
console.log(JSON.stringify(context));
const params = event['ResourceProperties']; // Papameters
const _requestType = event['RequestType']; // Create, Delete, Update
try {
const data = {
'Response': 'Your message: ' + params.Message
};
cfnresponse.send(event, context, cfnresponse.SUCCESS, data);
}
catch (error) {
console.log(error);
cfnresponse.send(event, context, cfnresponse.FAILED, {});
}
};
4 サンプル
サンプルをGitHubに置きました。名前等の競合がなければ、下記の手順で利用可能です。
- ダウンロード
$ git clone https://github.com/furuya02/CdkCustomResourceLambda.git
$ cd CdkCustomResourceLambda
- デプロイ
$ yarn
$ tsc
$ cdk synth
$ cdk deploy
Do you wish to deploy these changes (y/n)? y
- スタックの削除
cdk destroy
5 注意
今回、色々試していて気がついた点を列挙させて下さい。
これは、AWS CDKに限った話では無いですが、カスタムリソースでLambdaを使用する場合、下記の点に注意すると作業がスムーズに進むかも知れません。
- インラインで記述するので、特別なモジュールの読み込みはできない
- Lambdaの定義は、inlineで行う code: new lambda.InlineCode(fs.readFileSync()
- AWS CDKからパラメータで送ったキー名が、ラージキャメルに変更される(ログから渡されているパラメータを確認したほうが良い)
- カスタムリソースのLambdaは、確実に応答オブジェクトを返す send()
- カスタムリソースのLambdaは、asyncで起動すると、応答オブジェクトが返る前にLambdaが終了するので正常にスタックが作成されない(CREATE_IN_PROGRESSで止まる)
- send()メソッドの第4パラメータは、Deleteでも必要
- カスタムリソースのLambdaでNode10.xは使えない
- cdkの下の.gitignoreには、.jsが入っているので、インライン用のjsを対象外にしておかない、Githubへのpushで洩れる
CREATE_IN_PROGRESSで止まってしまったら、削除して1時間ぐらい放置する(すぐには消せない)[2019/08/03]↑こちらについては、下記で対策可能であると@toriclsさんから教えて頂きました。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-lambda-resource-delete/
6 最後に
今回は、カスタムリソースをAWS CDKで書いてみました。 失敗して、CREATE_IN_PROGRESSのまま返ってこなくなると、悲しくなります。