LoginSignup
0
0

CloudFormationのOutputsでForEach関数を使う

Last updated at Posted at 2023-11-25

1. はじめに

CloudFormationのOutputsセクションでForEachを使ってサブネットIDをエクスポートするときに、最初うまくいかなかったので備忘録として

2. 何をしたいのか

CloudFormationテンプレートで作成したリソースを他のテンプレートで参照したい場合、参照元のテンプレートのOutputsセクションにリソースを記述すると思います。
その記述をリソースの数が多いと面倒なので、ForEach関数を使ってコードをきれいにしたいと思いました。

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  

# 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]

# Outputs Section
Outputs:
#  VpcId
  SampleVpcId:
    Value: !Ref SampleVpc
    Export:
      Name: !Sub ${System}Vpc-Id

# SubnetId
  'Fn::ForEach::ExportSubnetLoop':
    - ExportSubnetName
    - - SampleSubnet01
      - SampleSubnet02
      - SampleSubnet03
      - SampleSubnet04
      - SampleSubnet05
      - SampleSubnet06
    - '${ExportSubnetName}Id':
         ###↓↓↓ここが誤り↓↓↓###
          Value: !Ref ExportSubnetName
         ###↑↑↑ここが誤り↑↑↑###
          Export: 
            Name: !Sub ${ExportSubnetName}-Id

間違い部分はValue: !Ref ExportSubnetNameとなります。
ForEach関数を使用した場合、Ref関数でExportSubnetNameの値を取得しても、IDを取得できず、スタックの出力結果は下の画像のようになってしまします。
これでは、VPCは参照できますが、サブネットは参照できません。

スクリーンショット 2023-11-25 133019.png

4. ではどうればよいか

# Outputs Section
Outputs:
#  VpcId
  SampleVpcId:
    Value: !Ref SampleVpc
    Export:
      Name: !Sub ${System}Vpc-Id
      
# SubnetId
  'Fn::ForEach::ExportSubnetLoop':
    - ExportSubnetName
    - - SampleSubnet01
      - SampleSubnet02
      - SampleSubnet03
      - SampleSubnet04
      - SampleSubnet05
      - SampleSubnet06
    - '${ExportSubnetName}Id':
          Value: !GetAtt [!Ref ExportSubnetName, SubnetId]
          Export: 
            Name: !Sub ${ExportSubnetName}-Id

Value!GetAttを使って記述します。
こうすればExportSubnetNameのサブネットIDを取得して、値として出力してくれるようになります。

スクリーンショット 2023-11-25 132658.png

5. 終わりに

ForEachを使った場合、Mappingsにパラメータをまとめるので、Resourcesは短くなりますが、Mappingsが以外と長くなります。
ForEachを使ってResourcesを短くしたほうがいいのか、通常どおり書いたほうがいいのかは、人によると思いました。

あと、Transform: AWS::LanguageExtensionsを忘れやすいので、気を付けましょう。

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