俺のアウトプット

調べたこと、試したことを書きます

CloudFormationテンプレートの条件関数

組み込み関数の条件関数を利用すると、リソースを柔軟に制御できます。

リソースを制御する大まかな流れは

  1. Parametersセクション
    • パラメータを入力
  2. Conditionsセクション
    • 入力値を評価して条件(論理値)を作成
  3. Resourcesセクション
    • 条件によりリソースを作成
    • 条件によりプロパティを定義
    • 条件によりプロパティ値 A or B を設定

となります。

条件関数

条件関数は全部で5つあります。
よく使うのはFn::IfFn::Equalsです。

条件関数 説明 備考
Fn::If 値の評価 !If [条件, 真の値, 偽の値] プロパティ定義に擬似パラメータAWS::NoValueを使用可能
Fn::Equals 2つの値が等しいかどうかを比較 !Equals [入力パラメータ, 値]
Fn::Not 真偽を反転 !Not [条件]
Fn::And 全ての条件が真かどうか !And [条件1, 条件2, ...] 条件数は2〜10個
Fn::Or いずれかの条件が真かどうか !Or [条件1, 条件2, ...] 条件数は2〜10個

Conditionsセクション

入力パラメータを評価する条件を定義します。
Fn::If以外の条件関数は、Conditionsセクションでしか使用出来ません。

Conditions:
 <論理ID>: 条件関数
 ...

Conditions:
  IsProduction: !Equals [!Ref Env, "production"]
  IsEC2Role: !Not [!Equals [!Ref EC2Role, ""]]
  IsPublic: !Equals [!Ref Scope, "public"]
  ProdAndPub: !And [!Equals [!Ref Env, "production"], !Equals [!Ref Scope, "public"]]
  ProdOrPub: !Or [!Equals [!Ref Env, "production"], !Equals [!Ref Scope, "public"]]

必ず条件関数を使います。下記はエラーになります。

Conditions:
  IsProduction: true

Template format error: Conditions can only be boolean operations on parameters and other conditions

Resourcesセクション

Conditionsセクションで作成した条件を使用してリソースを制御します。

リソース作成

リソースを作成するかどうかは、Conditionプロパティで制御します。条件がの場合はリソースを作成します。

Resources:
  MyEC2:
    Type: AWS::EC2::Instance
    Condition: 条件
    Properties:
      ...

プロパティ定義

プロパティを利用するかどうかは、条件関数Fn::Ifと疑似パラメータAWS::NoValueを使用します。
下記の例は、条件がの場合にロール名を設定、の場合はプロパティを無効(IamInstanceProfile行を削除と同等)にします。

Resources:
  MyEC2:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !If [条件, !Ref ロール名, !Ref "AWS::NoValue"]
      ...

プロパティ値の設定

条件によって値を設定する場合、関数Fn::Ifを使用します。
下記の例は、条件によりインスタンスタイプを変更します。

Resources:
  MyEC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !If [条件, "t2.micro", "t2.nano"]
      ...

Outputsセクション

Conditionプロパティを使用すると出力項目を制御できます。
Fn::If はOutputsセクションでも利用出来ます。

Outputs:
  IsProduction:
    Condition: 条件
    Value: true
  IsEC2Role:
    Value: !If [条件, true, false]

サンプル

条件関数を利用したテンプレートのサンプルです。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Env:
    Type: String
    Default: production
    AllowedValues:
      - development
      - production
    Description: enter the environment name.
  Scope:
    Type: String
    Default: public
    AllowedValues:
      - public
      - private
  EC2Role:
    Type: String
    Description: enter the ec2 role name.
  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
    Description: KeyPair Name
Conditions:
  IsProduction: !Equals [!Ref Env, "production"]
  IsEC2Role: !Not [!Equals [!Ref EC2Role, ""]]
  IsPublic: !Equals [!Ref Scope, "public"]
  ProdAndPub: !And [!Equals [!Ref Env, "production"], !Equals [!Ref Scope, "public"]]
  ProdOrPub: !Or [!Equals [!Ref Env, "production"], !Equals [!Ref Scope, "public"]]
Resources:
  # EC2作成
  MyEC2:
    Type: AWS::EC2::Instance
    Condition: IsPublic
    Properties:
      ImageId: ami-e99f4896
      InstanceType: !If [IsProduction, "t2.micro", "t2.nano"]
      IamInstanceProfile: !If [IsEC2Role, !Ref EC2Role, !Ref "AWS::NoValue"]
      BlockDeviceMappings:
        - DeviceName: '/dev/xvda'
          Ebs:
            VolumeType: 'gp2'
            VolumeSize: 10
      KeyName: !Ref KeyPair
      Tags:
      -
        Key: Name
        Value: !Sub "${AWS::StackName}-${Env}-${Scope}"
Outputs:
  IsProduction:
    Condition: IsProduction
    Value: true
  IsEC2Role:
    Condition: IsEC2Role
    Value: true
  IsPublic:
    Condition: IsPublic
    Value: true
  ProdAndPub:
    Value: !If [ProdAndPub, true, false]
  ProdOrPub:
    Value: !If [ProdOrPub, true, false]

f:id:kitsugi:20180731075537p:plain

参考