0
0

CloudFormationのForEach関数内でテンプレート内のリソースを参照する

Posted at

1. はじめに

CloudFormationのForEach関数を使用してリソースを作成する際に、テンプレート内のリソースを参照する方法でハマったので、備忘録として記録

2. 何をしたいのか

通常CloudFormationテンプレート内でリソースを参照するときは、

!Ref SampleVPC

のようにRef関数を使用すればいいが、ForEach関数を使用して作成リソースごとに参照するリソースを分ける場合は、!Ref SampleVPCこのような参照方法が使えません。
今回はAWS::EC2::SubnetRouteTableAssociationの中で、テンプレート内のサブネットとルートテーブルを参照したいと思います。

3. テンプレート

AWSTemplateFormatVersion: 2010-09-09
Description: Create VPC, Subent
Transform: AWS::LanguageExtensions

# Parameters Section
Parameters:
  System:
    Type: String
    Default: Sample
  VpcCidr:  
    Type: String
    Default: 10.0.0.0/24

# Mappings Section
Mappings:
  # SubnetMappings
  SubnetMappings:
    SampleSubnet01:
      Cidr: 10.0.0.0/27
      Az: ap-northeast-1c
      Number: 01
    SampleSubnet02:
      Cidr:  10.0.0.32/27
      Az: ap-northeast-1a
      Number: 02
    SampleSubnet03:
      Cidr: 10.0.0.64/27
      Az: ap-northeast-1c
      Number: 03
    SampleSubnet04:
      Cidr: 10.0.0.96/27 
      Az: ap-northeast-1a
      Number: 04
    SampleSubnet05:
      Cidr: 10.0.0.128/27
      Az: ap-northeast-1c
      Number: 05
    SampleSubnet06:
      Cidr: 10.0.0.160/27
      Az: ap-northeast-1a
      Number: 06
  # RouteTableMappings
  RouteTableMappings:
    SampleRouteTable01:
      Number: 01
    SampleRouteTable02:
      Number: 02
    SampleRouteTable03:
      Number: 03
  # RtbAssociationMappings
  RtbAssociationMappings:
    SampleRtbAssociation01:
      RouteTable: SampleRouteTable01
      Subnet: SampleSubnet01
    SampleRtbAssociation02:
      RouteTable: SampleRouteTable01
      Subnet: SampleSubnet02
    SampleRtbAssociation03:
      RouteTable: SampleRouteTable02
      Subnet: SampleSubnet03
    SampleRtbAssociation04:
      RouteTable: SampleRouteTable02
      Subnet: SampleSubnet04
    SampleRtbAssociation05:
      RouteTable: SampleRouteTable03
      Subnet: SampleSubnet05
    SampleRtbAssociation06:
      RouteTable: SampleRouteTable03
      Subnet: SampleSubnet06

# Resources Section
Resources:
# Sample Prd Vpc
  SampleVpc:
    Type: AWS::EC2::VPC
    Properties: 
      CidrBlock:  !Ref VpcCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub ${System}-vpc

# Subnet
# Private Subnets
  'Fn::ForEach::SubnetLoop':
    - SubnetName
    - - SampleSubnet01
      - SampleSubnet02
      - SampleSubnet03
      - SampleSubnet04
      - SampleSubnet05
      - SampleSubnet06
    - '${SubnetName}':
        Type: AWS::EC2::Subnet
        Properties:
          AvailabilityZone: !FindInMap [SubnetMappings, !Ref SubnetName, Az]
          CidrBlock: !FindInMap [SubnetMappings, !Ref SubnetName, Cidr]
          VpcId: !Ref SampleVpc
          Tags:
            - Key: Name
              Value: !Sub 
                - ${System}-subnet-${SubnetNumber}
                - SubnetNumber: !FindInMap [SubnetMappings, !Ref SubnetName, Number]

# 3 RouteTables
  'Fn::ForEach::RouteTableLoop':
    - RouteTableName
    - - SampleRouteTable01
      - SampleRouteTable02
      - SampleRouteTable03
    - '${RouteTableName}':
        Type: AWS::EC2::RouteTable
        Properties:
          VpcId: !Ref SampleVpc
          Tags:
            - Key: Name
              Value: !Sub 
                - ${System}-rtb-${RouteTableNumber}
                - RouteTableNumber: !FindInMap [RouteTableMappings, !Ref RouteTableName, Number]

# 6 RouteTable Association
  'Fn::ForEach::RtbAssociationLoop':
    - RtbAssociationName
    - - SampleRtbAssociation01
      - SampleRtbAssociation02
      - SampleRtbAssociation03
      - SampleRtbAssociation04
      - SampleRtbAssociation05
      - SampleRtbAssociation06
    - '${RtbAssociationName}':
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
        ### ↓↓↓ ハマったところ ↓↓↓
          RouteTableId: !GetAtt [!FindInMap [RtbAssociationMappings, !Ref RtbAssociationName, RouteTable], RouteTableId]
          SubnetId: !GetAtt [!FindInMap [RtbAssociationMappings, !Ref RtbAssociationName, Subnet], SubnetId]

4. ハマったところ

マッピングセクションからルートテーブルやサブネットの論理IDを参照するだけではうまくいかなかった。
そのため、GetAtt関数を使用し、その中でFindInMapで参照したルートテーブル(サブネット)名のIDを取得したことでうまくできた。
なお、ここの記述方法は以下でも可

Properties:
  RouteTableId: !GetAtt
    - !FindInMap [RtbAssociationMappings, !Ref RtbAssociationName, RouteTable]
    - RouteTableId
  SubnetId: !GetAtt
    - !FindInMap [RtbAssociationMappings, !Ref RtbAssociationName, Subnet]
    - SubnetId

5. おわりに

当たり前だが、やはりMappingsが長くなった。
今回はサブネットが6つなので、楽でしたが。

関数の中に関数を書いて、さらにその中に関数を書くと、記述方法がわからなくなってくるので、慣れていきたいと思いました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0