sam-cliのdeployが楽になっていたことに今頃気付く

# はじめに

何だったのかは、ちょっと覚えていないのですが、sam-cliでのデプロイ手順をみて、「あれ？これでデプロイ出来るの？」って思ったのが最初です。
そん時、sam-cliによるデプロイが、以前と比較して格段に楽になっていることを知りました。
でもこのデプロイ方法に変わったバージョンはsam-cli(0.33.1)からでした。（執筆時バージョン0.45.0）
なので「今頃気付く」です。

### この記事について

実際に試してみたい方もいるかもしれないので、SAMのインストールや、ひな型の作成も手順に含んでいます。

### 前提として

デプロイはAWS環境にデプロイしますので、aws configureでIAMユーザの設定を、ローカル環境に設定されていること。
またIAMユーザは、デプロイ等が可能な適切なロールが設定されていること。

```sh
aws configure
  # AWS Access Key ID [None]: ....................
  # AWS Secret Access Key [None]: ........................................
  # Default region name [None]: ap-northeast-1
  # Default output format [None]:
```

今回は、sam-cliはpipenvで管理させているので、pipenvが環境にインストールされていること。

```sh
pipenv --version
  # pipenv, version 2018.11.26
```

# v.0.33.1以前

### sam-cliインストール

```sh
pipenv install aws-sam-cli==0.32.0 --dev
sam --version
  # SAM CLI, version 0.32.0
```

### web-appひな型作成

```sh
sam init --runtime python3.8 -n sam-app -o .
  # Which template source would you like to use?
  #         1 - AWS Quick Start Templates
  #         2 - Custom Template Location
  # Choice: 1
  # 
  # Allow SAM CLI to download AWS-provided quick start templates from Github [Y/n]: Y
  # 
  # AWS quick start application templates:
  #         1 - Hello World Example
  #         2 - EventBridge Hello World
  #         3 - EventBridge App from scratch (100+ Event Schemas)
  # Template selection: 1
  # 
  # -----------------------
  # Generating application:
  # -----------------------
  # Name: sam-app
  # Runtime: python3.8
  # Dependency Manager: pip
  # Application Template: hello-world
  # Output Directory: .
  # 
  # Next steps can be found in the README file at ./sam-app/README.md
```

### デプロイ

```sh
cd sam-app/

aws s3 mb s3://S3_BUCKET_NAME
  # make_bucket: S3_BUCKET_NAME
sam package \
    --s3-bucket S3_BUCKET_NAME \
    --output-template-file packaged.yaml
  # 2020-03-17 08:18:51 Found credentials in shared credentials file: ~/.aws/credentials
  # Uploading to 5ac4597d491dffc68e5a9bbd9ed4a924  847 / 847.0  (100.00%)Successfully packaged artifacts and wrote output template to file packaged.yaml.
  # Execute the following command to deploy the packaged template
  # sam deploy --template-file /home/ec2-user/sam-app/packaged.yaml --stack-name <YOUR STACK NAME>
sam deploy \
    --template-file packaged.yaml \
    --stack-name sam-app \
    --capabilities CAPABILITY_IAM
  # 
  # Waiting for changeset to be created..
  # Waiting for stack create/update to complete
  # Successfully created/updated stack - sam-app
```

- デプロイを行う前に、packageでデプロイするモジュールをS3バケットにアップロードする必要があります。ですので、最初にアップロード先となとなるS3バケットを作成します。（もちろん、既にアップロード先のS3バケットが作成済みの場合は、この手順を不要です。）
- 次にpackageでは、アップロード先のS3バケット名を指定し、S3へアップロードしたオブジェクト情報を packaged.yml に出力します。
- deployでは、その packaged.yml と、スタック名を指定しデプロイを行います。

# v.0.33.1以降

### ecs-cliアップグレード

```sh
pipenv install aws-sam-cli==0.33.1 --dev
sam --version
   # SAM CLI, version 0.33.1
```

### デプロイ

```sh
sam deploy
  # Usage: sam deploy [OPTIONS]
  # Try 'sam deploy --help' for help.
  # 
  # Error: Missing option '--stack-name', 'sam deploy ?guided' can be used to provide and save needed parameters for future deploys.
```

はじめに `--guided` を指定してデプロイのためのパラメータを保存しましょう。

```sh
sam deploy --guided
  # 
  # Configuring SAM deploy
  # ======================
  # 
  #         Looking for samconfig.toml :  Not found
  # 
  #         Setting default arguments for 'sam deploy'
  #         =========================================
  #         Stack Name [sam-app]:
  #         AWS Region [us-east-1]: ap-northeast-1
  #         #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
  #         Confirm changes before deploy [y/N]:
  #         #SAM needs permission to be able to create roles to connect to the resources in your template
  #         Allow SAM CLI IAM role creation [Y/n]:
  #         Save arguments to samconfig.toml [Y/n]:
  # 
  #         Looking for resources needed for deployment: Not found.
  #         Creating the required resources...
  #         Successfully created!
  # 
  #                 Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1gs597e7ulbk8
  #                 A different default S3 bucket can be set in samconfig.toml
  # 
  #         Saved arguments to config file
  #         Running 'sam deploy' for future deployments will use the parameters saved above.
  #         The above parameters can be changed by modifying samconfig.toml
  #         Learn more about samconfig.toml syntax at
  #         https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
  # 
  #         Deploying with following values
  #         ===============================
  #         Stack name                 : sam-app
  #         Region                     : ap-northeast-1
  #         Confirm changeset          : False
  #         Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-1gs597e7ulbk8
  #         Capabilities               : ["CAPABILITY_IAM"]
  #         Parameter overrides        : {}
  # ...
```

**Configuring SAM deploy**の箇所だけちょっと説明します。

- **Stack Name [sam-app]:** CloudFormationのスタック名
- **AWS Region [us-east-1]:** デプロイするリージョン
- **Confirm changes before deploy [y/N]:** デプロイ時に確認を行うかどうか
- **Allow SAM CLI IAM role creation [Y/n]:** IAMロールの作成を許可するか
- **Save arguments to samconfig.toml [Y/n]:** samconfig.tomlにこれらを保存するか

となります。

以前のsam-cliのバージョンに比べて、手間がずいぶん減っていることがわかります。
パッケージをアップロードするためのバケットの作成も不要ですし、そのS3バケットへオブジェクトをアップロードするための手順も省かれています。
また、package、deployをする際に指定する必要があったオプションについても、省かれています。

勿論、次のデプロイからは

```sh
sam deploy
```
でデプロイ可能になります。

### 変わったのは手順だけ

かといって、内部的に全体の手順が変わっていることはありません。
現バージョンにおいても、以前のデプロイ方法でデプロイすることも可能です。

デプロイの中で、アップロードするためのS3バケットは、`--guided`オプション指定時にログを追えばわかりますが、途中で作成しています。
初回だと *Looking for resources needed for deployment: Not found.* とのメッセージが出力されていると思います。
これは、**aws-sam-cli-managed-default**というスタックがあるかどうかを確認してします。
この**aws-sam-cli-managed-default**スタックがない場合には、このスタック名でS3バケットを作成してます。

[このあたり](https://github.com/awslabs/aws-sam-cli/blob/c8642d25896cf1dff0f904679e7f7557563b325d/samcli/lib/bootstrap/bootstrap.py#L43-L50)で、aws-sam-cli-managed-defaultスタックが作成済みかの判定をしています。
ですので、同一リージョンであれば、**aws-sam-cli-managed-default**スタックで作成したS3バケットに、オブジェクトをアップロードします。

初回deploy時には、このバケット名、アプリのスタック名等を **samconfig.toml**に出力するかの確認（デフォルトでYes）があります。ここで**samconfig.toml**を作成することで、次回からは、このファイルを参照することで、`--guided` オプションを省き deploy することが可能になります。

# さいごに

Serverless Frameworkでは `sls deploy` 一発でデプロイが可能です。
それと比べて、SAMでは一発でデプロイ出来ない面倒さを感じていましたが、SAMも随分使いやすくなってますよ。

という話でした:robot: