[AWS] Lambdaをローカルで開発するためにAWS SAMに入門してみた (S3のputイベント検知編)

[AWS] Lambdaをローカルで開発するためにAWS SAMに入門してみた (S3のputイベント検知編):


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イベントがあったかを無事検知できた。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)