【Golang + Lambda + API Gateway】で、S3バケットを作るAPIを作ってみた


前提条件

2019年12月29日に試してみたものです。
Go 1.12.9

1. GolangのコードをLambdaで実行

必要なライブラリをインストール

$ go get -u github.com/aws/aws-lambda-go/lambda
$ go get -u github.com/aws/aws-sdk-go/...

指定したバケット名で、S3バケットを作るコード

作った関数は、引数として受け取ったバケット名で、S3バケットを作り、その結果をログに出力するもの。

hello.go
package main

import (
    "log"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

type MyEvent struct {
    BucketName string `json:"bucket_name"`
}

func hello(event MyEvent) {
    // 流れ:認証情報→セッション→S3
    creds := credentials.NewStaticCredentials("AWS_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "") //第3引数はtoken
    session, _ := session.NewSession(&aws.Config{
        Credentials: creds,
        Region:      aws.String("ap-northeast-1")},
    )
    svc := s3.New(session)
    resp, _ := svc.CreateBucket(&s3.CreateBucketInput{
        Bucket: aws.String(event.BucketName),
    })
    log.Println(resp) //Lambdaテストの実行結果のログ出力や、CloudWatchのロググループで確認できる
}

func main() {
    lambda.Start(hello)
}

ビルド(クロスコンパイル)して、zipファイルにする

Lambdaで動かすためには、普通にgo buildするのではなく、Linux上でも動作するようにクロスコンパイルの設定を追加する必要がある

$ GOOS=linux GOARCH=amd64 go build -o hello
$ zip handler.zip ./hello

zipファイルをLambdaにアップロード

  1. Lambdaコンソールから関数を作成し、上記で作成したZIPファイルをアップロード
  2. Lambdaの関数コードのハンドラは、作成した関数名と一致させる(本記事ではhello)
  3. 忘れずに保存ボタン

テスト(動作確認)

  • Lambdaコンソールの「テストイベントの設定」画面で、下記のjsonデータを入力
  • S3バケット名になるため、一意になる名前を指定
{
  "bucket_name": "test191229" 
}
  • S3コンソールで、指定したバケット名で作られているか確認
  • ログ出力を確認 → 成功した場合、「Location」(S3のURL)が返ってくる

2. API GatewayでAPI作成

  1. API Gatewayコンソールから「APIの作成」→REST APIの「構築」ボタン
  2. API名を入力し、API作成
  3. アクション→「リソースの作成」(リソース名は、アクセスするパスになるので注意
  4. アクション→「メソッドの作成」(GETを指定し、作ったLambda関数を指定)
  5. 「メソッドリクエスト」→「URLクエリ文字列パラメータ」を追加(bucket_name)
  6. 「マッピングテンプレートの追加」(Content-Type:application/json)
  7. 「テンプレートの生成」→emptyにし、以下を入力
#set($inputRoot = $input.path('$'))
{
    "bucket_name" : "$input.params('bucket_name')"
}

 ※上記が、作成したhello関数の引数として入ってくる

$input.params(x)

パラメータ名文字列 x が指定された場合に、パス、クエリ文字列、またはヘッダー値から (この順番で検索される) メソッドリクエストパラメータの値を返します。

マッピングテンプレートで使える変数・関数
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

8.最後に、「アクション」→「APIのデプロイ」(ここで入力するステージも、アクセスするパスになるので注意

アクセスするURL

  • 「APIのデプロイ」後、Lambdaコンソールに表示されるURLを利用
  • 例えば、ステージ名が「stage」、リソース名が「myresource」、「URLクエリ文字列パラメータ」が「bucket_name」の場合、
    URL/stage/myresource?bucket_name=test191230

  • ここにアクセスすると、「test191230」というS3バケットが作成される

参考にさせて頂いた記事

AWS Lambda で Go が使えるようになったので試してみた
golang + Lambda + API GatewayでREST APIを作ってみた
AWS SDK for Go S3バケット基本操作