AWS CloudFormation の Fn::ForEach に Resources セクションでは使えない文字列を使うとエラーになる
2023.8.24
アップデートについて
2023/Jul/26 に、CloudFormation(以下、CFn と呼ぶ)に待望のループ機能が実装されました。
これにより、今まで必要な数のリソースを同じコードで複製していましたが、「Fn::ForEach」を使用してリソースを記述することが可能になりました。
AWS CloudFormation が Fn::ForEach 組み込み関数によるループ機能を発表しました。Fn:: ForEach を使用すると、最小限のコード行でテンプレートの一部を複製できます。Fn:: ForEach を使用すると、テンプレートのレイアウトを簡略化し、自分や同僚がコードを簡単かつ迅速にレビューできるようになります。
ループ機能で CloudFormation のオーサリング体験を加速させましょう
でた当初は、面白そうなので使ってみましたがとても便利だなと思いました。
正直、CFn はこういったループを出さないと思っていたのでかなり衝撃でした。
ForEach の動作
はじめに、全体構造として以下が今回作成に使用した CFn のテンプレートです。
AWSTemplateFormatVersion: 2010-09-09 Transform: "AWS::LanguageExtensions" Description: IAM User Resources: "Fn::ForEach::HogeLoopName": - UserList - - coldAirflow - nhnTechorus - "User${UserList}": Type: "AWS::IAM::User" Properties: UserName: !Ref UserList
「ForEach」 の使い方はものすごく簡単で、まずは「Transform」として「AWS::LanguageExtensions」を宣言します。
「AWS::LanguageExtensions」とは、CFn によってホストされるマクロです。
簡単に言うと、拡張機能を使えるように宣言しています。
AWS::LanguageExtensions 変換 – AWS CloudFormation
Transform: "AWS::LanguageExtensions"
実際に、ループ機能を使っているのは「Resources」配下になります。
このテンプレートでは、IAM ユーザーを複数作成しています。
Fn::ForEach – AWS CloudFormation
Resources: "Fn::ForEach::HogeLoopName": - UserList - - coldAirflow - nhnTechorus - "User${UserList}": Type: "AWS::IAM::User" Properties: UserName: !Ref UserList
「UserList」にループしたときに使用する各値をリストにします。
今回の場合は、「cold.airflow」と「nhn.techorus」です。
各ループのときに「UserList 変数」に各値が格納されます。
「UserList」を元に、「AWS::IAM::User」で IAM ユーザーを作成しています。
これをデプロイすると実際に実行した場合に内部で処理されたテンプレートを見ることができます。
「.」を使うとエラーになる
では、本題です。
この「ForEach」を使って先程と同じ様に IAM ユーザーを作ろうとしたときに遭遇したエラーです。
以下が、その時に作成したテンプレートです。
AWSTemplateFormatVersion: 2010-09-09 Transform: "AWS::LanguageExtensions" Description: IAM User Resources: "Fn::ForEach::HogeLoopName": - UserList - - cold.Airflow - nhn.Techorus - "User${UserList}": Type: "AWS::IAM::User" Properties: UserName: !Ref UserList
先程のテンプレートと基本的な部分は変わらないですが、「UserList」の各ユーザー名だけ変更しています。
coldAirflow → cold.Airflow
これを実行するとエラーになります。
Transform AWS::LanguageExtensions failed with: OutputKey ‘Usercold.Airflow’ should be alphanumeric. Rollback requested by user.
なぜエラーになるのか
エラーログとタイトルに書いてあるとおりですが、「Resources」に使用できない文字列「.」が含まれておりエラーになってました。
ループされるときに、「Resources」の論理 IDに各変数の名前をつけるようにしています。
そのため、変数が展開されたときにエラーとなります。
"User${UserList}" ↓ 変換される Usercold.Airflow ↓ 実際のテンプレートに変換すると Usercold.Airflow: Type: "AWS::IAM::User" Properties: UserName: cold.Airflow
「Resources」 の論理 ID には、以下制限があります。
論理 ID
論理 ID は英数字(A-Za-z0-9)とし、テンプレート内で一意である必要があります。
リソース – AWS CloudFormation
「ForEach」としては文字列の制限はないですが、ループで各値が展開されたときに各リソース部分で使えないものがでてくる可能性があります。
そのため、変数として変換された場合に使用しても問題ない値を設定する必要があります。
まとめ
好奇心で使ってみたらエラーになってびっくりしました。
基本的な対処方法は、Resources の論理 ID に使えない文字列を使わないことですが、場合によっては使いたいみたいなときは力技でやるしかないのかなと思ってます。
参考記事
リソース – AWS CloudFormation
AWS::LanguageExtensions 変換 – AWS CloudFormation
Fn::ForEach – AWS CloudFormation
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitter2021年新卒入社。インフラエンジニアです。RDBが三度の飯より好きです。 主にデータベースやAWSのサーバレスについて書く予定です。あと寒いのは苦手です。
Recommends
こちらもおすすめ
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16