AWS SAMでデプロイする　RubyでLambda実行

[AWS saｍの環境構築 RubyでLambda実行](https://qiita.com/kon_yu/items/753f9ea70802fec590d6)の続き、ローカル環境でsamを使ってWebAPIのサンプルとテストの実行をRubyで行った。今回はデプロイしてAWSの環境で動かす。

[Quick Start - AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-quick-start.html)

Package the Applicationのあたりから


## デプロイ用のS3バケットを作成する

デプロイするにはそのままLambdaを展開するのではなくて、一旦s3のバケットにアップロードする必要がある。


```
> aws s3 mb s3://適当なバケット
make_bucket: 適当なバケット

# lsでバケットを確認してみる
> aws s3 ls
2019-02-XX XX:XX:XX 適当なバケット
```

心配だったのでAWSのコンソールでも確認してみたところ、バケットが作成されていることも確認した。

## パッケージをS3にアップロードする

下記のコマンドを実行するとpackaged artifacts(多分Lambdaのコードとかライブラリも？zipで固めたもの)がs3にアップロードされて、ローカルにはpackaged.yamlが作成された

```
> sam package \
    --output-template-file packaged.yaml \
    --s3-bucket 適当なバケット

Uploading to 818f0d274293fec4b3580cc9b3a0c6e0  643563 / 643563.0  (100.00%)
Successfully packaged artifacts and wrote output template to file packaged.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /Users/kon_yu/devlopment/sam_sample/sam-app/packaged.yaml --stack-name <YOUR STACK NAME>
```

packaged.yamlの中身を見るとCloudformationのファイルがある。
HelloWorldFunctionRoleというIAMロールがついている。

```
AWSTemplateFormatVersion: '2010-09-09'
Description: 'sam-app

  Sample SAM Template for sam-app

  '
Globals:
  Function:
    Timeout: 3
Outputs:
  HelloWorldApi:
    Description: API Gateway endpoint URL for Prod stage for Hello World function
    Value:
      Fn::Sub: https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/
  HelloWorldFunction:
    Description: Hello World Lambda Function ARN
    Value:
      Fn::GetAtt:
      - HelloWorldFunction
      - Arn
  HelloWorldFunctionIamRole:
    Description: Implicit IAM Role created for Hello World function
    Value:
      Fn::GetAtt:
      - HelloWorldFunctionRole
      - Arn
Resources:
  HelloWorldFunction:
    Properties:
      CodeUri: s3://適当なバケット/818f0d274293fec4b3580cc9b3a0c6e0
      Environment:
        Variables:
          PARAM1: VALUE
      Events:
        HelloWorld:
          Properties:
            Method: get
            Path: /hello
          Type: Api
      Handler: app.lambda_handler
      Runtime: ruby2.5
    Type: AWS::Serverless::Function
Transform: AWS::Serverless-2016-10-31
```


## デプロイ

```
sam deploy \
    --template-file packaged.yaml \
    --stack-name sam-app \
    --capabilities CAPABILITY_IAM \
    --region ap-northeast-1
```

--template-fileで読み込むcloudformationのテンプレートファイル(packaged.yaml)を指定
--stack-nameでcloudformationのスタック(sam-app)を指定
--capabilities CAPABILITY_IAMをオプションで付けるとIAMロールを作ってくれる。このIAMロールがlambdaの実行ロールに指定される
-- regionで東京リージョンを指定(ap-northeast-1)

## 動作確認
AWSコンソールからCloudformationを開いて、先ほど作成したsam-appのスタックを選択し下の方にある「出力」のタブを開くと
HelloWorldApiのエンドポイントが値にURLが格納されている。このURLをブラウザで開けば動作確認ができる。

Gemfileで規定したライブラリは、S3にアップロードされた中身は
sam buildでビルドして生成された.aws-sam/build/HelloWorldFunctionの中身のようだった。

```
Archive:  818f0d274293fec4b3580cc9b3a0c6e0
  inflating: app.rb
  inflating: Gemfile
  inflating: Gemfile.lock
  inflating: .bundle/config
  inflating: vendor/bundle/ruby/2.5.0/specifications/mime-types-3.2.2.gemspec
  inflating: vendor/bundle/ruby/2.5.0/specifications/httparty-0.16.3.gemspec
  inflating: vendor/bundle/ruby/2.5.0/specifications/multi_xml-0.6.0.gemspec
  inflating: vendor/bundle/ruby/2.5.0/cache/mime-types-data-3.2018.0812.gem
  inflating: vendor/bundle/ruby/2.5.0/bin/httparty
  inflating: vendor/bundle/ruby/2.5.0/gems/httparty-0.16.3/cucumber.yml
  inflating: vendor/bundle/ruby/2.5.0/gems/httparty-0.16.3/.rubocop_todo.yml
```

## デプロイされている内容をAWSコンソールから確認
ブラウザを開いてAWSのコンソールから東京リージョンを選ぶ
AWSのコンソールでLambdaを開くと
lambdaが作られたことがわかる。

またCloudformation削除してデプロイし直すとURLが変わるようだ。

例えばこんな感じ
* 1回目のデプロイ: https://hboimeyaht4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
* 2回目のデプロイ: https://8y2few5qxf.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/


#### 今後の課題

* もう一つ自前でAPI Gatewayのエンドポイントとそれに紐づくLambdaを作成する
* DynamoDBにデータを挿入する、データ取得するエンドポイントを作る
  * その際にLambda Layersを適用してみる
* デプロイ時の名前解決の問題

-------
参考情報
[本当にLambda Layersで幸せになれるのか？ 旧式のデプロイ方式からLambda Layersを活用したデプロイ方式への移行を検討する ｜ DevelopersIO](https://dev.classmethod.jp/server-side/serverless/migrate-to-lambda-layers/)
[AWS SAMでAPI Gatewayのリソースポリシーを設定してみた ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/sam_apig_resource_policy/)