ローカル環境でLambda+S3のテストをする
ローカル環境でLambda+S3のテストをする:
sam local & localstack を使ってローカルでLambdaのテストする環境を構築したときの手順とハマったところをまとめたものです。おもに参考文献[2]を参考にして構築しました。
SAMのリソースの作成方法についてはここではあまり触れていません。
公式ページの説明にしたがってインストールします。
dockerコンテナの起動
locastack の場合も、aws-cli を呼び出すときに profile の設定がないとコケます[1]
環境変数によってS3の参照先を切り分けるロジックをアプリケーションのコードに実装します。
sam local 上に起動した lambda function を起動します
手動で次のように入力します
SAM Local と localstack を使って Docker Container 上に起動した lambda function から local stack 上に起動した S3 に疎通することができました。
ただ、結局のところ以下のような手順を毎回実行するので、開発サイクルの高速化はさほどのぞめませんでした(AWSコンソール上でソースコード修正 => テスト実行のほうがむしろ早いかも)。
概要
sam local & localstack を使ってローカルでLambdaのテストする環境を構築したときの手順とハマったところをまとめたものです。おもに参考文献[2]を参考にして構築しました。SAMのリソースの作成方法についてはここではあまり触れていません。
構築の要件
- Lambda Function の中で S3 を参照している部分をローカル環境でテストしたい
- テストサイクルが早くなることを期待
Stack
- AWS SAM
- SAM CLI, version 0.10.0
- localstack
手順
必要な資材のインストール
公式ページの説明にしたがってインストールします。- aws-sam-cli
- docker for Mac
localstack の起動
docker-compose.yml
version: '3'
services:
localstack:
image: localstack/localstack
ports:
- 4567-4578:4567-4578
- 8080:8080
docker-compose up -d
profileの設定
locastack の場合も、aws-cli を呼び出すときに profile の設定がないとコケます[1]~/.aws/credentials
[localstack] aws_access_key_id = dummy aws_secret_access_key = dummy
~/.aws/config
[profile localstack] region = us-east-1 output = text
Localstack上の S3 に Bucket/Object を作成する
message.txt
Hi, there!
# bucket作成 aws s3 --endpoint-url=http://localhost:4572 s3api create-bucket --bucket test-bucket --profile=localstack # オブジェクト作成 aws s3 --endpoint-url=http://localhost:4572 cp message.txt s3://test-bucket --profile=localstack
docker networkの確認
sam local 実行時に docker network を指定しないと、SAM Local => localstackに疎通ができません。 [2]docker network ls (sam-app/script) 18:49:45 NETWORK ID NAME DRIVER SCOPE ... b2fbba06747a localstack_default bridge local ...
環境変数をSAMのテンプレートで指定する
sam local 実行時に --env-vars で環境変数を指定しても、 SAMテンプレートに環境変数が指定されていないと有効になりません。env.json
{
"S3ReadFunction": {
"IS_LOCAL_STACK": "true",
"S3_BUCKET": "test-bucket"
}
}
template.yaml
Globals:
Function:
Environment:
Variables:
IS_LOCAL_STACK: false
S3_BUCKET: 'production-bucket'
S3のエンドポイントに localstack のエンドポイントを指定する
環境変数によってS3の参照先を切り分けるロジックをアプリケーションのコードに実装します。app.js
const AWS = require('aws-sdk');
// localstack
const config = {
endpoint: (process.env.IS_LOCAL_STACK === "true"? "http://localstack:4572": undefined),
s3ForcePathStyle: process.env.IS_LOCAL_STACK === "true",
}
const s3 = new AWS.S3(config);
const { S3_BUCKET_MAIL_BOX } = process.env;
// handlerのコード
exports.lambdaHandler = async (event, context) => {
try {
const params = {
Bucket: S3_BUCKET,
Key: event.Key
};
const ret = await s3.getObject(params).promise();
const message = ret.Body.toString();
console.log(message);
} catch (err) {
console.log(err);
return err;
}
};
ビルド
sam build --use-container
sam local 実行
sam local 上に起動した lambda function を起動しますsam local invoke S3ReadFunction --docker-network b2fbba06747a --env-vars env.json --profile=localstack
標準入力
{"Key": "message.txt"}<Enter>
<Ctrl-D>
出力結果
... 2019-02-01T09:34:34.903Z 3d01ad34-1760-1c18-4042-4088ba5fffa1 Hi, there! ...
終わりに
SAM Local と localstack を使って Docker Container 上に起動した lambda function から local stack 上に起動した S3 に疎通することができました。ただ、結局のところ以下のような手順を毎回実行するので、開発サイクルの高速化はさほどのぞめませんでした(AWSコンソール上でソースコード修正 => テスト実行のほうがむしろ早いかも)。
- docker image のビルド (
sam build --use-container) - docker container の起動 (
sam local invoke)
コメント
コメントを投稿