Serverless FrameworkとAWS Lambda with Python or Node.jsでS3アクセス

前回RubyでServerless Frameworkを触ってみました。今回は同じことをPythonとNode.jsでします。

作成するAWS Lambdaは、前回と同じですが、CloudWatchからスケジュール起動します。Lambdaでの処理内容はS3にアクセスしてログに残すのみです。

カレントディレクトリにひな型作成

$ serverless create --template aws-python3
Serverless: Generating boilerplate...
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v2.16.1
 -------'

Serverless: Successfully generated boilerplate for template: "aws-python3"
Serverless: NOTE: Please update the "service" property in serverless.yml with your service name

Node.jsであれば aws-python3 のかわりに aws-nodejs とします。

3つのファイルが生成されました。前回のRubyとの違いはソースファイルの拡張子のみ。

  • .gitignore
  • handler.py または handler.js
  • serverless.yml

ソースコード

serverless.yml は以下の内容にします。前回のRubyとの違いは runtime の欄のみです。

service: sample

frameworkVersion: '2'

provider:
  name: aws
  runtime: python3.8 # Node.js の場合は nodejs12.x
  region: ap-northeast-1
  iamManagedPolicies:
    - arn:aws:iam::aws:policy/AmazonS3FullAccess

functions:
  hello:
    handler: handler.hello
    events:
      # AWS CloudWatchのスケジュール設定
      # 2分おきに実行
      - schedule: cron(*/2 * * * ? *)
    environment:
      # Python実行時の環境変数の設定
      S3_BUCKET: ...
      S3_KEY: ...

PythonまたはJavaScriptのソースファイルは以下の通りです。S3からテキストファイルを読み込んで標準出力しています。標準出力の内容はCloudWatch Logsに書き出されます。

handler.py

import os
import boto3

# 環境変数取得
s3_bucket = os.environ["S3_BUCKET"]
s3_key = os.environ["S3_KEY"]

def hello(event, context):
    res = readS3Object()
    print(res)

def readS3Object():
    session = boto3.session.Session()
    s3_client = session.client("s3")
    res = s3_client.get_object(
        Bucket = s3_bucket,
        Key = s3_key,
    )
    return res['Body'].read().decode("utf-8")

handler.js

'use strict';

const AWS = require('aws-sdk');

// 環境変数取得
const s3_bucket = process.env.S3_BUCKET;
const s3_key = process.env.S3_KEY;

module.exports.hello = async event => {
    const s3 = new AWS.S3();
    return new Promise(function(resolve, reject) {
        s3.getObject({ Bucket: s3_bucket, Key: s3_key }, function(err, data) {
            if (err) {
                console.log(err);
            }
            const body = data.Body;
            let text = "";
            for (let i = 0, len = body.byteLength; i < len; i++) {
                text += String.fromCharCode(body[i]);
            }
            console.log(text); // CloudWatchに書き出す
        });
    });
};

※エラー処理はいい加減です。先日の記事 API GatewayとLambdaを使ってS3の静的ホスティングをしてみる のほうが少しマシです。

デプロイ

$ serverless deploy -v

serverless.yml に書いたスケジュールが過ぎると、CloudWatch Logsに実行されたログが残っていることを確認できます。