Serverless Framework のテンプレートをGo言語で試してみた

# 概要
Serverless Frameworkのtempleateを作成する機能の内の、
*aws-go* を使ってとりあえずデプロイするところまでやってみました。

### 環境
- Node v8.11.1
- npm 5.6.0
- Go 1.10.3
- IAMユーザが作成されていること(AWS APIを使って操作するため)

#### Serverless Frameworkとは
以下の手順などを自動でやってくれるので、開発における手間が省けて超便利。
- Lambda関数を生成する
- 関数をアップロードする
- トリガーとなるイベントの設定

### Serverless Frameworkのインストール
以下のコマンドでインストールしてください。

`npm install -g serverless`

### credentialsの設定
作成してあるIAMユーザのアクセスキー、シークレットアクセスキーを入力してください。

```
❯ vim ~/.aws/credentials

[hoge]
aws_access_key_id =  piyo
aws_secret_access_key = huga
```
[hoge]の部分ですが、複数の環境にアクセスする必要があり、IAMユーザーを使い分ける必要がある場合には、各環境に合うような命名で設定しておくことをお勧めします。

### configの設定

```
❯ vim ~/.aws/config

[hoge]
output = json
region = ap-northeast-1    //好きなリージョンで設定してください。
```

### 新規プロジェクトをtemplateで作成してみる

ここまで設定したら、いよいよslsのtemplateで新規プロジェクトを作成してみます。
次のコマンドは、必ず$GOPATH以下で実行してください。

~/go/src/github.com/xxxxx/sls-sample
`sls create --template aws-go`

実行後、以下のファイルが作成されます。

``` hello/main.go
package main

import (
	"github.com/aws/aws-lambda-go/lambda"
)

type Response struct {
	Message string `json:"message"`
}

func Handler() (Response, error) {
	return Response{
		Message: "Go Serverless v1.0! Your function executed successfully!",
	}, nil
}

func main() {
	lambda.Start(Handler)
}
```

```world/main.go
package main

import (
	"github.com/aws/aws-lambda-go/lambda"
)

type Response struct {
	Message string `json:"message"`
}

func Handler() (Response, error) {
	return Response{
		Message: "Okay so your other function also executed successfully!",
	}, nil
}

func main() {
	lambda.Start(Handler)
}
```


こんな感じでtemplateファイルが作成されたのが確認できたと思います。
作成されたファイルのうち、`serverless.yml`のみ、一部編集をしてください。

```serverless.yml
# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
#    docs.serverless.com
#
# Happy Coding!

service: hoge # 好きなプロジェクト名
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"

provider:
  name: aws
  runtime: go1.x

# you can overwrite defaults here
#  stage: dev
#  region: us-east-1
region: ap-northeast-1  #リージョンを設定してください(今回は東京)

# you can add statements to the Lambda function's IAM Role here
#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"

# you can define service wide environment variables here
#  environment:
#    variable1: value1

package:
 exclude:
   - ./**
 include:
   - ./bin/**

functions:
  hello:
    handler: bin/hello
  world:
    handler: bin/world

#    The following are a few example events you can configure
#    NOTE: Please make sure to change your handler code to work with those events
#    Check the event documentation for details
# events:
#    events:
#      - http:
#          path: users/create
#          method: get
#      - s3: ${env:BUCKET}
#      - schedule: rate(10 minutes)
#      - sns: greeter-topic
#      - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000
#      - alexaSkill: amzn1.ask.skill.xx-xx-xx-xx
#      - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx
#      - iot:
#          sql: "SELECT * FROM 'some_topic'"
#      - cloudwatchEvent:
#          event:
#            source:
#              - "aws.ec2"
#            detail-type:
#              - "EC2 Instance State-change Notification"
#            detail:
#              state:
#                - pending
#      - cloudwatchLog: '/aws/lambda/hello'
#      - cognitoUserPool:
#          pool: MyUserPool
#          trigger: PreSignUp

#    Define function environment variables here
#    environment:
#      variable2: value2

# you can add CloudFormation resource templates here
#resources:
#  Resources:
#    NewResource:
#      Type: AWS::S3::Bucket
#      Properties:
#        BucketName: my-new-bucket
#  Outputs:
#     NewOutput:
#       Description: "Description for the output"
#       Value: "Some output value"
```

### デプロイと実行
ここまでファイルの設定ができたら、実際にデプロイするところまでやってみましょう。

~/go/src/github.com/xxxxx/sls-sample

```
$ make build

go get github.com/aws/aws-lambda-go/lambda
env GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go
env GOOS=linux go build -ldflags="-s -w" -o bin/world world/main.go
```

以下の、`$ sls deploy --aws-profile hoge `
の部分で、はじめに設定したcredentials、configの名前(ここではhoge)を指定して実行してください。

```
$ sls deploy --aws-profile hoge

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (4.5 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
........................
Serverless: Stack update finished...
Service Information
service: hoge
stage: dev
region: ap-northeast-1
stack: hello-dev
api keys:
  None
endpoints:
  None
functions:
  hello: hello-dev-hello
  world: hello-dev-world
```

このような表示になっていればデプロイ成功です！

## まとめ
ここまで意外とすんなりできました。
`aws-go`の他にもたくさんtemplateが用意されているので、他のものにも挑戦してみてもいいですね。

### おまけ
まとめで、templateがたくさんあると記述したものの中身です。

```
 Template "true" is not supported. Supported templates are: "aws-nodejs", "aws-
nodejs-typescript", "aws-nodejs-ecma-script", "aws-python", "aws-python3", "aws-
groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-kotlin-jvm-maven", "aws-
kotlin-jvm-gradle", "aws-kotlin-nodejs-gradle", "aws-scala-sbt", "aws-csharp", 
"aws-fsharp", "aws-go", "aws-go-dep", "azure-nodejs", "fn-nodejs", "fn-go", 
"google-nodejs", "kubeless-python", "kubeless-nodejs", "openwhisk-java-maven", 
"openwhisk-nodejs", "openwhisk-php", "openwhisk-python", "openwhisk-swift", 
"spotinst-nodejs", "spotinst-python", "spotinst-ruby", "spotinst-java8", 
"webtasks-nodejs", "plugin" and "hello-world".
```