CloudFormationを利用してS3を作成する場合、内容よってはオブジェクトも出力されてしまっているというパターンがあるかと思います。このときスタックの削除を試みるとオブジェクトが残っているので、中身のオブジェクトを先に削除しないとスタックの削除ができないという悲しい自体が発生します。検証などでリソースの再作成を繰り返してると、これが地味に手間なのです。
これはカスタムリソースという手法を利用すれば、スタックの削除一発でオブジェクトの削除まで可能になります。今回はこの方法を書いていたきいと思います
カスタムリソースとは
通常のリソースタイプではできない処理に機能を追加して処理させる方法です。今回の例だと、通常S3削除時にはオブジェクトを削除するという動作はできませんが、このカスタムリソースを使用することでオブジェクトを削除するという動作を追加することができます。
S3オブジェクト削除用lambda
下記S3削除用のlambdaをデプロイします。Outputsでは、S3の作成が記述されたどこのyamlでも使えるようにエクスポートさせてます。
AWSTemplateFormatVersion: "2010-09-09"
Description: lambda to delete object in S3
Resources:
s3deletelambda:
Type: AWS::IAM::Role
Properties:
RoleName: s3_delete_lambda_role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: s3delete
Role: !GetAtt s3deletelambda.Arn
Runtime: python3.7
Handler: index.lambda_handler
Timeout: 600
Code:
ZipFile: | #ここから先にlambadaのコードを記載する
...
Outputs: # どこのS3作成先でも使えるようにクロススタック
LambdaFunction:
Value: !GetAtt LambdaFunction.Arn
Export:
Name: LambdaFunction-cfn-arn
lambdaのコードはこちらを参照(動作確認済みです)
クロススタックがわからないひとはこちらへ
S3側
S3を作成してるコードのResourcesにカスタムリソース使うよのコードを追加してあげます。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
...
LambdaUsedToCleanUp:
Type: Custom::cleanupbucket
Properties:
ServiceToken: {Fn::ImportValue: LambdaFunction-cfn-arn}
BucketName: !Ref XXX
検証のときつらかったこと
lambdaはCloudFormationの記述ミスると1時間レスポンス返ってこなくなります。 その間基本的には待つしかないようなので、できるだけコードは詰めてからスタックは流した方がよいです。
私はハンドラーのところで記述を間違えて、上記事象の罠にしばらくとらわれてしまいました。下記ご参考にどうぞ。
Handler: ファイル名(拡張子なし).ハンドラー名 → index.lambda_handler
※参考