Pickup
- aws-sam-cliを利用した
ローカルで擬似的にS3のputイベントを検知させるテスト with golang
の備忘録です - 事前にhello world編を見ておいて頂けると環境が整います
Requirement
- golang:1.11.4
- aws-cli
- aws-sam-cli
- docker (local lambda test)
Document
■ どうやったらlocalでS3のputイベント作れる?
- そもそもどうやってsamコマンドってどんなことできるぞや?
- イベントとかはどうやってつくる?
の疑問を解消させていくために、samコマンドのヘルプを参照してみる。
(※ 以下、ざっくり和訳なのであしからず)
sam
- aws-sam-cliのalias
- cloudformationのサーバーレス拡張版
- オプションでやることが大分違うが、「生成 / ビルド / localでのテスト / バリデーションチェック / deploy」など一通りこの子で完結できる
→ sam自体が色々なことができる模様。
寄り道して他のものも見てみたくなるが、今回は local
にのみピックアップ。
$ sam --help
Usage: sam [OPTIONS] COMMAND [ARGS]...
AWS Serverless Application Model (SAM) CLI
The AWS Serverless Application Model extends AWS CloudFormation to provide
a simplified way of defining the Amazon API Gateway APIs, AWS Lambda
functions, and Amazon DynamoDB tables needed by your serverless
application. You can find more in-depth guide about the SAM specification
here: https://github.com/awslabs/serverless-application-model.
Commands:
logs Fetch logs for a function
deploy Deploy an AWS SAM application. This is an alias for 'aws
cloudformation deploy'.
package Package an AWS SAM application. This is an alias for 'aws
cloudformation package'.
publish Publish a packaged AWS SAM template to the AWS Serverless
Application Repository.
init Initialize a serverless application with a...
build Build your Lambda function code
validate Validate an AWS SAM template.
local Run your Serverless application locally for...
sam local
-
generate-event
:- 疑似イベントつくる
-
invoke
:- Lambda functionの実行
-
start-api
:- 開発するAPIのテストする時にローカルエンドポイントをセットする。
- なお、 hot-reloadingしているためfunctionに変更を加えた場合でもRestartする必要はない
-
start-lambda
:- ローカルエンドポイントに設定したLambda funcを使えるように起動するコマンド
→ 今回のお目当ては generate-event
$ sam local --help
Usage: sam local [OPTIONS] COMMAND [ARGS]...
Run your Serverless application locally for quick development & testing
Options:
--help Show this message and exit.
Commands:
generate-event You can use this command to generate sample...
invoke Invokes a local Lambda function once.
start-api Sets up a local endpoint you can use to test your API.
Supports hot-reloading so you don't need to restart this
service when you make changes to your function.
start-lambda Starts a local endpoint you can use to invoke your local
Lambda functions.
sam local generate-event
helpにS3イベントの作成コマンドがまとまっているのでこれを活用する。
$ sam local generate-event --help
Usage: sam local generate-event [OPTIONS] COMMAND [ARGS]...
~ (中略) ~
Generate the event that S3 sends to your Lambda function when a new object is uploaded
$ sam local generate-event s3 [put/delete]
You can even customize the event by adding parameter flags. To find which flags apply to your command,
run:
$ sam local generate-event s3 [put/delete] --help
Then you can add in those flags that you wish to customize using
$ sam local generate-event s3 [put/delete] --bucket <bucket> --key <key>
After you generate a sample event, you can use it to test your Lambda function locally
$ sam local generate-event s3 [put/delete] --bucket <bucket> --key <key> | sam local invoke <function logical id>
~ (後略) ~
■ S3のputイベントを作る
$ sam local generate-event s3 put --bucket test.secondly --key app/test.json
※ bucketは指定しないと example-bucket
が指定されるのでbucket指定操作を行う場合は注意
※ 今回はkeyは別に入れなくても問題ないが、見栄えのためいれた
■ S3の擬似putイベントをgolangに検知させる
どんなイベントをキャッチしたかわかりやすいようにmain.goを修正。
$ cat hello-world/main.go
package main
import (
"fmt"
"context"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, s3Event events.S3Event) {
for _, record := range s3Event.Records {
if record.EventName == "ObjectCreated:Put" {
s3 := record.S3
fmt.Printf("[SUCCESS] event doing!! - %s \n",record.EventName)
fmt.Printf("[%s - %s] Bucket = %s, Key = %s \n", record.EventSource, record.EventTime, s3.Bucket.Name, s3.Object.Key)
} else {
fmt.Printf("[Skip] event doing!! - %s \n",record.EventName)
}
}
}
func main(){
lambda.Start(handler)
}
※ どんなjsonが取得できるかは↓のawsが提供しているリポジトリを参照
https://github.com/aws/aws-lambda-go/blob/master/events/s3.go#L13-L23
buildし直して、実行してみる。
$ make build
GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world
$ sam local invoke "HelloWorldFunction" -e event.json
2019-01-07 13:50:13 Found credentials in shared credentials file: ~/.aws/credentials
2019-01-07 13:50:13 Invoking hello-world (go1.x)
~ (中略) ~
[SUCCESS] event doing!! - ObjectCreated:Put
[aws:s3 - 1970-01-01 00:00:00 +0000 UTC] Bucket = test.secondly, Key = app/test.json
null
~ (後略) ~
→ ObjectCreated:Put
イベントをキャッチし、どんなbucketに対してputイベントがあったかを無事検知できた。