DynamoDB Localでテーブル作成できなくて少しハマった話

# 経緯

個人的に、サーバレスでアプリ作りたくて、AWS SAMとDynamoDB Localで試作してた。



以下のページが参考になった。
[aws-sam-cliでLambda,DynamoDBのサーバーレスアプリケーション開発に入門してみる](https://qiita.com/umeneri/items/6fb3f7560f4a878f6dfd)

# エラー内容

テーブル定義をjsonで作成して、aws cliでコマンド実行したらエラーで作れない。

```bash
$ aws dynamodb create-table --cli-input-json file://table/test-table.json --endpoint-url http://127.0.0.1:8000 --region ap-northeast-1

An error occurred (ValidationException) when calling the CreateTable operation: No provisioned throughput specified for the table
```

json定義はこんな感じ。

```json
{
	"AttributeDefinitions": [
		{
			"AttributeName": "name",
			"AttributeType": "S"
		},
		{
			"AttributeName": "time",
			"AttributeType": "S"
		}
	],
	"TableName": "test-table",
	"KeySchema": [
		{
			"AttributeName": "name",
			"KeyType": "HASH"
		},
		{
			"AttributeName": "time",
			"KeyType": "RANGE"
		}
	]
}
```

# 結論

`billing-mode`オプションで`PAY_PER_REQUEST`を指定すれば作れた。

```bash
$ aws dynamodb create-table --cli-input-json file://table/test-table.json --endpoint-url http://127.0.0.1:8000 --region ap-northeast-1 --billing-mode PAY_PER_REQUEST

$ aws dynamodb list-tables --endpoint-url http://127.0.0.1:8000  --region ap-northeast-1
{
    "TableNames": [
        "test-table"
    ]
}
```
# あとは余談

## 紆余曲折

- エラーMSGでググったけど、それっぽい解が出てこない。

- AWS CLIの[ドキュメント](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html)で、必須項目は「attribute」「table-name」「key-schema」で足りてるっぽい。

- jsonがどこか間違ってるのかなと思って、以下のコマンドでテンプレート生成して作り直したけど一緒。

  ```bash
  aws dynamodb create-table --generate-cli-skeleton > table-template.json
  ```

- エラーをもう一回読んで、google翻訳してみる。  
  「No provisioned throughput specified for the table」  
  「テーブルにプロビジョニングされたスループットが指定されていません」  
  なるほど。完全に？理解した！

## 結局

改めてAWS CLIのcreate-tableの[ドキュメント](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html)を見てみると

> --provisioned-throughput
>
> > Represents the provisioned throughput settings for a specified table or index. The settings can be modified using the `UpdateTable` operation.
> > If you set BillingMode as `PROVISIONED` , you must specify this property. If you set BillingMode as `PAY_PER_REQUEST` , you cannot specify this property.
> > For current minimum and maximum provisioned throughput values, see [Limits](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) in the *Amazon DynamoDB Developer Guide* .

BillingModeを`PROVISIONED`に設定した場合、このプロパティを指定する必要があります。BillingModeを`PAY_PER_REQUEST`に設定した場合、このプロパティは指定できません。

> --billing-mode
>
> > Controls how you are charged for read and write throughput and how you manage capacity. This setting can be changed later.
> >
> > - `PROVISIONED` - We recommend using `PROVISIONED` for predictable workloads. `PROVISIONED` sets the billing mode to [Provisioned Mode](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual) .
> > - `PAY_PER_REQUEST` - We recommend using `PAY_PER_REQUEST` for unpredictable workloads. `PAY_PER_REQUEST` sets the billing mode to [On-Demand Mode](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand) .
> >   Possible values:
> > - `PROVISIONED`
> > - `PAY_PER_REQUEST`

- `PROVISIONED-`予測可能なワークロードには` PROVISIONED`を使用することをお勧めします。`PROVISIONED`は、請求モードを[ Provisioned Modeに](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual)設定し[ます](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual)。
- `PAY_PER_REQUEST-`予測不能なワークロードには` PAY_PER_REQUEST`を使用することをお勧めします。`PAY_PER_REQUEST`は、請求モードを[オンデマンドモードに設定します](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand)。

**これデフォルトがプロビジョンドで、オンデマンドにするには指定しないといけない？**（書いてないけど）

で解決した。

## 所感？

- エラーもっとよく読めばすぐ分かったかも。。
- デフォルトがPROVISIONEDなのはAPIの[ドキュメント](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/APIReference/API_CreateTable.html#DDB-CreateTable-request-BillingMode)見ても書いてなかった。  
  ※オンデマンドができたの後になってからってのもあるかもしれないけど、  
 「ProvisionedThroughput」は「Required: No」ってなってるからメンテされてないって訳ではなさそう。
- CloudFormationの[ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)には書いてあった。 
  ※話がそれるけど、CloudFormationのドキュメントは
  　英語版は「Default: false」で、日本語版は「デフォルト: true」ってなってる事あるから注意！
  　（マジでやめてほしい。気づいたらサポートに言ってるけど。）

- 実際のAWS環境で試してみるために、`endpoint-url`オプション外して実行するとこんなエラーが……


  ```bash
  $ aws dynamodb create-table --cli-input-json file://table/test-table.json --region ap-northeast-1 
  
  An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: ReadCapacityUnits and WriteCapacityUnits must both be specified when BillingMode is PROVISIONED
  ``` 

  BillingModeがPROVISIONEDだとCapacityUnitsを指定しないといけないよと。
  なんでLocalは出ないの。。（そしてやっぱりデフォルトはPROVISIONEDだ）

- でも実際のAWS環境であっても、**一瞬でテーブル作れたのは感動した。**すげー

  ```bash
  $ date ; \
  > aws dynamodb create-table --cli-input-json file://table/test-table.json --region ap-northeast-1 --billing-mode PAY_PER_REQUEST 1>/dev/null ; \
  > aws dynamodb list-tables  --region ap-northeast-1 ; \
  > date
  2019年 11月 30日 土曜日 16:31:24 JST
  {
      "TableNames": [
          "test-table"
      ]
  }
  2019年 11月 30日 土曜日 16:31:35 JST
  ```

おわり