CloudFormationのFn::ForEachを使う
はじめに
今更だけど初めてForEachを使ったのでメモ
複数のIAMユーザーを作りたいときにForEachが便利
ForEach
昨年の7月にFn::ForEach
が追加された。
以前は繰り替えし処理はできなかったので、このアップデートが追加されたときにはタイムラインが少しだけ盛り上がってた気がする。
基本的な使い方
以下の資料がわかりやすい。
構文が見慣れないので、こういうものと受け入れて使っていくとよさそう。
AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::LanguageExtensions'
Resources:
'Fn::ForEach::UserLoop':
- Name
- - Alice
- Bob
- Charlie
- 'User${Name}':
Type: 'AWS::IAM::User'
DeletionPolicy: Delete
Properties:
UserName: !Sub '${Name}-${AWS::AccountId}'
デプロイするとちゃんと意図通り3人分のIAMユーザーが作成された。
ForEachは以下のような構文で構成されている
'Fn::ForEach::UniqueLoopName':
- Identifier
- - Value1 # Collection
- Value2
- 'OutputKey':
OutputValue
意味は以下の通りだが、公式ドキュメントの悪い部分が出いている。(参照)
UniqueLoopName
このループの名前。名前はテンプレート内で一意である必要があり、テンプレートの Resources セクションのどの論理 ID 値とも競合できません。この名前は変換された出力には含まれません。
Identifier
複製されたテンプレートフラグメントを表す、OutputKey と OutputValue パラメーターで置き換える識別子。OutputKey と OutputValue パラメータにある ${Identifier} または &{Identifier} のすべてのインスタンスは、Collection パラメータの値に置き換えられます。
Collection
反復処理の対象となる値のコレクション。このパラメーターの配列または Ref に対する CommaDelimitedList の場合があります。&{Identifier} を使用すると、英数字以外の文字を Collection に渡すことができます。
OutputKey
変換されたテンプレートのキー。${Identifier} または &{Identifier} が OutputKey パラメータに含まれている必要があります。たとえば、テンプレートの Resources セクションで Fn::ForEach が使用されている場合、これは各リソースの論理 ID です。
&{} 構文では、OutputKey パラメータで使用する Collection に英数字以外の文字を使用できます。
OutputValue
Collection パラメータの各項目に変換されたテンプレートで複製される値。たとえば、Fn::ForEach をテンプレートの Resources セクションで使用する場合、これは各リソースを設定するために繰り返されるテンプレートフラグメントです。
これもわかりやすいわけではないけども、自分は以下のように理解している。
- UniqueLoopName
- ユニークであれば何でもいい。これ自体を
!Ref
などで参照することもないと思っている
- ユニークであれば何でもいい。これ自体を
- Identifier
- ForEach内で参照するために使う
-
${Identifieer}
は後述するOutputValue
内で参照される
-
- ForEach内で参照するために使う
- Collection
- 繰り替えしたい要素のリスト
- 上記のようなフロースタイルでも
[Alice, Bob, Charlie]
のようなブロックスタイルでもいい - よく見るのがCloudFormationの
Parameters
をCommaDelimitedList
にするやつ
- 上記のようなフロースタイルでも
- 参考:SNSリソースの複製
- 繰り替えしたい要素のリスト
- OutputKey
- CloudFormation上の論理IDになる。したがってユニークである必要がある。
-
${Identifier}
を含む必要がある
- OutputValue
- 繰り返し処理を行う場所。
${Identifier}
を使うことでリストの要素を処理できる。
- 繰り返し処理を行う場所。
ユーザーごとにIAMユーザーを2個作る
若干特殊な場合だと思うけども、1ユーザごとに用途が異なるIAMユーザーを作成する。(CLIやデプロイ用のものと、モバイル用のConsoleログイン用。自分の管理下にIICがないのでこういう感じになった)
Fn::ForEach
では、Multiple key-value pairs
を記載できるので以下のような形式になる。
最初はそんな書き方できること知らなかったけども、公式ドキュメントのサンプルにもあるFn::ForEach
を入れ子してるのと同じことなのかもしれない。
yamlのアンカー・エイリアスでなんとかできるのかと思ってたけども、CloudFormationが対応していないらしい。
AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::LanguageExtensions'
Resources:
'Fn::ForEach::UserLoop':
- Name
- - Alice
- Bob
- Charlie
- 'User${Name}':
Type: 'AWS::IAM::User'
DeletionPolicy: Delete
Properties:
UserName: !Sub 'User-${Name}-${AWS::AccountId}'
'Console${Name}':
Type: 'AWS::IAM::User'
DeletionPolicy: Delete
Properties:
UserName: !Sub 'Console-${Name}-${AWS::AccountId}'
実行すると意図通りのユーザーが作成される
以下、参考
入れ子にしたFn::ForEach
サンプルの通り、Fn::ForEach
は入れ子にできるので、先ほどの例は以下のように書き換えることができる。
この場合はOutputKey
に${Identifier}
を含まなくていいらしい
AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::LanguageExtensions'
Resources:
'Fn::ForEach::TypeLoop':
- UseType
- - User
- Console
- 'Fn::ForEach::UserLoop':
- Name
- - Alice
- Bob
- Charlie
- '${UseType}${Name}':
Type: 'AWS::IAM::User'
DeletionPolicy: Delete
Properties:
UserName: !Sub '${UseType}-${Name}-${AWS::AccountId}'
同じものができている。(内容同じなので画像は使いまわし。。。)
おわりに
こういう繰り返しはCDKのほうがまぁ楽ではあるけども、CDKをデプロイする用のIAMユーザーとかはCloudFormationでデプロイするようにしているので、Fn::ForEach
に多少慣れた気がする。
Discussion