AWS SAMでdynamoのリソースを変更するときにエラーになった

lambda + Dynamo DBのサーバーレスなWeb APIを開発しています。インフラ構築は勉強を兼ねてAWS SAMを利用。
テンプレート上でDynamoの定義変更を行いデプロイしたところ、以下のエラーが発生。

```
CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename FugaDynamoDBTable and update the stack again.
```

一度テンプレート上で削除してからデプロイ、さらに再び構築するとうまくいきました。以下その過程です。

# やりたかったこと & エラー

開発中、DynamoのGSIを貼り直したくなった。テンプレートで定義し直しデプロイするとまるっとリプレイスされるが、該当テーブルには手動で入れたテストデータしかなかったので問題無し。

```yaml:template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  HogeFunction:
    Type: AWS::Serverless::Function 
    Properties: #中略
  FugaDynamoDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
        TableName: FugaTable
        GlobalSecondaryIndexes: # ←ここに変更を加えた
#以下略
```

`sam build` → `sam deploy` と打ち、出力を観察。

```
CloudFormation stack changeset (抜粋)
---------------------------------------------------------------------------------------------
Operation       LogicalResourceId         ResourceType                  Replacement       
---------------------------------------------------------------------------------------------
* Modify        FugaDynamoDBTable        AWS::DynamoDB::Table           True     
   :                   :                          :                      :
```

ReplacementがTrueで問題ないので、そのままデプロイしたところ、該当のDynamoのアップデートに以下のエラーが発生しロールバックが実行された。

```
CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename FugaDynamoDBTable and update the stack again.
```

# 対応
エラーメッセージはテーブル名 (`FugaTable`)を変更するように言っている。しかしテーブル名は変えたくない。

[AWS CloudFormation > ユーザーガイド > スタックのリソースの更新動作](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html)によると、リプレイスは置換リソースを作ってから古いリソースを削除するらしい。そこで「名前が被っているのが悪いのかな」と考え、**Dynamo DBのwebコンソールから手動で削除し、再デプロイ。しかし結果は変わらず。**

リソース名(`FugaDynamoDBTable`)を変えれば新設リソースと見做されそうな気もするが、なんか気持ち悪い。

同じくユーザーガイドの[Name タイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-name.html)に

>スタックリソースの変更を AWS CloudFormation 以外で行うことも避けてください。たとえば、スタックに属しているリソースの名前を AWS CloudFormation を使用せずに変更した場合、そのスタックを更新または削除しようとしたときにエラーが発生します。

との記述を発見(ごめんなさい)。

ではテンプレート上でも無かったことにして実態に合わせようと、`FugaDynamoDBTable`の定義を**丸々コメントアウトし再度デプロイ。**

```
CloudFormation stack changeset
------------------------------------------------------------------------------
Operation       LogicalResourceId      ResourceType               Replacement
------------------------------------------------------------------------------
- Delete        FugaDynamoDBTable      AWS::DynamoDB::Table       N/A        
```

と確認され実行。特にエラーなく削除されたことになった。

**再び該当部分をコメントインしデプロイ。**

```
CloudFormation stack changeset
-----------------------------------------------------------------------------------
Operation        LogicalResourceId       ResourceType               Replacement   
-----------------------------------------------------------------------------------
+ Add            FugaDynamoDBTable       AWS::DynamoDB::Table       N/A           
```

意図通りのchangesetになったのでそのまま実行。無事にデプロイ:tada:。コンソール上でも意図した設定になっていることを確認できた。

## 追記
約1年前に全く同じ問題で全く同じ過程を辿った方がいた。SAMでハマったらCloudFormationの情報もちゃんと探すべきか。
[CloudFormation内のDynamoDBリソース更新でハマった話](https://qiita.com/silverbox/items/5d4bef786c4173c00b15)