背景
- 直近terraformばかり使っていたがCloudFormationを使う機会に恵まれた
- 同じようなリソースの繰り返し記述を前にチェックの大変さを想像し悲しくなる
- ForEach関数でレビューの負荷を下げることができれば嬉しい
- 何番煎じかわからないがこの記事が誰かの役に立つと嬉しい
練習
- VPC2個とそのVPCに紐づくSubnetを2個作る
サンプルコード
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::LanguageExtensions
Mappings:
VpcM:
Vpc01:
Cidr: 10.0.1.0/24
Name: test-vpc-01
Vpc02:
Cidr: 10.0.2.0/24
Name: test-vpc-02
SubnetVpc01M:
Vpc01Prv01:
Cidr: 10.0.1.0/28
Az: ap-northeast-1a
Name: Vpc01Prv01
Vpc01Prv02:
Cidr: 10.0.1.16/28
Az: ap-northeast-1c
Name: Vpc01Prv02
SubnetVpc02M:
Vpc02Prv01:
Cidr: 10.0.2.0/28
Az: ap-northeast-1a
Name: Vpc02Prv01
Vpc02Prv02:
Cidr: "10.0.2.16/28"
Az: "ap-northeast-1c"
Name: Vpc02Prv02
Resources:
# vpc
'Fn::ForEach::VPC':
- VpcName
- [Vpc01, Vpc02]
- '${VpcName}':
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !FindInMap [VpcM, !Ref VpcName, Cidr]
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !FindInMap [VpcM, !Ref VpcName, Name]
# vpc01 subnet
'Fn::ForEach::SubnetVpc1':
- SubnetName
- [Vpc01Prv01, Vpc01Prv02]
- '${SubnetName}':
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !FindInMap [SubnetVpc01M, !Ref SubnetName, Az]
# 修正したいポイント(後述)
VpcId: !Ref Vpc01
CidrBlock: !FindInMap [SubnetVpc01M, !Ref SubnetName, Cidr]
Tags:
- Key: Name
Value: !FindInMap [SubnetVpc01M, !Ref SubnetName, Name]
# vpc02 subnet
'Fn::ForEach::SubnetVpc2':
- SubnetName
- [Vpc02Prv01, Vpc02Prv02]
- '${SubnetName}':
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !FindInMap [SubnetVpc02M, !Ref SubnetName, Az]
# 修正したいポイント(後述)
VpcId: !Ref Vpc02
CidrBlock: !FindInMap [SubnetVpc02M, !Ref SubnetName, Cidr]
Tags:
- Key: Name
Value: !FindInMap [SubnetVpc02M, !Ref SubnetName, Name]
ハマったところ
- 以下エラーによく遭遇。色々確認したが、私の場合100%インデントのミス
Transform AWS::LanguageExtensions failed with: Duplicate key 'Type' when merging keys to parent object in Fn::ForEach. Rollback requested by user.
クリアできなかったところ
- 以下を見る限り[AWS::LanguageExtensions]を使っていれば、Ref関数内でFindMap関数を使用できそうなのだけれども、参照方法がわからず、結果サブネットリソースのVpcIDの参照をハードコードしてしまった(うまくいけばもう少し圧縮できたと思う)