S3のバケットsrc-bucketに画像がアップロードされたら、それをトリガーにして別のバケットdest-bucketにコピーする関数をLambdaで作成する。言語はpython 3.6。
やりたいこと
src-bucketにobj.jpgがアップロードされたら、自動的にobj.jpgをdest-bucketにコピーしたい。
AWSのLambdaを使って、そのような関数を作成する。
IAMロールの作成
Lambda関数に適用するIAM ロールを作成する。
IAMロールには、以下のポリシーを適用する。
- AWSLambdaBasicExecutionRole
- テンプレートにある
- CloudWatch Logsに書き込むため
- s3:GetObjectとs3:PutObjectをsrc-bucketおよびdest-bucketに対して利用できるようなポリシー
ビジュアルエディターで作ると楽。作ったもののjsonは以下。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::src-bucket/*",
"arn:aws:s3:::dest-bucket/*"
]
}
]
}
Resourceのバケット名は適当に。ちなみにこれだと、srcとdestの両方に読み書きの権限が与えられてしまうので、ちゃんとわけたほうが丁寧だが、ここでは一緒にする。
Lambda関数の作成
Lambda関数を作る。コンソール画面から行う。
IAMロールは前節で作ったものを適用する。ソースコードは以下。
import json
import urllib.parse
import boto3
import os
print('Loading function')
s3 = boto3.client('s3')
def lambda_handler(event, context):
src_bucket = os.getenv('SRC_BUCKET_NAME')
dest_bucket = os.getenv('DEST_BUCKET_NAME')
src_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
dest_key = src_key
try:
cp_src = f"{src_bucket}/{src_key}"
print(f"src: {cp_src}")
print(f"dest: {dest_bucket}/{dest_key}")
response = s3.copy_object(Bucket=dest_bucket, CopySource=cp_src, Key=dest_key)
return True
except Exception as e:
print(e)
print('Error getting/putting object.')
raise e
バケット名を環境変数でSRC_BUCKET_NAMEとDEST_BUCKET_NAMEにしているので、そのように設定する。
テストイベントは、「S3 Put」をテンプレートにして、event['Records'][0]['s3']['object']['key']に相当するところを、適当なファイル名にするとよい。そのファイル名で、src_bucketにファイルを上げておけば、テストができる。
トリガーの設定
テストがとおるようになったら、トリガーを設定する。Designerより、「トリガーの追加」からS3を選択し、「バケット」と「イベントタイプ」を選ぶ。バケットはsrc-bucket、イベントタイプは「オブジェクトの作成(すべて)」。トリガーの有効化にチェックを入れて追加。
これで、なにかsrc-bucketにアップロードして、dest-bucketにコピーされていればOK。
このトリガーの設定による影響を、S3の「プロパティ」→「Events」で確認できる。Lambda関数だけ消しても、Eventsの設定は残ることに注意。
参考
ありがとうございました。
コメント