AWS S3イベントをトリガーにLambda Functionを実行する

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

Lambda FunctionはS3で発生したイベント(例えばオブジェクトのputやdelete)をトリガーに実行することができます。

ここではS3にオブジェクトをputした契機でLambda Functionを実行する方法を記述します。


Lambda関数の作成

関数の設計図から作成するとS3イベントの作成、紐付けも同時に行えます。

設計図の使用からs3-get-object-pythonを選択。

  • 関数名: 任意の関数名を入力
  • 実行ロール: 大抵の場合、S3のオブジェクトにアクセスするのでS3へのアクセス権のあるロールを割り当てておきます。


S3トリガー

イベントをウォッチするS3バケットの入力を行います。

  • バケット: 対象のバケットを入力
  • イベントタイプ: バケットに対してのトリガー対象の操作。例えばオブジェクトが書き込まれた時に関数を実行したい場合は、すべてのオブジェクト作成イベントを指定
  • プレフィックス: プレフィックスに一致するオブジェクトが作成された場合のみ関数を実行
  • サフィックス: 例えば拡張子など、サフィックスが一致したオブジェクトが作成された場合のみ関数を実行
  • トリガーの有効化: チェックする

トリガーを後から有効/無効にする場合、DesignerパネルからS3をクリックし、有効・無効トグルをon/offすればよい。

関数を作成することでS3イベントも作成される。

f:id:letitride:20200604184423p:plain


関数作成・トリガーの有効化時点で、S3の対象バケットにputが発生すれば作成したLambda関数が実行される。


テストイベントの設定

テストイベントを作成する時、S3 Putというテンプレートを指定できる。S3オブジェクトが作成時のイベントモックなので問題なければこれを利用すれば良い。


Python Boto3を利用してS3へアクセスする

Boto3を利用すれば簡単にS3オブジェクトを操作できる。上述したS3へのアクセスロールが必要。

オブジェクトの取得。eventに影響があったS3オブジェクトの情報が渡されてくる。

import boto3

s3 = boto3.resource('s3')
for rec in event['Records']:
  filename = rec['s3']['object']['key']
  bucketName = rec['s3']['bucket']['name']
  obj = s3.Object(bucketName, filename)
  response = obj.get()
  print( response['Body'].read() )


オブジェクトの保存

obj = s3.Object('buketName', filename)
response = obj.put(
  Body='file content...'
)


関数のサンプル

import boto3
import os

def lambda_handler(event, context):
  s3 = boto3.resource('s3')
  for rec in event['Records']:
    filename = rec['s3']['object']['key']

    # putされたファイルの読み込み
    obj = s3.Object(rec['s3']['bucket']['name'], filename)
    response = obj.get()

    # S3にアップロード
    obj = s3.Object('lambda-relation-write-bucket', filename + '.zip')
    response = obj.put(
      Body=response['Body'].read()
    )

# EC2でのテスト用 必要なevent hashを定義
import json
if __name__ == "__main__":
    data = '''
{
  "Records": [
    {
     "s3": {
        "bucket": {
          "name": "lambda-relation-bucket"
        },
        "object": {
          "key": "sample.txt"
        }
      }
    }
  ]
}
'''
    event = json.loads(data)
    context = None
    lambda_handler(event, context)