背景
AWS使ってサーバーレスで自分用の家計簿的なwebサービスを勉強も兼ねて開発中。基本的にAWSリソースはCloudFormationで管理中。AWS Amplify使えばいいんじゃね?という話もあるけど、AWSの勉強兼ねてるので、はい。
やりたかった事
既存テーブルにレンジキーを追加したい。 はい、普通でもテーブル削除&再作成が必要な処理です。この時、このテーブルにデータは存在していないので新規キーに対する値不整合問題は無し。
とりあえずやってみた。
CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename {対象テーブル名} and update the stack again.
カスタム名があるスタックで(更新でなく)交換が必要なリソースはCloudFormationでは更新できないという事ですね。
リネームせよと言ってるけど、DynamoDBのテーブル名は後から変えられない。
一旦手動でテーブル消してみる。
こうすれば再作成されるだろう、と期待。が、同じエラー。
真面目に対応すべく、検索して出てきた公式ページが以下リンク。
AWS CloudFormation の「Cannot update a stack when a custom-named resource requires replacing」エラーを解決する方法を教えてください。
カスタム名を変える必要があるらしい。上記リンクから辿った以下リンクによると、DynamoDBのカスタム名はTableNameプロパティらしい。ってそこ変えられないんですが。すでに実リソースは削除してるし。
Name タイプ
※CloudFormationで作成されたリソースはAWSコンソールで変更しちゃ駄目って書いてありますね。でもCloudFormationで更新できなかったのですYo。
考察
CloudFormationで識別に使われてそうな名前らしき所は、CloudFormation内スタック識別子(というのか? yamlだと第二インデント部分。)。
Resources:
# 中略 #
{ここで指定している名称}:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: "hogehoge_table"
AttributeDefinitions:
- AttributeName: "tgt_date"
AttributeType: "S"
KeySchema:
- AttributeName: "tgt_date"
KeyType: HASH
BillingMode: PAY_PER_REQUEST
# 後略 #
ここを適当に別名にしてCloudFormation更新してみる。AWSでのコンソール更新時に表示される変更セットのプレビューでは、先ほど変更した箇所で、新しいの追加+古いの削除の動作をする様子。が、テーブル名は変えてなかったので、新しいのを追加する部分で失敗。
ダミーの別テーブル作るのも微妙。追加で失敗するなら、一旦該当ブロックを消した状態で更新してみる。対象テーブル削除した状態だし、現状と一致してる。更新しようとした時の変更セットのプレビューでは、古いのを削除のみ。そして更新成功。実テーブルが削除されてるが、それに関わるエラーは無かった模様。
そして、本来更新したかった元のCloudFormationで実行。無事に新テーブルとして作成されました。
まとめ
DynamoDBのキー構造変更のような、本来でも再作成が必要なリソース更新の場合、手動でやるのと同様にしましょう。公式ページに書かれている、CloudFormationで作成されたリソースはCloudFormationで更新して というのはこういう意味だったのだと思います。
- CloudFormationのTemplateからそのリソース定義を一旦消す
- (もしそのリソースIDを別の所で使用していたら、一旦現状固定値指定。多分。※未検証)
- CloudFormationを一時変更Templateで更新
- CloudFormationのTemplateに新規設定のリソース定義追加
- CloudFormationを新Templateで更新