はじめに
CloudFomationでLambdaリソースを作るにはやり方が2つ。
- S3へ事前に固めたZipファイルを指定してLambdaリソースを作る
- テンプレートファイルそのものにインラインでベタ書きで書いてしまう
後者のベタ書きだと色々不都合があって、
- Nodejs.18ランタイムだと、CommonJS形式の強制的にindex.jsになる(マネコンからデフォルトで作成するとES形式のindex.mjsなのに)
- テンプレートとコードが分離できないので、IDEのlinterが通せない
- インラインだとテンプレートファイルがそもそも見にくい
テンプレートへのインラインベタ書きをやめるには、CodeセクションでLambdaコードにS3へアップロードしたZipファイルを指定すればよく、AWS CLIだとaws cloudformation package
が使えるが、自前でpackage化して面倒くささを体感してみる。
参考:packageコマンド
つくるもの
sam package
の動作を参考にする。
package
コマンドでは、
- 材料となるテンプレートファイルの中でLambdaコードのローカルのファイルパスを指定して
- テンポラリなzipファイルを作成してS3へアップロードすると
- Code部分をS3パスに置き替えた新しいテンプレートファイルを作成してくれる
これをbashとCloudFormationのテンプレートで工夫して実装する。
bash側
zip操作とS3へのアップロード操作。zip時には-j
オプション(junk-paths)が無いとlambdaランタイムがindexファイルを参照できなくなって困る。また、アップロードするS3バケットは一時的にしか使わないので、ライフサイクルルールでファイルが削除されるような設定にしておくと良いかも。
#!/bin/bash
VAR=$(uuidgen);
ARR=(${VAR//-/ });
VAR=${ARR[0]};
TMP_BACKET=bd8z-temporary;
PACKEGE_ZIP="file-${VAR}.zip";
zip -r -j $PACKEGE_ZIP src;
aws s3api put-object --bucket "${TMP_BACKET}" --key "${PACKEGE_ZIP}" --body $PACKEGE_ZIP;
aws cloudformation create-stack --stack-name "stack-${VAR}" --capabilities CAPABILITY_NAMED_IAM --template-body file://templateV2.yaml --parameters ParameterKey=UUID,ParameterValue=${VAR} ParameterKey=LambdaCodeKey,ParameterValue=${PACKEGE_ZIP} ParameterKey=LambdaCodeBucket,ParameterValue=${TMP_BACKET};
CFnのテンプレート側
ParameterセクションでLambda関数のS3の場所を指定できるようにする。
Parameters:
LambdaCodeKey:
Type: String
LambdaCodeBucket:
Type: String
<--------中略------->
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "App-Lambda-${UUID}"
Handler: index.handler
Role: !GetAtt LambdaServiceRole.Arn
Runtime: nodejs18.x
Timeout: 300
Environment:
Variables:
APIPATH: !Sub prod/${APIPath}
APIURL: !Sub https://${RestAPI}.execute-api.${AWS::Region}.amazonaws.com/
BUCKETNAME01: images-for-serverless-page
DYNAMODB_TALBENAME: !Ref MyTable
IMAGE_KEY01: background.png
PARTITION_KEY: !Ref PartitionKey
Code:
S3Bucket: !Ref LambdaCodeBucket
S3Key: !Ref LambdaCodeKey
おわりに
packagingコマンドを使う場合だと、linterで警告が出るので何となく気持ち悪い。自分でS3へアップロードするメリットはこの警告が解消できるぐらいかな。
package コマンドを使う場合にcfn-lintが吐く警告
成果物
packgingコマンドで実行する版も載せた。