AWS SAMでLambdaのみのFunctionを作成してみた
前回に引き続き、AWS SAMネタです。
sam init コマンドで作成されてるのはAPI Gateway + Lambdaという構成のテンプレートなのですが
Lambda単体で動かしたい or Lambdaと別のイベント(S3とかDynamoDBとか)を切っ掛けに動かしたいこともあるかと思います。
なのでsam initコマンドで作成したテンプレートを改修し、Lambda単体で動くFunctionを作成してみました。
以下、やってみた手順とソースです。
手順
既にsam initでプロジェクトが作成済の前提です。
1. プロジェクト内にフォルダを新たに作り、main.goファイルを作成する。
2. main.goを以下のように作成する。
package main import ( "context" "fmt" "time" "github.com/aws/aws-lambda-go/lambda" ) const timeFormat = "2006-01-02 15:04:05" const messageFormat = "Hello, now is %s!" // MyEvent ... type MyEvent struct { Name string `json:"name"` } // HandleRequest ... func HandleRequest(ctx context.Context) (string, error) { t := time.Now() message := createMessage(t) return message, nil } func createMessage(t time.Time) string { return fmt.Sprintf(messageFormat, t.Format(timeFormat)) } func main() { lambda.Start(HandleRequest) }
今回作成したのは現在日時を返すFunctionです。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/go-programming-model-handler-types.html
こちらを元として作成しました。
3. (デプロイまで試すなら)template.ymlを修正して、追加したFunctionをデプロイ対象に加える。
4. Makefileを修正する。
sam init で作成したhello-world、今回作成したmy-eventの両方をビルドするようにしました。
.PHONY: deps clean build all: deps clean build deps: go get -u github.com/aws/aws-lambda-go/events go get -u github.com/aws/aws-lambda-go/lambda clean: rm -rf ./hello-world/hello-world rm -rf ./my-event/my-event build: GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world GOOS=linux GOARCH=amd64 go build -o my-event/my-event ./my-event
5. テストを作成する
main_test.goを作成し、以下のようなテストメソッドを作成しました。
mainの中身とそのままですがw、メッセージを作成する内部処理をテストしています。
package main import ( "fmt" "testing" "time" ) func TestCreateMessage(t *testing.T) { now := time.Now() message := createMessage(now) expect := fmt.Sprintf(messageFormat, now.Format(timeFormat)) if message != expect { t.Fatal("createMessage Failed.") } }
6. ローカルでの実行
ビルドして、ローカルでLambdaを実行してみます。
$ make $ sam local generate-event cloudwatch scheduled-event > my-event.json $ sam local invoke MyEventFunction --event my-event.json
7. テストの実行
go test -v ./my-event/
参考サイト
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-init.html
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/go-programming-model-handler-types.html
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-generate-event.html
AWS SAMによるテンプレートプロジェクト作成~ローカルでの実行
AWS SAMを使い、テンプレートのプロジェクトを作成してローカルで実行するまでの
流れについて纏めてみました。
既に色々なサイトで書かれてはいますが、今後の自分のために書いておきます。
前提として
となります。
プロジェクト作成
$ sam init --runtime go1.x --name your-project-name
プロジェクトが作成されるので、以下のようにMakefileを編集しました。
.PHONY: deps clean build all: deps clean build deps: go get -u github.com/aws/aws-lambda-go/events go get -u github.com/aws/aws-lambda-go/lambda clean: rm -rf ./hello-world/hello-world build: GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world
ローカルでの実行
AWS SAMのインストールでも必要ですが、実行にはDockerが必要となります。
なのでDockerの起動もコマンドに含んでいます。
$ make $ sam local generate-event apigateway aws-proxy > event.json # API Gatewayのイベントを記述したjsonを作成 $ sudo service docker start # docker起動 $ sudo service docker status # docker起動確認 $ sam local invoke HelloWorldFunction --event event.json
テスト
テストのテンプレートとして作成されるので、その実行コマンドになります。
$ go test -v ./hello-world/
AWS CLI、GolangでS3のPre Signed URLを取得してみる
AWS CLIとGolangで、それぞれS3にあるオブジェクトのPre Signed URLを取得してみました。
やってみた背景としては、リクエストがあった時にS3に配置したオブジェクトを安全にリクエスト元へ渡したい、みたいな要件を耳に挟み
- Pre Singed URLを作ればいいんじゃないのか
- 取得元IPは固定だろうから、バケットにIP制限を別途つける
みたいなことを思いついたためです。
バケットにIP制限を付けるあたりは、以下が参考になりそうです。
S3でIP制限 - Qiita
AWS CLIでのPre Signed URL取得
事前にバケットを用意し、ファイルを入れておきます。
またAWS CLIのインストールも必要です。
以下のコマンドで取得できました。
# バケットの中身を確認 $ aws s3 ls s3://your-bucket/ # pre signed urlを発行。--expires-inで有効期間の秒を設定 $ aws s3 presign s3://your-bucket/sample.txt --expires-in 120 https://your-bucket.s3.amazonaws.com/sample.txt?AWSAccessKeyID=xxxxx
取得できたPre Signed URLをブラウザに張り付け、ファイルの中身が表示されることを確認します。
有効期間が過ぎたら再度アクセスして、今度はAccess Deniedになることも確認します。
AWS SDKでの取得
次にaws-sdk-goで取得してみます。
公式サイトのサンプルソースを改変し、以下のようなソースで実行してみました。
package main import ( "log" "os" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) func main() { region := os.Args[1] bucket := os.Args[2] key := os.Args[3] log.Printf("your region = %s, bucket = %s, key = %s\n", region, bucket, key) sess, err := session.NewSession(&aws.Config{ Region: aws.String(region)}, ) svc := s3.New(sess) req, _ := svc.GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), }) urlStr, err := req.Presign(2 * time.Minute) if err != nil { log.Println("Failed to sign request", err) } log.Println("Pre signed url : ", urlStr) }
ビルドし、引数にリージョン・バケット・キーを渡して実行してみます。
$ ./s3-pre-signed-url-get-sample region your-bucket your-key 2019/03/xx xx:xx:xx Pre signed url : https://your-bucket.s3.amazonaws.com/sample.txt?AWSAccessKeyID=xxxxx
「Pre signed url : 」以降に出力されるPre Signed URLをブラウザに張り付け、ファイルの中身が表示されることを確認します。
こちらも無事、表示されるかと思います。
まとめ
AWS CLI、aws-sdk-goを使ってPre Signed URLを取得できることが分かりました。
後はこれらをアプリに組み込み、リクエストがあり次第、取得したPre Signed URLをリクエスト元に返せばいいことになります。
今回作成したGolangのソースは以下にも載せてあります。
GitHub - SrcHndWng/s3-pre-signed-url-get-sample
参考サイト
以下のサイトを参考にさせていただきました。
ありがとうございました。
【小ネタ】AWS CLIでS3のPre-Signed URLを生成できるようになっていました! | Developers.IO
https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/s3-example-presigned-urls.html
Windows Subsystem for Linux上にAWS SAMの実行環境を構築する + Golangの開発環境を用意する
タイトルにあるように、Windows Subsystem for Linux上でAWS SAMを実行する環境を構築してみました。
単純にLinux上にAWS SAMの実行環境を構築するだけと思いきや、細々と調べながら進めることになったので
その結果をメモ代わりに書いておきます。
AWS SAM
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
こちらの公式のガイドを見ればわかるのですが、AWS SAMのCLIの実行には
が必要となります。
Windows Subsystem for LinuxでDockerを動かすのが結構癖がありました。
結論から書いてしまうと
- Dockerは17.09.0を使った
- Windows Subsystem for Linuxを起動するコマンドプロンプト(やパワーシェルのターミナルなど)は管理者権限で起動しておく必要がある
- 管理者権限で起動したターミナル上でdockerを起動しておいたうえで、AWS SAMのコマンドを実行する必要がある
ということになります。
詳細については既に詳しく書かれている方がいたので、そちらを参考にしてください。
どうしても Docker on Ubuntu 18.04 on WSL したかった - Qiita
Windows10 Home の WSL で Docker を使う - Qiita
Golangの開発環境
Windows Subsystem for LinuxでAWS SAMを実行するにあたり、
- Windows上のエディタ(Visual Studio Code) で入力補完を利かせる
- Windows Subsystem for Linux上でビルドを行う
を実現したいと思いました。
結果
- WindowsとWindows Subsystem for Linuxの両方に同じバージョンのGolangをインストールする
- WindowsとWindows Subsystem for LinuxでGOPATHを共有する
ことになりました。
詳細については既に詳しく書かれている方がいたので、そちらを参考にしてください。
WSLENVでWSLとWindowsの環境変数を共有する(Go開発環境編) | re-imagine
まとめ
こんな感じで、一つ一つは簡単なのですが、結構色々と調べつつ環境の構築ができました。
最後に、今回参考にさせていただいたサイトのURLを載せておきたいと思います。
gbのテストで特定のものを実行する、結果を色付けする
タイトルにあるように、gbのテストで
- 特定のパッケージ、メソッドを実行する
- テストの結果の詳細を表示する、結果を色付けして分かりやすくする
方法についてです。
ただgbだけでなく、普通の「go test」でも使えるかと思います。
(go testの場合は「gb」を「go」に変えるだけです。)
パッケージ・メソッドを指定、詳細を表示する方法
まず、パッケージ・メソッドを指定、詳細を表示する方法についてです。
以下のようなコマンドとなります。
gb test パッケージ名 -run テスト対象メソッド -v
それぞれについて説明すると
- パッケージ名 ・・・ gb test の後にテスト対象のパッケージ名を指定
- -run ・・・ テスト対象のテストメソッド名を指定
- -v ・・・ 詳細を出力するためのオプション
です。
結果を色づけする方法
次に結果を色づけする方法についてです。
testing - colorizing golang test run output - Stack Overflow
こちらのstackoverflowの記事を参考にし、今回はsedで特定のキーワードを色付けすることにしました。
先のコマンドの結果をパイプで繋げ、以下のように実行します。
gb test パッケージ名 -run テスト対象メソッド -v \ | sed ''/RUN/s//$(printf "\033[33mRUN\033[0m")/'' \ | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' \ | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/'' \ | sed ''/error/s//$(printf "\033[31merror\033[0m")/''
- RUN ・・・ 黄色
- PASS ・・・ 緑
- FAIL ・・・ 赤
- error ・・・ 赤
にそれぞれ色づけしています。
色の指定については以下のサイトを参考にしました。
http://yonchu.hatenablog.com/entry/2012/10/20/044603
これでGolangのテストについて、ターミナルから実行する場合に少しやり易くなるかと思います。
色を変えるsedコマンドについては、シェルスクリプトなどに書いておいて、パイプでシェルに渡してもいいかもです。
ビルドツールのgbをVisual Studio Codeで使ってみる
Golangのビルドツールのgbを試してみました。
私は普段Visual Studio Codeを使っているので、こちらでエラーとならないよう設定もしました。
gbを使うメリットとしては
- 自分が作成したpackageをimportする際にGopathからのフルパスを書かなくていい
- 使用する外部ライブラリを定義ファイルに記述できる
などです。
以下、私が使用したときの手順メモです。
プロジェクトについて
プロジェクト直下のsrcフォルダ内に自分で作成するソース、vendorフォルダ内に外部ライブラリを保存します。
今回はGitHub - fatih/gb-example: Example gb project with dependencies and CI integrationという、gbを使ったサンプルプロジェクトがあったので
こちらが動くかどうかを試してみました。
git cloneでプロジェクトをダウンロードしてきます。
git clone https://github.com/fatih/gb-example.git
Visual Studio Codeの設定
File - Preferences - Settings より設定を行います。
まだgbを使っているのはこのプロジェクトのみなので、今回はローカルプロジェクトのみ設定する
Workspace Settingsの方に以下の設定を行いました。
- Gocode Package Lookup Mode : gb に変更。
- go.gopathを「"go.gopath": "${workspaceRoot};${workspaceRoot}/vendor"」に設定。
- Windowsだとカンマ区切りか?
- 参考 https://github.com/Microsoft/vscode-go/issues/249
- buildOnSave : offに変更。
gbの使用について
- vendor/manifestに使用するライブラリを記載される。
- なのでvendor/manifest以外はGithub等に上げる必要はない。
外部ライブラリの取得、更新
$ gb vendor update -all
ビルド、テスト
$ gb build $ gb test