■ はじめに
https://dk521123.hatenablog.com/entry/2017/04/05/235618
https://dk521123.hatenablog.com/entry/2021/10/07/103317
の続き。 (よくありがちな) AWS Lambdaで、 S3バケット内のファイルを監視し、 そのファイルを別の場所にデプロイする、、、みたいなことをやってみる (本当は、Serverless Framework で実装したかったが 時間もないので、ひとまず、手動でデプロイする形で、、、) => (追記 2024/05/26)Serverless Framework v4 が、 有償になったため、別フレームワークを考える
Serverless Framework以外のフレームワーク
https://dk521123.hatenablog.com/entry/2024/05/26/001612
目次
【1】今回やること 1)その他事項(Version) 【2】Tips 1)S3バケットおよびパスの取得 2)メモ:Python3.12 上の注意点 【3】使用上の注意 1)S3イベント再作成する場合 【4】構築手順例 0)前提条件 1)Lambda関数をAWS上に登録する 2)トリガーの追加する 3)【任意】環境変数の追加する 4)処理したいプログラムを実装する 5)動作確認 【5】サンプル
【1】今回やること
[1] S3バケットのファイルを監視し、ファイルが更新された場合にLamda起動 [2] そのファイルを、REST API経由でアップロードする
1)その他事項(Version)
* Python: Python3.12
【2】Tips
1)S3バケットおよびパスの取得
import urllib.parse def lambda_handler(event, context): # ★引数 event から以下のように取得 s3_bucket_name = event["Records"][0]["s3"]["bucket"]["name"] s3_key = urllib.parse.unquote_plus(event["Records"][0]["s3"]["object"]["key"], encoding="utf-8") logger.info(f"Event fired from s3 [s3://{s3_bucket_name}/{s3_key}]")
2)メモ:Python3.12 上の注意点
(AWS Lambda とは、直接関係ないが、作ってて築いたので、メモ) * いくつかのライブラリが廃止されている => 例えば、以下の関連記事で扱った distutilsパッケージ とか。
Python ~ 基本編 / bool ~
https://dk521123.hatenablog.com/entry/2021/10/02/000000
【3】使用上の注意
1)S3イベント再作成する場合
間違ったなどでS3イベント再作成する場合、 エラー「Configuration is ambiguously defined」が表示される可能性がある。 なお、対象方法については、以下の関連記事を参照のこと
Lambda のトラブルシュート
https://dk521123.hatenablog.com/entry/2017/12/16/231714
【4】構築手順例
0)前提条件
* S3バケット自体は作成済 * AWS Lambda に使うロール/VPCは作成済
1)Lambda関数をAWS上に登録する
[1] AWSマネージメントコンソールにログインし、 「Lambda」のページにアクセスする [2] 画面右上の「Create function」ボタン押下 [3] 以下を入力し、画面右下の「Create function」ボタン押下 ~~~~~~~ * 「Author from scratch」を選択(デフォルトで選択されている) Base information * Function name : 任意(今回は「demo-s3-trigger」) * Runtime : Python 3.12 (他にも「3.8」~「3.11」が選択可能) * Architecture : x86_64(デフォルトで選択されている) ~~~~~~~ ※ 後は、既存のロールやVPCなどを選択する ※ 今回は、「Test Event登録およびTest 実行」は省略 => 行いたい場合は、以下の関連記事を参照のこと
Lambda ~ Python / 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/07/103317
2)トリガーの追加する
「1)-[3]」の流れのまま... [1] 「Add trigger」ボタン押下 [2] Add triggerの設定ページにおいて、以下を「s3」と入力すると 「s3」アイコンがでてくるので選択 [3] 選択すると、以下の項目が現れるので、適宜入力し「Add」ボタン押下 * Bucket: 対象のS3バケット名(ここでは「your-s3-bucket」) * Event types : 任意のイベント(ここでは、デフォルトの「All object create events」) * Prefix: 任意(ここでは「images/」) * Suffix: 任意(ここでは「.png」) * Recursive invocation: 内容(I acknowledge that...)を確認し、チェック
3)【任意】環境変数の追加する
[1] [Configuration]-[Environment variables]を選択 [2] 「Edit」ボタン押下 [3] 「Add environment variables」ボタン押下 [4] Key/Valueを入力し「Save」ボタン押下 * Key: 任意 (今回は「TARGET_URL」,「DRY_RUN」) * Value: 任意(今回は「http://your-rest-api-host:9092」,「false」)
4)処理したいプログラムを実装する
[1] 以下「【4】サンプル」を参考に実装 [2] 「Deploy」ボタン押下
5)動作確認
[1] 該当S3バケットのパスにファイルを置く [2] Lambda の画面で、 [Monitor]-[View CloudWatch logs]を選択し、ログを確認できる
【5】サンプル
import os import logging import json import urllib.parse import boto3 logger = logging.getLogger() logger.setLevel(logging.INFO) logger.info("Loading function") s3_client = boto3.client("s3") def lambda_handler(event, context): # Step1: Get the object from the event and show its content type s3_bucket_name = event["Records"][0]["s3"]["bucket"]["name"] s3_key = urllib.parse.unquote_plus(event["Records"][0]["s3"]["object"]["key"], encoding="utf-8") logger.info(f"Event fired from s3 [s3://{s3_bucket_name}/{s3_key}]") try: # Step2: Get contents response = s3_client.get_object(Bucket=s3_bucket_name, Key=s3_key) target_content = response ["Body"].read() # Step3-1: Create request to upload a file url = os.getenv("TARGET_URL", "http://your-rest-api-host:9092") req = urllib.request.Request( url, target_content , method="POST", headers={"Content-Type": "application/octet-stream"}, ) # Step3-2: Send the request and print response is_dry_run = os.getenv("DRY_RUN", "false").lower() == "true" if (is_dry_run ): logger.info("just dry run...") else: logger.info("Uploading...") with urllib.request.urlopen(req) as res: logger.info(json.loads(res.read())) except Exception as ex: logger.error(ex) raise ex logger.info("Done...") return { "statusCode": 200, "body": { "result": "The process is successful!!" } }
参考文献
よくありがちなので、ほぼそのまんまの例があった。
公式ドキュメント
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example.html
その他一般サイト
https://qiita.com/hp-Genqiita/items/676a830105cce4a82039
関連記事
Lambda ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2017/04/05/235618
Lambda ~ Python / 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/07/103317
Lambda ~ Python / 外部モジュール追加 ~
https://dk521123.hatenablog.com/entry/2024/05/25/005456
Lambda のトラブルシュート
https://dk521123.hatenablog.com/entry/2017/12/16/231714
Serverless Framework ~ 環境設定編 ~
https://dk521123.hatenablog.com/entry/2023/11/02/000200
Serverless Framework ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/11/03/234825
Serverless Framework ~ offline ~
https://dk521123.hatenablog.com/entry/2023/11/09/004458
Serverless Framework以外のフレームワーク
https://dk521123.hatenablog.com/entry/2024/05/26/001612
Python ~ 基本編 / urllib ~
https://dk521123.hatenablog.com/entry/2022/08/05/000000
Python ~ Requestsライブラリ ~
https://dk521123.hatenablog.com/entry/2024/05/23/162229
Python ~ 基本編 / bool ~
https://dk521123.hatenablog.com/entry/2021/10/02/000000
Python ~ 基本編 / ファイル読込・書込 ~
https://dk521123.hatenablog.com/entry/2019/10/07/000000
Python ~ 基本編 / 正規表現 ~
https://dk521123.hatenablog.com/entry/2019/09/01/000000
Terraform ~ AWS Lambda / あれこれ ~
https://dk521123.hatenablog.com/entry/2024/05/31/005406